View Javadoc
1   /*
2    * Copyright (c) 2002-2017, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.jsr168.pluto;
35  
36  import fr.paris.lutece.plugins.jsr168.pluto.core.PortalEnvironment;
37  import fr.paris.lutece.plugins.jsr168.pluto.core.PortalURL;
38  import fr.paris.lutece.plugins.jsr168.pluto.core.PortletContainerEnvironment;
39  import fr.paris.lutece.plugins.jsr168.pluto.servlet.ServletRequestImpl;
40  import fr.paris.lutece.portal.service.security.LuteceUser;
41  import fr.paris.lutece.portal.service.security.SecurityService;
42  import fr.paris.lutece.portal.service.util.AppLogService;
43  import fr.paris.lutece.portal.service.util.AppPropertiesService;
44  import fr.paris.lutece.portal.web.LocalVariables;
45  import fr.paris.lutece.util.ReferenceItem;
46  import fr.paris.lutece.util.ReferenceList;
47  
48  import org.apache.pluto.PortletContainer;
49  import org.apache.pluto.om.common.DisplayName;
50  import org.apache.pluto.om.common.ObjectID;
51  import org.apache.pluto.om.entity.PortletEntity;
52  import org.apache.pluto.om.portlet.PortletApplicationDefinition;
53  import org.apache.pluto.om.portlet.PortletApplicationDefinitionList;
54  import org.apache.pluto.om.portlet.PortletDefinition;
55  import org.apache.pluto.om.portlet.PortletDefinitionList;
56  import org.apache.pluto.om.window.PortletWindowCtrl;
57  import org.apache.pluto.portalImpl.core.PortletContainerFactory;
58  import org.apache.pluto.portalImpl.factory.FactoryAccess;
59  import org.apache.pluto.portalImpl.om.window.impl.PortletWindowImpl;
60  import org.apache.pluto.portalImpl.services.ServiceManager;
61  import org.apache.pluto.portalImpl.services.config.Config;
62  import org.apache.pluto.portalImpl.services.factorymanager.FactoryManager;
63  import org.apache.pluto.portalImpl.services.log.Log;
64  import org.apache.pluto.portalImpl.services.portletdefinitionregistry.PortletDefinitionRegistry;
65  import org.apache.pluto.portalImpl.services.portletentityregistry.PortletEntityRegistry;
66  
67  import java.util.Collections;
68  import java.util.Iterator;
69  import java.util.Locale;
70  import java.util.Map;
71  import java.util.Properties;
72  
73  import javax.portlet.PortletRequest;
74  
75  import javax.servlet.ServletConfig;
76  import javax.servlet.http.HttpServletRequest;
77  import javax.servlet.http.HttpServletResponse;
78  
79  
80  /**
81   * Main access point for connect Lutece container with Pluto container
82   */
83  public final class LuteceToPlutoConnector
84  {
85      /**
86       * The initialization isn't launched
87       */
88      public static final int STATE_INIT_NOTYET = 0;
89  
90      /**
91       * The initialization is working
92       */
93      public static final int STATE_INIT_WORKING = 1;
94  
95      /**
96       * Value greater than <code>STATE_INIT_DONE</code> means: initialization
97       * is done, but this don't inform about success or faillure.
98       */
99      public static final int STATE_INIT_DONE = 2;
100 
101     /**
102      * The initialization is done with success
103      */
104     public static final int STATE_INIT_DONE_OK = 3;
105 
106     /**
107      * The initialization is done, but in faillure
108      */
109     public static final int STATE_INIT_DONE_KO = 4;
110 
111     /**
112      * The init current state, possibles values are:<br>
113      * <li><code>STATE_INIT_NOTYET</code>
114      * <li><code>STATE_INIT_WORKING</code>
115      * <li><code>STATE_INIT_DONE_OK</code>
116      * <li><code>STATE_INIT_DONE_KO</code>
117      */
118     private static int _nStateInit = STATE_INIT_NOTYET;
119 
120     /**
121      * Pluto's main container
122      */
123     private static PortletContainer _portletContainer;
124 
125     /**
126      * Utility classes have no constructor
127      */
128     private LuteceToPlutoConnector(  )
129     {
130     }
131 
132     /**
133      * Initialize Pluto container
134      *
135      * @param config The <code>ServletConfig</code> of the web application
136      * @return <code>true</code> if all is ok
137      */
138     private static boolean init( ServletConfig config )
139     {
140         // Check if init isn't done
141         if ( _nStateInit == STATE_INIT_NOTYET )
142         {
143             synchronized ( LuteceToPlutoConnector.class )
144             {
145                 _nStateInit = STATE_INIT_WORKING;
146 
147                 try
148                 {
149                     // Init Lutece/Pluto connector: ServiceManager (services access for Pluto)
150                     ServiceManager.init( config );
151                     ServiceManager.postInit( config );
152 
153                     // Read Pluto's "unique container name" 
154                     String strContainerNameParam = LutecePlutoConstant.CONFIG_SERVICES_PARAM_UNIQUE_CONTAINERNAME;
155                     String strContainerNameParamDefault = LutecePlutoConstant.CONFIG_SERVICES_PARAM_UNIQUE_CONTAINERNAME_DEFAULT;
156                     String strUniqueContainerName = Config.getParameters(  )
157                                                           .getString( strContainerNameParam,
158                             strContainerNameParamDefault );
159 
160                     // Initialize the environement 
161                     PortletContainerEnvironment environment = new PortletContainerEnvironment(  );
162                     environment.addContainerService( Log.getService(  ) );
163                     environment.addContainerService( FactoryManager.getService(  ) );
164                     environment.addContainerService( FactoryAccess.getInformationProviderContainerService(  ) );
165 
166                     // No special properties to transmit
167                     Properties properties = new Properties(  );
168 
169                     _portletContainer = PortletContainerFactory.getPortletContainer(  );
170                     _portletContainer.init( strUniqueContainerName, config, environment, properties );
171 
172                     if ( _portletContainer.isInitialized(  ) )
173                     {
174                         _nStateInit = STATE_INIT_DONE_OK;
175                     }
176                     else
177                     {
178                         _nStateInit = STATE_INIT_DONE_KO;
179                     }
180                 }
181                 catch ( Throwable t )
182                 {
183                     _nStateInit = STATE_INIT_DONE_KO;
184                     AppLogService.error( AppPropertiesService.getProperty( LutecePlutoConstant.PROPERTY_LOG_PREFIX ) +
185                         AppPropertiesService.getProperty( LutecePlutoConstant.PROPERTY_LOG_INITIALIZATION_FAIL ), t );
186 
187                     // TODO
188                     // For initialization in servlets container (in function init(ServletConfig))
189                     // the function will throw an UnavailableException(". . ."): the portlet 
190                     // must become "unavailable" if permanent is set to true
191                 }
192             }
193         }
194 
195         // return true if init was a success
196         return ( _nStateInit == STATE_INIT_DONE_OK );
197     }
198 
199     /**
200      * TODO Not implemented: must be called (and coded) for shutdown Pluto
201      * container.
202      */
203     public static void shutdown(  )
204     {
205     }
206 
207     /**
208      * Render the portlet fragment
209      *
210      * @param nPortletID Lutece portlet ID
211      * @param strPortletName JSR 168 portlet name (ID)
212      * @return the portlet fragment page
213      */
214     public static String render( int nPortletID, String strPortletName )
215     {
216         // Restore main parameter from the ThreadLocal
217         ServletConfig config = LocalVariables.getConfig(  );
218         HttpServletRequest request = LocalVariables.getRequest(  );
219         HttpServletResponse response = LocalVariables.getResponse(  );
220 
221         // Initialize pluto if isn't done
222         if ( !init( config ) )
223         {
224             return AppPropertiesService.getProperty( LutecePlutoConstant.PROPERTY_PROBLEM_INITIALIZATION );
225         }
226 
227         AppLogService.debug( "JSR168 / BEGIN Render porlet (lutece ID [" + nPortletID + "]; portlet name [" +
228             strPortletName + "]" );
229 
230         // Retrieve the portlet window
231         PlutoSession plutoSession = PlutoSession.findSession( request );
232         PortletWindowImpl portletWindow = plutoSession.getPortletWindow( String.valueOf( nPortletID ) );
233 
234         // Wrap request and response
235         HttpServletRequest luteceRequest = new ServletRequestImpl( request, portletWindow );
236         LuteceHttpServletResponse luteceResponse = new LuteceHttpServletResponse( response );
237 
238         String strPortletEntityId = LutecePlutoConstant.WEBAPP + "." + strPortletName;
239 
240         ObjectID objectID = org.apache.pluto.portalImpl.util.ObjectID.createFromString( strPortletEntityId );
241         PortletEntity portletEntity = PortletEntityRegistry.getPortletEntity( objectID );
242         ( (PortletWindowCtrl) portletWindow ).setPortletEntity( portletEntity );
243 
244         try
245         {
246             PortalEnvironment portalEnvironment = new PortalEnvironment( config, luteceRequest, luteceResponse,
247                     String.valueOf( nPortletID ) );
248 
249             // Needed since we want to avoid side effect in PortalEnvironment constructor
250             portalEnvironment.initPortalEnvironment(  );
251 
252             _portletContainer.portletLoad( portletWindow, luteceRequest, luteceResponse );
253             _portletContainer.renderPortlet( portletWindow, luteceRequest, luteceResponse );
254 
255             String strData = luteceResponse.getBufferString(  );
256 
257             return strData;
258         }
259         catch ( Throwable e )
260         {
261             AppLogService.error( AppPropertiesService.getProperty( LutecePlutoConstant.PROPERTY_LOG_PREFIX ) +
262                 " exception " + e.getClass(  ).getName(  ) + ": " + e.getMessage(  ), e );
263         }
264 
265         return AppPropertiesService.getProperty( LutecePlutoConstant.PROPERTY_PROBLEM_RENDER );
266     }
267 
268     /**
269      * Realise an action (render or action)
270      *
271      * @param nPortletId Lutece portlet ID
272      * @param strPortletName JSR 168 portlet name (ID)
273      * @return <code>true</code> for a normal processing, <code>false</code> for the need to send a redirect to the client.
274      */
275     public static boolean request( int nPortletId, String strPortletName )
276     {
277         // Restore main parameters from the ThreadLocal
278         HttpServletRequest request = LocalVariables.getRequest(  );
279 
280         if ( PortalURL.isActionURL( request ) )
281         {
282             return LuteceToPlutoConnector.requestAction( nPortletId, strPortletName );
283         }
284 
285         return LuteceToPlutoConnector.requestRender( nPortletId );
286     }
287 
288     /**
289      * Return titles list of defined portlets
290      *
291      * @return titles list of defined portlets
292      */
293     public static ReferenceList getPortletTitles(  )
294     {
295         // Restore main parameter from the ThreadLocal
296         ServletConfig config = LocalVariables.getConfig(  );
297         HttpServletRequest request = LocalVariables.getRequest(  );
298 
299         ReferenceList result = new ReferenceList(  );
300 
301         if ( !init( config ) )
302         {
303             return result;
304         }
305 
306         String webapp = LutecePlutoConstant.WEBAPP;
307         ObjectID webappObjectID = org.apache.pluto.portalImpl.util.ObjectID.createFromString( webapp );
308         PortletApplicationDefinitionList applicationDefinitionList = PortletDefinitionRegistry.getPortletApplicationDefinitionList(  );
309         PortletApplicationDefinition applicationDefinition = applicationDefinitionList.get( webappObjectID );
310         PortletDefinitionList portletDefinitionList = applicationDefinition.getPortletDefinitionList(  );
311 
312         Iterator it = portletDefinitionList.iterator(  );
313 
314         while ( it.hasNext(  ) )
315         {
316             PortletDefinition portletDefinition = (PortletDefinition) it.next(  );
317             String strName = portletDefinition.getName(  );
318 
319             DisplayName displayNameObj = portletDefinition.getDisplayName( request.getLocale(  ) );
320 
321             if ( displayNameObj == null )
322             {
323                 displayNameObj = portletDefinition.getDisplayName( Locale.ENGLISH );
324             }
325 
326             String strDisplayName;
327 
328             if ( displayNameObj != null )
329             {
330                 strDisplayName = displayNameObj.getDisplayName(  );
331             }
332             else
333             {
334                 strDisplayName = strName;
335             }
336 
337             ReferenceItem refItem = new ReferenceItem(  );
338             refItem.setCode( strName );
339             refItem.setName( strDisplayName );
340             result.add( refItem );
341         }
342 
343         return result;
344     }
345 
346     /**
347      * Return list of buttons that must be displayed on the portlet titlebar.
348      *
349      * @param nPortletID Lutece portlet ID
350      * @param strPortletName JSR 168 portlet name (ID)
351      * @return Return button defined for this
352      */
353     public static Buttons getButtons( int nPortletID, String strPortletName )
354     {
355         // Restore main parameter from the ThreadLocal
356         ServletConfig config = LocalVariables.getConfig(  );
357         HttpServletRequest request = LocalVariables.getRequest(  );
358         HttpServletResponse response = LocalVariables.getResponse(  );
359 
360         final Buttons buttons = new Buttons(  );
361 
362         if ( init( config ) )
363         {
364             // Retrieve the portlet window
365             PlutoSession plutoSession = PlutoSession.findSession( request );
366             PortletWindowImpl portletWindow = plutoSession.getPortletWindow( String.valueOf( nPortletID ) );
367 
368             String strPortletEntityId = LutecePlutoConstant.WEBAPP + "." + strPortletName;
369             ObjectID objectID = org.apache.pluto.portalImpl.util.ObjectID.createFromString( strPortletEntityId );
370             PortletEntity portletEntity = PortletEntityRegistry.getPortletEntity( objectID );
371             ( (PortletWindowCtrl) portletWindow ).setPortletEntity( portletEntity );
372 
373             buttons.init( request, response, portletEntity.getPortletDefinition(  ), portletWindow );
374         }
375 
376         return buttons;
377     }
378 
379     /**
380      * Realise an action
381      *
382      * @param nPortletID Lutece portlet ID
383      * @param strPortletName JSR 168 portlet name (ID)
384      * @return <code>true</code> for a normal processing, <code>false</code> for the need to send a redirect to the client.
385      */
386     private static boolean requestAction( int nPortletID, String strPortletName )
387     {
388         // Restore main parameters from the ThreadLocal
389         ServletConfig config = LocalVariables.getConfig(  );
390         HttpServletRequest request = LocalVariables.getRequest(  );
391         HttpServletResponse response = LocalVariables.getResponse(  );
392 
393         if ( !init( config ) )
394         {
395             return false;
396         }
397 
398         AppLogService.debug( "JSR168 / BEGIN Action porlet (lutece ID [" + nPortletID + "]; portlet name [" +
399             strPortletName + "]" );
400 
401         // Map all Lutece user info
402         prepareUserInfo( request );
403 
404         // Retrieve the portlet window
405         PlutoSession plutoSession = PlutoSession.findSession( request );
406         PortletWindowImpl portletWindow = plutoSession.getPortletWindow( String.valueOf( nPortletID ) );
407 
408         PortalURL portalURL = new PortalURL( request );
409 
410         portalURL.fillWindowPortlet( portletWindow );
411 
412         String strPortletEntityId = LutecePlutoConstant.WEBAPP + "." + strPortletName;
413         ObjectID objectID = org.apache.pluto.portalImpl.util.ObjectID.createFromString( strPortletEntityId );
414         PortletEntity portletEntity = PortletEntityRegistry.getPortletEntity( objectID );
415         ( (PortletWindowCtrl) portletWindow ).setPortletEntity( portletEntity );
416 
417         HttpServletRequest luteceRequest = new ServletRequestImpl( request, portletWindow );
418         LuteceHttpServletResponse luteceResponse = new LuteceHttpServletResponse( response );
419 
420         try
421         {
422             PortalEnvironment portalEnvironment = new PortalEnvironment( config, luteceRequest, luteceResponse,
423                     String.valueOf( nPortletID ) );
424 
425             // Needed since we want to avoid side effect in PortalEnvironment constructor
426             portalEnvironment.initPortalEnvironment(  );
427 
428             _portletContainer.portletLoad( portletWindow, luteceRequest, luteceResponse );
429             _portletContainer.processPortletAction( portletWindow, luteceRequest, luteceResponse );
430         }
431         catch ( Throwable e )
432         {
433             AppLogService.error( AppPropertiesService.getProperty( LutecePlutoConstant.PROPERTY_LOG_PREFIX ) +
434                 " exception " + e.getClass(  ).getName(  ) + ": " + e.getMessage(  ), e );
435         }
436 
437         return true;
438     }
439 
440     /**
441      * Realise a render action (change mode and state)
442      *
443      * @param nPortletID Lutece portlet ID
444      * @return <code>true</code> for a normal processing, <code>false</code> for the need to send a redirect to the client.
445      */
446     private static boolean requestRender( int nPortletID )
447     {
448         // Restore main parameters from the ThreadLocal
449         ServletConfig config = LocalVariables.getConfig(  );
450         HttpServletRequest request = LocalVariables.getRequest(  );
451 
452         if ( !init( config ) )
453         {
454             return false;
455         }
456 
457         // Map all Lutece user info
458         prepareUserInfo( request );
459 
460         // Retrieve the portlet window
461         PlutoSession plutoSession = PlutoSession.findSession( request );
462         PortletWindowImpl portletWindow = plutoSession.getPortletWindow( String.valueOf( nPortletID ) );
463 
464         PortalURL portalURL = new PortalURL( request );
465 
466         portalURL.fillWindowPortlet( portletWindow );
467 
468         return false;
469     }
470 
471     /**
472      * Initialize user informations for current portlet
473      *
474      * @param request The HTTP request
475      */
476     private static void prepareUserInfo( HttpServletRequest request )
477     {
478         LuteceUser luteceUser = SecurityService.getInstance(  ).getRegisteredUser( request );
479 
480         if ( luteceUser != null )
481         {
482             Map mapUserInfos = luteceUser.getUserInfos(  );
483             Map cstMapUserInfos = Collections.unmodifiableMap( mapUserInfos );
484             request.setAttribute( PortletRequest.USER_INFO, cstMapUserInfos );
485         }
486         else
487         {
488             // User not identified, getAttribute on "user info" must return null 
489             request.removeAttribute( PortletRequest.USER_INFO );
490         }
491     }
492 }