1   /*
2    * Copyright 2000-2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.wsrp4j.producer.driver;
18  
19  import java.rmi.RemoteException;
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.Iterator;
23  
24  import javax.servlet.http.HttpServletRequest;
25  import javax.servlet.http.HttpSession;
26  
27  import oasis.names.tc.wsrp.v1.types.BlockingInteractionResponse;
28  import oasis.names.tc.wsrp.v1.types.ClonePortlet;
29  import oasis.names.tc.wsrp.v1.types.DestroyFailed;
30  import oasis.names.tc.wsrp.v1.types.DestroyPortlets;
31  import oasis.names.tc.wsrp.v1.types.DestroyPortletsResponse;
32  import oasis.names.tc.wsrp.v1.types.GetMarkup;
33  import oasis.names.tc.wsrp.v1.types.GetPortletDescription;
34  import oasis.names.tc.wsrp.v1.types.GetPortletProperties;
35  import oasis.names.tc.wsrp.v1.types.GetPortletPropertyDescription;
36  import oasis.names.tc.wsrp.v1.types.GetServiceDescription;
37  import oasis.names.tc.wsrp.v1.types.InitCookie;
38  import oasis.names.tc.wsrp.v1.types.MarkupParams;
39  import oasis.names.tc.wsrp.v1.types.MarkupResponse;
40  import oasis.names.tc.wsrp.v1.types.MarkupType;
41  import oasis.names.tc.wsrp.v1.types.MissingParametersFault;
42  import oasis.names.tc.wsrp.v1.types.ModifyRegistration;
43  import oasis.names.tc.wsrp.v1.types.PerformBlockingInteraction;
44  import oasis.names.tc.wsrp.v1.types.PortletContext;
45  import oasis.names.tc.wsrp.v1.types.PortletDescription;
46  import oasis.names.tc.wsrp.v1.types.PortletDescriptionResponse;
47  import oasis.names.tc.wsrp.v1.types.PortletPropertyDescriptionResponse;
48  import oasis.names.tc.wsrp.v1.types.PropertyList;
49  import oasis.names.tc.wsrp.v1.types.RegistrationContext;
50  import oasis.names.tc.wsrp.v1.types.RegistrationData;
51  import oasis.names.tc.wsrp.v1.types.RegistrationState;
52  import oasis.names.tc.wsrp.v1.types.ReleaseSessions;
53  import oasis.names.tc.wsrp.v1.types.ReturnAny;
54  import oasis.names.tc.wsrp.v1.types.ServiceDescription;
55  import oasis.names.tc.wsrp.v1.types.SetPortletProperties;
56  import oasis.names.tc.wsrp.v1.types.StateChange;
57  
58  import org.apache.axis.AxisEngine;
59  import org.apache.axis.MessageContext;
60  import org.apache.axis.transport.http.HTTPConstants;
61  import org.apache.wsrp4j.exception.ErrorCodes;
62  import org.apache.wsrp4j.exception.WSRPException;
63  import org.apache.wsrp4j.exception.WSRPXHelper;
64  import org.apache.wsrp4j.log.LogManager;
65  import org.apache.wsrp4j.log.Logger;
66  import org.apache.wsrp4j.producer.ConsumerRegistry;
67  import org.apache.wsrp4j.producer.ConsumerRegistryAccess;
68  import org.apache.wsrp4j.producer.ProviderAccess;
69  import org.apache.wsrp4j.producer.Registration;
70  import org.apache.wsrp4j.producer.provider.ConsumerConfiguredPortlet;
71  import org.apache.wsrp4j.producer.provider.DescriptionHandler;
72  import org.apache.wsrp4j.producer.provider.Portlet;
73  import org.apache.wsrp4j.producer.provider.PortletStateManager;
74  import org.apache.wsrp4j.producer.provider.ProducerOfferedPortlet;
75  import org.apache.wsrp4j.producer.provider.Provider;
76  import org.apache.wsrp4j.util.Constants;
77  import org.apache.wsrp4j.util.LocaleHelper;
78  import org.apache.wsrp4j.util.ParameterChecker;
79  
80  /**
81   * <p>Implements the WSRP-interfaces:
82   * <ul>
83   *   <li>Service Description Interface (required): Defines an operation for
84   *   acquiring the Producer's metadata.</li>
85   *   <li>Markup Interface (required): Defines operations for getting markup
86   *   from a portlet as well as processing user interactions with that markup.
87   *   Contains also the operation for Consumer assistance in pre-initializing
88   *   HTTP-cookies.</li>
89   *   <li>Registration Interface (optional): Defines operations for establishing,
90   *   updating and destroying a regisration. Each registration reflects a particular
91   *   relationship between a Consumer and a Producer.</li>
92   *   <li>Portlet Management Interface (optional): Defines operations for getting
93   *   portlet metadata, cloning portlets for further customization and interacting
94   *   with the property interface.</li>
95   * </li>
96   * </p>
97   * <p>All methods are implemented by calling the corresponding sub-components
98   * (Producer- and Provider-side components). Additionally each method implementation
99   * performs high level checks (e.g. a parameter validation to ensure that all required
100  * input parameters are available) and maps internal exceptions to exceptions defined
101  * vy WSRP.</p> 
102  * <p>Involves additional servlet related objects -> no mapping of the interfaces
103  * possible</p>
104  */
105 
106 public class WSRPEngine implements
107         oasis.names.tc.wsrp.v1.intf.WSRP_v1_PortletManagement_PortType,
108         oasis.names.tc.wsrp.v1.intf.WSRP_v1_Markup_PortType,
109         oasis.names.tc.wsrp.v1.intf.WSRP_v1_Registration_PortType,
110         oasis.names.tc.wsrp.v1.intf.WSRP_v1_ServiceDescription_PortType {
111 
112     private boolean registrationRequired;
113 
114     // provider
115     private Provider provider = null;
116 
117     // consumer registry
118     private ConsumerRegistry consumerRegistry = null;
119 
120     //holds an instance of the WSRPEngine
121     private static WSRPEngine instance = null;
122 
123     // helper instance for WSRP parameter validation
124     private ParameterChecker paramCheck = new ParameterChecker();
125 
126     // log and trace support
127     private Logger logger = LogManager.getLogManager().getLogger(
128             this.getClass());
129 
130     /**
131      * Constructor reading the config from the properties file
132      */
133     private WSRPEngine() throws java.rmi.RemoteException {
134         String MN = "Constructor";
135         if (logger.isLogging(Logger.TRACE_HIGH)) {
136             logger.entry(Logger.TRACE_HIGH, MN);
137         }
138 
139         try {
140             provider = ProviderAccess.getProvider();
141             consumerRegistry = ConsumerRegistryAccess.getConsumerRegistry();
142 
143             registrationRequired = consumerRegistry.isRegistrationRequired();
144 
145         }
146         catch (WSRPException e) {
147 
148             WSRPXHelper.handleWSRPException(e);
149 
150         }
151 
152         if (logger.isLogging(Logger.TRACE_HIGH)) {
153             logger.exit(Logger.TRACE_HIGH, MN);
154         }
155 
156     }
157 
158     /**
159      * Internal method.
160      * Creates a new session and initializes it
161      */
162     private void createSession() throws WSRPException {
163         MessageContext msgContext = AxisEngine.getCurrentMessageContext();
164 
165         HttpServletRequest servletRequest = (HttpServletRequest) msgContext
166                 .getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
167         HttpSession session = servletRequest.getSession(true);
168 
169         if (session == null) {
170             throw new WSRPException(ErrorCodes.OPERATION_FAILED);
171         }
172     }
173 
174     /**
175      Internal method.
176      Returns an instance of the WSRPEngine
177      @return WSRPEngine 
178      */
179     public synchronized static WSRPEngine getInstance()
180             throws java.rmi.RemoteException {
181         if (instance == null) {
182             instance = new WSRPEngine();
183         }
184 
185         return instance;
186     }
187 
188     /**
189      * Service Description Interface
190      */
191 
192     /**
193      * <p>Allows a Producer to provide information about its capabilities. Producers
194      * may choose to restrict the information returned in ServiceDescription based on
195      * the supplied RegistrationContext.</p>
196      * <p>Checks registration (if required) by querying the ConsumerRegistry and calls
197      * the DescriptionHandler to get the service description.</p> 
198      *
199      * @param request a generated wrapper containing all input arguments for this method
200      *
201      * @return ServiceDescription
202      * 
203      * @exception java.rmi.RemoteException
204      */
205     public ServiceDescription getServiceDescription(
206             GetServiceDescription request) throws java.rmi.RemoteException {
207 
208         String MN = "getServiceDescription";
209         if (logger.isLogging(Logger.TRACE_HIGH)) {
210             logger.entry(Logger.TRACE_HIGH, MN);
211         }
212 
213         ServiceDescription description = null;
214 
215         try {
216             // perform parameter check
217             paramCheck.check(request);
218 
219             DescriptionHandler descrHandler = provider.getDescriptionHandler();
220             RegistrationContext regContext = request.getRegistrationContext();
221 
222             boolean registered = false;
223 
224             if (regContext != null) {
225                 registered = consumerRegistry.check(regContext
226                         .getRegistrationHandle());
227             }
228 
229             // check registration aspects, then fetch corresponding service description
230             // TODO: also check if regHandle==null?
231             if (!registrationRequired || ((regContext != null) && (registered))) {
232                 description = descrHandler.getServiceDescription(regContext,
233                         request.getDesiredLocales());
234             }
235             else {
236                 if (regContext == null && !registered) {
237 
238                     description = descrHandler.getServiceDescription(null,
239                             request.getDesiredLocales());
240                 }
241                 else {
242 
243                     throw new WSRPException(ErrorCodes.INVALID_REGISTRATION);
244                 }
245             }
246 
247         }
248         catch (WSRPException e) {
249 
250             WSRPXHelper.handleWSRPException(e);
251 
252         }
253         catch (Throwable t) {
254             t.printStackTrace();
255         }
256 
257         if (logger.isLogging(Logger.TRACE_HIGH)) {
258             logger.exit(Logger.TRACE_HIGH, MN);
259         }
260 
261         return description;
262     }
263 
264     /**
265      * Registration Interface
266      */
267 
268     /**
269      * Calls the ConsumerRegistry to register a certain consumer.
270      * Returns a registration context including a new registration handle. 
271      *
272      * @param request a generated wrapper containing all input arguments for this method
273      * 
274      * @return RegistrationContext
275      * 
276      * @exception java.rmi.RemoteException
277      */
278     public RegistrationContext register(RegistrationData request)
279             throws java.rmi.RemoteException {
280 
281         String MN = "register";
282         if (logger.isLogging(Logger.TRACE_HIGH)) {
283             logger.entry(Logger.TRACE_HIGH, MN);
284         }
285 
286         RegistrationContext regContext = null;
287 
288         try {
289 
290             // perform parameter check
291             paramCheck.check(request, Constants.NILLABLE_FALSE);
292 
293             // add consumer to consumer registry
294             Registration consumerRegistration = consumerRegistry
295                     .register(request);
296 
297             // return registration context (containing a regHandle)
298             regContext = consumerRegistration.getRegistrationContext();
299 
300         }
301         catch (WSRPException e) {
302 
303             WSRPXHelper.handleWSRPException(e);
304 
305         }
306 
307         if (logger.isLogging(Logger.TRACE_HIGH)) {
308             logger.exit(Logger.TRACE_HIGH, MN);
309         }
310 
311         return regContext;
312     }
313 
314     /**
315      * Deregisters a certain consumer identified by a registration handle
316      * within the ConsumerRegistry. Throws an InvalidRegistration if
317      * there is no consumer registered with the given registration handle.  
318      * 
319      * @param request a generated wrapper containing all input arguments for this method
320      * 
321      * @exception java.rmi.RemoteException
322      * 
323      * @throws InvalidRegistration
324      *         The given registrationhandle is invalid / not yet registered
325      */
326     public ReturnAny deregister(RegistrationContext request)
327             throws java.rmi.RemoteException {
328 
329         String MN = "deregister";
330         if (logger.isLogging(Logger.TRACE_HIGH)) {
331             logger.entry(Logger.TRACE_HIGH, MN);
332         }
333 
334         // perform parameter check
335         paramCheck.check(request, Constants.NILLABLE_FALSE);
336 
337         try {
338 
339             checkRegistration(request);
340 
341         }
342         catch (WSRPException e) {
343 
344             WSRPXHelper.handleWSRPException(e);
345         }
346 
347         if (logger.isLogging(Logger.TRACE_HIGH)) {
348             logger.exit(Logger.TRACE_HIGH, MN);
349         }
350 
351         return new ReturnAny();
352     }
353 
354     /**
355      * Modifies the registration of a certain consumer. Throws an InvalidRegistration
356      * if there is no consumer registered with the given registration handle.
357      * 
358      * @param request a generated wrapper containing all input arguments for this method
359      *
360      * @return A RegistrationState-object if the Producer chooses to have the Consumer provide
361      *         persistent storage for those registration states, else null.
362      * 
363      * @exception java.rmi.RemoteException
364      */
365     public RegistrationState modifyRegistration(ModifyRegistration request)
366             throws java.rmi.RemoteException {
367 
368         String MN = "modifyRegistration";
369         if (logger.isLogging(Logger.TRACE_HIGH)) {
370             logger.entry(Logger.TRACE_HIGH, MN);
371         }
372 
373         // perform parameter check
374         paramCheck.check(request);
375 
376         // TODO: what behaviour is there required=
377         // just set the new stuff
378         // or merge it in?
379 
380         RegistrationState regState = null;
381 
382         try {
383 
384             checkRegistration(request.getRegistrationContext());
385 
386         }
387         catch (WSRPException e) {
388 
389             WSRPXHelper.handleWSRPException(e);
390         }
391 
392         Registration registration = consumerRegistry.get(request
393                 .getRegistrationContext().getRegistrationHandle());
394 
395         // set new attributes
396         registration.setRegistrationData(request.getRegistrationData());
397         registration.setRegistrationContext(request.getRegistrationContext());
398 
399         // return changed registration state
400         // -> case Producer chooses to have Consumer provide persistent storage
401         regState = new RegistrationState();
402         regState.setRegistrationState(registration.getRegistrationContext()
403                 .getRegistrationState());
404         regState.setExtensions(null);
405 
406         if (logger.isLogging(Logger.TRACE_HIGH)) {
407             logger.exit(Logger.TRACE_HIGH, MN);
408         }
409 
410         return regState;
411 
412     }
413 
414     /**
415      * check if the registration handle is valid
416      * if not throw some RuntimeException
417      * 
418      * @param registrationContext
419      *               the registration handle of the consumer
420      * 
421      * @throws InvalidRegistration
422      * @throws MissingParameterFault
423      */
424     private void checkRegistration(RegistrationContext registrationContext)
425             throws java.rmi.RemoteException, WSRPException {
426 
427         String MN = "checkRegistration";
428         if (logger.isLogging(Logger.TRACE_HIGH)) {
429             logger.entry(Logger.TRACE_HIGH, MN);
430         }
431 
432         paramCheck.check(registrationContext, Constants.NILLABLE_FALSE);
433 
434         if (!consumerRegistry
435                 .check(registrationContext.getRegistrationHandle())) {
436             throw new WSRPException(ErrorCodes.INVALID_REGISTRATION);
437 
438         }
439 
440         if (logger.isLogging(Logger.TRACE_HIGH)) {
441             logger.exit(Logger.TRACE_HIGH, MN);
442         }
443 
444     }
445 
446     /**
447      * Get the required portlet AND check for the registration.
448      * If the producer is enabled for registration the
449      * portlet's registration policy is being checked.
450      * 
451      * @param registrationContext
452      * @param portletHandle
453      * @return 
454      * @exception java.rmi.RemoteException
455      */
456     private Portlet getPortlet(RegistrationContext registrationContext,
457             String portletHandle) throws java.rmi.RemoteException {
458 
459         String MN = "getPortlet";
460         if (logger.isLogging(Logger.TRACE_HIGH)) {
461             logger.entry(Logger.TRACE_HIGH, MN);
462         }
463 
464         Portlet portlet = null;
465 
466         try {
467 
468             portlet = provider.getPortletPool().get(portletHandle);
469 
470             if (registrationRequired) {
471                 ProducerOfferedPortlet parent = null;
472 
473                 if (portlet instanceof ProducerOfferedPortlet) {
474                     parent = (ProducerOfferedPortlet) portlet;
475                 }
476                 else {
477                     //validate the consumers registration for the requested clone portlet
478                     String regHandle = registrationContext
479                             .getRegistrationHandle();
480                     if (!provider.getPortletRegistrationFilter().isAvailable(
481                             regHandle, portletHandle)) {
482                         throw new WSRPException(ErrorCodes.ACCESS_DENIED);
483                     }
484 
485                     // get parent
486                     String parentHandle = ((ConsumerConfiguredPortlet) portlet)
487                             .getParentHandle();
488 
489                     parent = (ProducerOfferedPortlet) provider.getPortletPool()
490                             .get(parentHandle);
491 
492                 }
493 
494                 if ((parent != null) && parent.isRegistrationRequired()) {
495                     checkRegistration(registrationContext);
496                 }
497 
498             }
499 
500         }
501         catch (WSRPException e) {
502             WSRPXHelper.handleWSRPException(e);
503         }
504 
505         if (logger.isLogging(Logger.TRACE_HIGH)) {
506             logger.exit(Logger.TRACE_HIGH, MN);
507         }
508 
509         return portlet;
510     }
511 
512     /**
513      Internal method.
514      Validates if a cookie/the session value has been expired. If the cookie/session is expired an invalid
515      cookie fault will be thrown.
516      */
517     private void checkCookie() throws java.rmi.RemoteException, WSRPException {
518         // check if http-session has expired; if so throw InvalidCookie-Exception.
519         MessageContext msgContext = AxisEngine.getCurrentMessageContext();
520 
521         HttpServletRequest servletRequest = (HttpServletRequest) msgContext
522                 .getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
523         HttpSession session = servletRequest.getSession(false);
524 
525         if (session == null) {
526             throw new WSRPException(ErrorCodes.INVALID_COOKIE);
527         }
528 
529     }
530 
531     /**
532      * This method checks the MarkupParams from the consumer request and tries to
533      * find a match between the mimeType, mode, windowState and locale of the
534      * portlet description and the requested values. The first match which is found
535      * is returned in a <code>MarkupType</code> object where the arrays
536      * for modes and windowStates and locales have a length of one.  
537      *  
538      * @param portletDescription The description of the portlet.
539      * @param markupParams The markup params from the consumer request
540      * @return The <code>MarkupType</code> object which should be used to call the portlet.
541      * @throws WSRPException In case no match was found
542      **/
543     private MarkupType checkMarkupParams(PortletDescription portletDescription,
544             MarkupParams markupParams) throws WSRPException {
545 
546         String MN = "checkMarkupParams";
547         if (logger.isLogging(Logger.TRACE_HIGH)) {
548             logger.entry(Logger.TRACE_HIGH, MN);
549         }
550 
551         MarkupType match = new MarkupType();
552 
553         String[] reqMimeTypes = markupParams.getMimeTypes();
554         String reqMode = markupParams.getMode();
555         String reqWindowState = markupParams.getWindowState();
556         String[] reqLocales = markupParams.getLocales();
557         boolean foundMime, foundWindow, foundMode;
558         foundMime = foundWindow = foundMode = false;
559 
560         MarkupType[] markupTypes = portletDescription.getMarkupTypes();
561         for (int i = 0; i < markupTypes.length; i++) {
562 
563             // check if mime type is supported by portlet
564             String mimeType = markupTypes[i].getMimeType();
565             for (int j = 0; j < reqMimeTypes.length; j++) {
566 
567                 // TODO: Checking of mime types that are
568                 //        not fully qualified e.g. 'text/*'
569                 if (mimeType.equalsIgnoreCase(reqMimeTypes[j])) {
570                     foundMime = true;
571                     match.setMimeType(mimeType);
572 
573                     // check if the mode is supported for this mime type
574                     String[] modes = markupTypes[i].getModes();
575                     for (int k = 0; k < modes.length; k++) {
576 
577                         if (modes[k].equalsIgnoreCase(reqMode)) {
578                             foundMode = true;
579                             match.setModes(new String[] { reqMode });
580 
581                             //check window state
582                             String[] windowStates = markupTypes[i]
583                                     .getWindowStates();
584                             for (int l = 0; l < windowStates.length; l++) {
585 
586                                 if (windowStates[l]
587                                         .equalsIgnoreCase(reqWindowState)) {
588                                     foundWindow = true;
589                                     match
590                                             .setWindowStates(new String[] { reqWindowState });
591 
592                                     // check locales
593                                     String[] locales = markupTypes[i]
594                                             .getLocales();
595                                     if (locales == null) {
596                                         if (logger.isLogging(Logger.TRACE_HIGH)) {
597                                             logger.exit(Logger.TRACE_HIGH, MN);
598                                         }
599                                         return match;
600                                     }
601 
602                                     for (int m = 0; m < locales.length; m++) {
603                                         for (int n = 0; n < reqLocales.length; n++) {
604                                             if (locales[m]
605                                                     .equalsIgnoreCase(reqLocales[n])) {
606                                                 match
607                                                         .setLocales(new String[] { locales[m] });
608 
609                                                 if (logger
610                                                         .isLogging(Logger.TRACE_HIGH)) {
611                                                     logger.exit(
612                                                             Logger.TRACE_HIGH,
613                                                             MN);
614                                                 }
615                                                 return match;
616                                             }
617                                             else {
618                                                 // lets see if at least a the language can be done
619                                                 if (LocaleHelper
620                                                         .getLanguageCode(
621                                                                 locales[m])
622                                                         .equalsIgnoreCase(
623                                                                 LocaleHelper
624                                                                         .getLanguageCode(reqLocales[n]))) {
625                                                     match
626                                                             .setLocales(new String[] { LocaleHelper
627                                                                     .getLanguageCode(locales[m]) });
628 
629                                                     if (logger
630                                                             .isLogging(Logger.TRACE_HIGH)) {
631                                                         logger
632                                                                 .exit(
633                                                                         Logger.TRACE_HIGH,
634                                                                         MN);
635                                                     }
636 
637                                                     return match;
638                                                 }
639 
640                                             }
641                                         }
642                                     }
643                                 }
644                             }
645                         }
646                     }
647                 }
648             }
649         }
650 
651         if (logger.isLogging(Logger.TRACE_HIGH)) {
652             logger.exit(Logger.TRACE_HIGH, MN);
653         }
654 
655         if (!foundMime)
656             throw new WSRPException(ErrorCodes.UNSUPPORTED_MIME_TYPE);
657         if (!foundMode)
658             throw new WSRPException(ErrorCodes.UNSUPPORTED_MODE);
659         if (!foundWindow)
660             throw new WSRPException(ErrorCodes.UNSUPPORTED_WINDOW_STATE);
661 
662         throw new WSRPException(ErrorCodes.UNSUPPORTED_LOCALE);
663     }
664 
665     /**
666      * Markup Interface
667      */
668 
669     /**
670      * <p>Requests the markup for rendering the current state of a portlet by calling
671      * the PortletInvoker.</p>
672      * <p>Throws InvalidHandleFault if there is no portlet in the PortletPool that
673      * corresponds to the provided portlet handle. Throws InvalidRegistration
674      * if there is no registration with the given registration handle available within
675      * the ConsumerRegistry (case registration is required).</p>
676      * <p>Fetches the portlet description from the DescriptionHandler to figure out
677      * whether the portlet supports template processing or not. If so, it checks whether
678      * templates are provided or not.</p>
679      *  
680      * @param request a generated wrapper containing all input arguments for this method
681      *
682      * @return MarkupResponse
683      *
684      * @exception java.rmi.RemoteException
685      */
686     public MarkupResponse getMarkup(GetMarkup request)
687             throws java.rmi.RemoteException {
688 
689         String MN = "getMarkup";
690         if (logger.isLogging(Logger.TRACE_HIGH)) {
691             logger.entry(Logger.TRACE_HIGH, MN);
692         }
693 
694         MarkupResponse markupResponse = null;
695 
696         try {
697 
698             // perform parameter check
699             paramCheck.check(request);
700 
701             this.checkCookie();
702 
703             RegistrationContext regContext = request.getRegistrationContext();
704 
705             PortletDescription portletDescription = null;
706 
707             portletDescription = provider.getDescriptionHandler()
708                     .getPortletDescription(
709                             request.getPortletContext().getPortletHandle(),
710                             regContext, null,
711                             request.getMarkupParams().getLocales());
712 
713             // check the markup params and find the locale, mimetype, mode, state whcih is used
714             // for render
715             MarkupType markupType = this.checkMarkupParams(portletDescription,
716                     request.getMarkupParams());
717 
718             //replace with markup types from the request
719             request.getMarkupParams().setLocales(markupType.getLocales());
720             request.getMarkupParams().setMimeTypes(
721                     new String[] { markupType.getMimeType() });
722             request.getMarkupParams().setMode(markupType.getModes()[0]);
723             request.getMarkupParams().setWindowState(
724                     markupType.getWindowStates()[0]);
725             request.getMarkupParams().setWindowState(
726                     markupType.getWindowStates()[0]);
727 
728             // check if template processing is supported
729             Boolean templateProcessing = portletDescription
730                     .getDoesUrlTemplateProcessing();
731             if (templateProcessing == null) {
732                 // TODO get default
733                 templateProcessing = Boolean.FALSE;
734             }
735 
736             if (templateProcessing.booleanValue()) {
737                 // consumer has to provide templates
738                 try {
739                     paramCheck
740                             .check(request.getRuntimeContext().getTemplates());
741                 }
742                 catch (MissingParametersFault e) {
743                     templateProcessing = Boolean.FALSE;
744                 }
745             }
746 
747             // invoke the portlet service
748             markupResponse = provider.getPortletInvoker().invokeGetMarkup(
749                     request);
750 
751             // TODO: Check if markup requires rewriting.
752             //        For now: If no template processing supported set requiresRewriting=true
753             if (!templateProcessing.booleanValue()) {
754                 markupResponse.getMarkupContext().setRequiresUrlRewriting(
755                         Boolean.TRUE);
756             }
757             else {
758                 markupResponse.getMarkupContext().setRequiresUrlRewriting(
759                         Boolean.FALSE);
760             }
761 
762         }
763         catch (WSRPException e) {
764             WSRPXHelper.handleWSRPException(e);
765         }
766 
767         if (logger.isLogging(Logger.TRACE_HIGH)) {
768             logger.exit(Logger.TRACE_HIGH, MN);
769         }
770 
771         return markupResponse;
772     }
773 
774     /**
775      * <p>Invokes a blocking interaction with the adressed portlet by calling
776      * the PortletInvoker</p>
777      * <p>Throws InvalidHandleFault if there is no portlet in the PortletPool that
778      * corresponds to the provided portlet handle. Throws InvalidRegistration
779      * if there is no registration with the given registration handle available within
780      * the ConsumerRegistry (case registration is required).</p>
781      *
782      * @param request a generated wrapper containing all input arguments for this method
783      *
784      * @return BlockingInteractionResponse
785      *
786      * @exception java.rmi.RemoteException
787      */
788     public BlockingInteractionResponse performBlockingInteraction(
789             PerformBlockingInteraction request)
790             throws java.rmi.RemoteException {
791         String MN = "performBlockingInteraction";
792         if (logger.isLogging(Logger.TRACE_HIGH)) {
793             logger.entry(Logger.TRACE_HIGH, MN);
794         }
795 
796         BlockingInteractionResponse interactionResponse = null;
797 
798         try {
799 
800             // perform parameter validation
801             paramCheck.check(request);
802 
803             checkCookie();
804 
805             // check PortletStateChange setting
806             // might clone before write
807             PortletContext newPortletContext = null;
808             newPortletContext = handlePortletStateChange(request);
809 
810             // check the markup params and find the locale, mimetype, mode, state whcih is used
811             // for render
812             PortletDescription portletDescription = null;
813 
814             portletDescription = provider.getDescriptionHandler()
815                     .getPortletDescription(
816                             request.getPortletContext().getPortletHandle(),
817                             request.getRegistrationContext(), null,
818                             request.getMarkupParams().getLocales());
819 
820             MarkupType markupType = this.checkMarkupParams(portletDescription,
821                     request.getMarkupParams());
822 
823             //replace with markup types from the request
824             request.getMarkupParams().setLocales(markupType.getLocales());
825             request.getMarkupParams().setMimeTypes(
826                     new String[] { markupType.getMimeType() });
827             request.getMarkupParams().setMode(markupType.getModes()[0]);
828             request.getMarkupParams().setWindowState(
829                     markupType.getWindowStates()[0]);
830 
831             // invoke the service
832             interactionResponse = provider.getPortletInvoker()
833                     .invokePerformBlockingInteraction(request);
834             if (newPortletContext != null) {
835                 interactionResponse.getUpdateResponse().setPortletContext(
836                         newPortletContext);
837             }
838         }
839         catch (WSRPException e) {
840             WSRPXHelper.handleWSRPException(e);
841         }
842 
843         if (logger.isLogging(Logger.TRACE_HIGH)) {
844             logger.exit(Logger.TRACE_HIGH, MN);
845         }
846 
847         return interactionResponse;
848     }
849 
850     /**
851      * checks if portlet may be accessed according to the PortletStateChange setting
852      * throws the appropriate exceptions
853      * or clones before write
854      * @param request
855      */
856     private PortletContext handlePortletStateChange(
857             PerformBlockingInteraction request) throws RemoteException,
858             WSRPException {
859 
860         final String MN = "handlePortletStateChange";
861 
862         PortletContext portletContext = null;
863         Portlet portlet = null;
864         try {
865             portlet = provider.getPortletPool().get(
866                     request.getPortletContext().getPortletHandle());
867         }
868         catch (WSRPException e) {
869             if (e.getErrorCode() == ErrorCodes.GET_PORTLET_FAILED) {
870                 // portlet not in pool, must be an invalid handle
871                 WSRPXHelper.throwX(logger, Logger.ERROR, MN,
872                         ErrorCodes.INVALID_HANDLE);
873             }
874             else {
875                 WSRPXHelper.throwX(e.getErrorCode());
876             }
877         }
878 
879         // use the bad way to distinguish the portlet type
880         // TODO: need to refine that
881         StateChange stateChange = null;
882         stateChange = request.getInteractionParams().getPortletStateChange();
883         if (portlet instanceof ProducerOfferedPortlet) {
884             if (stateChange.toString().equals(StateChange._readOnly)) {
885                 // force the consumer to clone since we can't make sure the portlet won't change state
886                 // in JSR168 case
887                 WSRPXHelper.throwX(ErrorCodes.PORTLET_STATE_CHANGE_REQUIRED);
888             }
889             else if (stateChange.toString().equals(
890                     StateChange._cloneBeforeWrite)) {
891                 // need to clone the portlet
892                 portletContext = handleCloneBeforeWrite(request);
893             }
894             else {
895                 // must be readWrite, can't access a POP in readWrite mode
896                 WSRPXHelper.throwX(ErrorCodes.OPERATION_FAILED);
897             }
898         }
899         else if (portlet instanceof ConsumerConfiguredPortlet) {
900             if (stateChange.toString().equals(StateChange._readOnly)) {
901                 // does it make sense to access a CCP in readOnly?
902                 // force consumer to clone if he access a CCP in readOnly
903                 WSRPXHelper.throwX(ErrorCodes.PORTLET_STATE_CHANGE_REQUIRED);
904             }
905             else if (stateChange.toString().equals(
906                     StateChange._cloneBeforeWrite)) {
907                 // need to clone the portlet
908                 portletContext = handleCloneBeforeWrite(request);
909             }
910             else {
911                 // must be readWrite, readWrite is fine, continue
912             }
913         }
914         else {
915             // what is it then :-)
916             WSRPXHelper.throwX(logger, Logger.ERROR, MN,
917                     ErrorCodes.OPERATION_FAILED);
918         }
919 
920         return portletContext;
921     }
922 
923     /**
924      * clone portlet and its session before performBlockingInteraction continues
925      * @param request
926      */
927     private PortletContext handleCloneBeforeWrite(
928             PerformBlockingInteraction request) throws WSRPException,
929             java.rmi.RemoteException {
930 
931         // clone the portlet
932         PortletContext portletContext = null;
933         ClonePortlet cloneRequest = new ClonePortlet();
934         cloneRequest.setPortletContext(request.getPortletContext());
935         cloneRequest.setRegistrationContext(request.getRegistrationContext());
936         cloneRequest.setUserContext(request.getUserContext());
937 
938         portletContext = clonePortlet(cloneRequest);
939 
940         // change the portletContext in the original request
941         // thus we continue with the new cloned portlet
942         request.setPortletContext(portletContext);
943 
944         // TODO: copy session        
945 
946         return portletContext;
947     }
948 
949     /**                                                                          
950      * Creates a new HTTP session and initializes it
951      * <p>Throws InvalidRegistration if there is no registration with the given
952      * registration handle available within the ConsumerRegistry (if registration is
953      * required).</p>
954      *
955      * @param request a generated wrapper containing all input arguments for this method
956      * 
957      * @exception java.rmi.RemoteException
958      *
959      * @return null
960      * 
961      * @throws MissingParameterFault
962      * @throws InvalidRegistration
963      */
964     public ReturnAny initCookie(InitCookie request)
965             throws java.rmi.RemoteException {
966 
967         String MN = "initCookie";
968         if (logger.isLogging(Logger.TRACE_HIGH)) {
969             logger.entry(Logger.TRACE_HIGH, MN);
970         }
971         try {
972 
973             // perform parameter check
974             paramCheck.check(request);
975 
976             // if registration is required, a valid registration must exist
977             // for the given registration handle
978             if (registrationRequired) {
979                 checkRegistration(request.getRegistrationContext());
980             }
981 
982             // create the HTTP session
983             createSession();
984 
985         }
986         catch (WSRPException e) {
987 
988             WSRPXHelper.handleWSRPException(e);
989         }
990 
991         if (logger.isLogging(Logger.TRACE_HIGH)) {
992             logger.exit(Logger.TRACE_HIGH, MN);
993         }
994 
995         return new ReturnAny();
996     }
997 
998     /**
999      * <p>Destroys the sessions adressed by the delivered sessionIDs.
1000     * Returns null by default.</p>
1001     * <p>Throws InvalidRegistration if there is no registration with the given
1002     * registration handle available within the ConsumerRegistry (case registration is
1003     * required).</p>
1004     *
1005     * @param request a generated wrapper containing all input arguments for this method
1006     * 
1007     * @return null
1008     */
1009    public ReturnAny releaseSessions(ReleaseSessions request)
1010            throws java.rmi.RemoteException {
1011
1012        String MN = "releaseSession";
1013        if (logger.isLogging(Logger.TRACE_HIGH)) {
1014            logger.entry(Logger.TRACE_HIGH, MN);
1015        }
1016
1017        // since we don't use the WSRP sessions
1018        // we always report success
1019
1020        if (logger.isLogging(Logger.TRACE_HIGH)) {
1021            logger.exit(Logger.TRACE_HIGH, MN);
1022        }
1023        return new ReturnAny();
1024    }
1025
1026    /**
1027     * Portlet Management Interface
1028     */
1029
1030    /**
1031     * <p>Fetches a PortletDescription from the DescriptionHandler.</p>
1032     * <p>Throws InvalidHandleFault if there is no portlet in the PortletPool that
1033     * corresponds to the provided portlet handle. Throws InvalidRegistration
1034     * if there is no registration with the given registration handle available within
1035     * the ConsumerRegistry (case registration is required).</p>
1036     * 
1037     * @param request a generated wrapper containing all input arguments for this method
1038     *
1039     * @return 
1040     *
1041     * @exception java.rmi.RemoteException
1042     */
1043    public PortletDescriptionResponse getPortletDescription(
1044            GetPortletDescription request) throws java.rmi.RemoteException {
1045
1046        String MN = "getPortletDescription";
1047        if (logger.isLogging(Logger.TRACE_HIGH)) {
1048            logger.entry(Logger.TRACE_HIGH, MN);
1049        }
1050
1051        PortletDescription portletDescription = null;
1052        PortletDescriptionResponse response = null;
1053
1054        try {
1055
1056            // perform parameter check
1057            paramCheck.check(request);
1058
1059            RegistrationContext regContext = request.getRegistrationContext();
1060
1061            portletDescription = provider.getDescriptionHandler()
1062                    .getPortletDescription(
1063                            request.getPortletContext().getPortletHandle(),
1064                            regContext, null, request.getDesiredLocales());
1065
1066            response = new PortletDescriptionResponse();
1067            response.setPortletDescription(portletDescription);
1068            response.setResourceList(null);
1069            response.setExtensions(null);
1070
1071        }
1072        catch (WSRPException e) {
1073
1074            WSRPXHelper.handleWSRPException(e);
1075
1076        }
1077
1078        if (logger.isLogging(Logger.TRACE_HIGH)) {
1079            logger.exit(Logger.TRACE_HIGH, MN);
1080        }
1081
1082        return response;
1083    }
1084
1085    /**
1086     * <p>Calls the PortletPool to clone a portlet.</p>
1087     * <p>Throws InvalidHandleFault if there is no portlet to be cloned in the PortletPool
1088     * that corresponds to the provided portlet handle. Throws InvalidRegistration
1089     * if there is no registration with the given registration handle available within
1090     * the ConsumerRegistry (case registration is required).</p>
1091     * 
1092     * @param request a generated wrapper containing all input arguments for this method
1093     * @return 
1094     * @exception java.rmi.RemoteException
1095     */
1096    public PortletContext clonePortlet(ClonePortlet request)
1097            throws java.rmi.RemoteException {
1098
1099        String MN = "clonePortlet";
1100        if (logger.isLogging(Logger.TRACE_HIGH)) {
1101            logger.entry(Logger.TRACE_HIGH, MN);
1102        }
1103
1104        PortletContext portletContext = null;
1105
1106        try {
1107            // parameter validation
1108            paramCheck.check(request);
1109
1110            PortletStateManager portletStateManager = null;
1111
1112            portletStateManager = provider.getPortletStateManager();
1113
1114            String orgPortletHandle = request.getPortletContext()
1115                    .getPortletHandle();
1116
1117            Portlet portletClone = null;
1118
1119            // clone portlet
1120            portletClone = provider.getPortletPool().clone(orgPortletHandle);
1121
1122            if (portletClone != null) {
1123
1124                String newPortletHandle = portletClone.getPortletHandle();
1125
1126                // create portlet context
1127                portletContext = new PortletContext();
1128                portletContext.setPortletHandle(newPortletHandle);
1129                portletContext.setPortletState(portletStateManager.getAsString(
1130                        newPortletHandle).getBytes());
1131                portletContext.setExtensions(null);
1132
1133                // remember clone handle for this registration
1134                RegistrationContext regContext = request
1135                        .getRegistrationContext();
1136                if (regContext != null) {
1137                    String regHandle = regContext.getRegistrationHandle();
1138                    if (regHandle != null
1139                            && consumerRegistry.check(regHandle) == true) {
1140                        provider.getPortletRegistrationFilterWriter()
1141                                .makeAvailable(regHandle, newPortletHandle);
1142                    }
1143                }
1144
1145            }
1146            else {
1147                throw new WSRPException(ErrorCodes.OPERATION_FAILED);
1148            }
1149
1150        }
1151        catch (WSRPException e) {
1152            WSRPXHelper.handleWSRPException(e);
1153        }
1154
1155        if (logger.isLogging(Logger.TRACE_HIGH)) {
1156            logger.exit(Logger.TRACE_HIGH, MN);
1157        }
1158
1159        return portletContext;
1160    }
1161
1162    /**
1163     * <p>Removes all portlets corresponding to the provided portlet handles from the
1164     * PortletPool. All portlet handles refering to portlets that cannot be destroyed
1165     * (e.g. portlet handles from Producer Offered Portlets) will be returned within the
1166     * DestroyPortletResponse as DestroyFailed-objects.</p>
1167     * <p>Throws InvalidRegistration if there is no registration with the given
1168     * registration handle available within the ConsumerRegistry (case registration
1169     * is required).</p>
1170     *
1171     * @param request a generated wrapper containing all input arguments for this method
1172     *
1173     * @exception java.rmi.RemoteException
1174     */
1175    public DestroyPortletsResponse destroyPortlets(DestroyPortlets request)
1176            throws java.rmi.RemoteException {
1177
1178        String MN = "destroyPortlets";
1179        if (logger.isLogging(Logger.TRACE_HIGH)) {
1180            logger.entry(Logger.TRACE_HIGH, MN);
1181        }
1182
1183        // perform paramCheck.check
1184        paramCheck.check(request);
1185
1186        try {
1187
1188            checkRegistration(request.getRegistrationContext());
1189
1190            // remove ConsumerPortletRegistrations
1191            RegistrationContext regContext = request.getRegistrationContext();
1192            if (regContext != null) {
1193                String regHandle = regContext.getRegistrationHandle();
1194                if (regHandle != null
1195                        && consumerRegistry.check(regHandle) == true) {
1196                    provider.getPortletRegistrationFilterWriter().remove(
1197                            regHandle,
1198                            Arrays.asList(request.getPortletHandles())
1199                                    .iterator());
1200                }
1201            }
1202
1203        }
1204        catch (WSRPException e) {
1205
1206            WSRPXHelper.handleWSRPException(e);
1207        }
1208
1209        Iterator handles = Arrays.asList(request.getPortletHandles())
1210                .iterator();
1211
1212        // result iterator contains portlet handles refering to those portlets
1213        // that could not be deleted (e.g. producer offered portlets)
1214        Iterator result = provider.getPortletPool().destroySeveral(handles);
1215
1216        ArrayList failedHandles = new ArrayList();
1217
1218        while (result.hasNext()) {
1219
1220            DestroyFailed failed = new DestroyFailed();
1221            failed.setPortletHandle(result.next().toString());
1222            failed
1223                    .setReason("Portlet handle refers to a producer offered portlet!");
1224            failedHandles.add(failed);
1225
1226        }
1227
1228        DestroyFailed[] destroyFailedArray = new DestroyFailed[failedHandles
1229                .size()];
1230        failedHandles.toArray(destroyFailedArray);
1231
1232        DestroyPortletsResponse response = new DestroyPortletsResponse();
1233        response.setDestroyFailed(destroyFailedArray);
1234        response.setExtensions(null);
1235
1236        if (logger.isLogging(Logger.TRACE_HIGH)) {
1237            logger.exit(Logger.TRACE_HIGH, MN);
1238        }
1239
1240        return response;
1241    }
1242
1243    /**
1244     * <p>Sets the properties of a portlet.</p>
1245     * <p>Throws InvalidHandleFault if there is no portlet in the PortletPool
1246     * that corresponds to the provided portlet handle. Throws InvalidRegistration
1247     * if there is no registration with the given registration handle available within
1248     * the ConsumerRegistry (case registration is required).</p>
1249     *
1250     * @param request a generated wrapper containing all input arguments for this method
1251     *
1252     * @return 
1253     * @exception java.rmi.RemoteException
1254     */
1255    public PortletContext setPortletProperties(SetPortletProperties request)
1256            throws java.rmi.RemoteException {
1257
1258        String MN = "setPortletProperties";
1259        if (logger.isLogging(Logger.TRACE_HIGH)) {
1260            logger.entry(Logger.TRACE_HIGH, MN);
1261        }
1262
1263        PortletContext portletContext = null;
1264
1265        try {
1266
1267            // perform parameter check
1268            paramCheck.check(request);
1269
1270            String portletHandle = request.getPortletContext()
1271                    .getPortletHandle();
1272            Portlet portlet = getPortlet(request.getRegistrationContext(),
1273                    portletHandle);
1274
1275            // check if portlet is a consumer configured portlet //TODO? 
1276            if (portlet instanceof ConsumerConfiguredPortlet) {
1277
1278                provider.getPortletStateManager().setAsPropertyList(
1279                        portletHandle, request.getPropertyList());
1280                portletContext = request.getPortletContext();
1281
1282            }
1283            else {
1284                throw new WSRPException(ErrorCodes.INCONSISTENT_PARAMETERS);
1285            }
1286
1287        }
1288        catch (WSRPException e) {
1289
1290            WSRPXHelper.handleWSRPException(e);
1291
1292        }
1293
1294        if (logger.isLogging(Logger.TRACE_HIGH)) {
1295            logger.exit(Logger.TRACE_HIGH, MN);
1296        }
1297
1298        return portletContext;
1299
1300    }
1301
1302    /**
1303     * <p>Fetches the current property values of a portlet and returns them.</p> 
1304     * <p>Throws InvalidHandleFault if there is no portlet in the PortletPool
1305     * that corresponds to the provided portlet handle. Throws InvalidRegistration
1306     * if there is no registration with the given registration handle available within
1307     * the ConsumerRegistry (case registration is required).</p>
1308     * 
1309     * @param request a generated wrapper containing all input arguments for this method
1310     *
1311     * @return PropertyList containing all properties of the adressed portlet
1312     *
1313     * @exception java.rmi.RemoteException
1314     */
1315    public PropertyList getPortletProperties(GetPortletProperties request)
1316            throws java.rmi.RemoteException {
1317
1318        String MN = "getPortletProperties";
1319        if (logger.isLogging(Logger.TRACE_HIGH)) {
1320            logger.entry(Logger.TRACE_HIGH, MN);
1321        }
1322
1323        PropertyList propertyList = null;
1324
1325        try {
1326            // perform parameter check
1327            paramCheck.check(request);
1328
1329            String portletHandle = request.getPortletContext()
1330                    .getPortletHandle();
1331            getPortlet(request.getRegistrationContext(), portletHandle);
1332
1333            PortletStateManager portletStateManager = provider
1334                    .getPortletStateManager();
1335            propertyList = portletStateManager.getAsPropertyList(portletHandle);
1336
1337        }
1338        catch (WSRPException e) {
1339
1340            WSRPXHelper.handleWSRPException(e);
1341
1342        }
1343
1344        if (logger.isLogging(Logger.TRACE_HIGH)) {
1345            logger.exit(Logger.TRACE_HIGH, MN);
1346        }
1347
1348        return propertyList;
1349    }
1350
1351    /**
1352     * <p>Returns a model description containing the property descriptions of all properties
1353     * of a portlet.</p>
1354     * <p>Throws InvalidHandleFault if there is no portlet in the PortletPool
1355     * that corresponds to the provided portlet handle. Throws InvalidRegistration
1356     * if there is no registration with the given registration handle available within
1357     * the ConsumerRegistry (case registration is required).</p>
1358     * 
1359     * @param request a generated wrapper containing all input arguments for this method
1360     *
1361     * @return 
1362     *
1363     * @exception java.rmi.RemoteException
1364     */
1365    public PortletPropertyDescriptionResponse getPortletPropertyDescription(
1366            GetPortletPropertyDescription request)
1367            throws java.rmi.RemoteException {
1368
1369        String MN = "getPortletPropertyDescription";
1370        if (logger.isLogging(Logger.TRACE_HIGH)) {
1371            logger.entry(Logger.TRACE_HIGH, MN);
1372        }
1373
1374        PortletPropertyDescriptionResponse response = null;
1375
1376        try {
1377
1378            // perform parameter check
1379            paramCheck.check(request);
1380
1381            String portletHandle = request.getPortletContext()
1382                    .getPortletHandle();
1383            getPortlet(request.getRegistrationContext(), portletHandle);
1384
1385            response = new PortletPropertyDescriptionResponse();
1386            response.setModelDescription(provider.getPortletStateManager()
1387                    .getModelDescription(portletHandle,
1388                            request.getDesiredLocales(), false));
1389            response.setResourceList(null);
1390            response.setExtensions(null);
1391
1392        }
1393        catch (WSRPException e) {
1394
1395            WSRPXHelper.handleWSRPException(e);
1396
1397        }
1398
1399        if (logger.isLogging(Logger.TRACE_HIGH)) {
1400            logger.exit(Logger.TRACE_HIGH, MN);
1401        }
1402
1403        return response;
1404    }
1405
1406}