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  /*
35  
36   */
37  package org.apache.pluto.invoker.impl;
38  
39  import org.apache.pluto.Constants;
40  import org.apache.pluto.PortletContainerServices;
41  import org.apache.pluto.core.CoreUtils;
42  import org.apache.pluto.core.InternalPortletRequest;
43  import org.apache.pluto.core.InternalPortletResponse;
44  import org.apache.pluto.factory.PortletObjectAccess;
45  import org.apache.pluto.invoker.PortletInvoker;
46  import org.apache.pluto.om.ControllerObjectAccess;
47  import org.apache.pluto.om.portlet.PortletDefinition;
48  import org.apache.pluto.om.portlet.PortletDefinitionCtrl;
49  import org.apache.pluto.om.servlet.ServletDefinition;
50  import org.apache.pluto.services.log.LogService;
51  import org.apache.pluto.services.log.Logger;
52  
53  import java.io.IOException;
54  
55  import java.util.HashMap;
56  import java.util.Map;
57  
58  import javax.portlet.ActionRequest;
59  import javax.portlet.ActionResponse;
60  import javax.portlet.Portlet;
61  import javax.portlet.PortletConfig;
62  import javax.portlet.PortletContext;
63  import javax.portlet.PortletException;
64  import javax.portlet.PortletRequest;
65  import javax.portlet.PortletResponse;
66  import javax.portlet.RenderRequest;
67  import javax.portlet.RenderResponse;
68  
69  import javax.servlet.RequestDispatcher;
70  import javax.servlet.ServletConfig;
71  import javax.servlet.ServletContext;
72  import javax.servlet.ServletRequest;
73  import javax.servlet.ServletResponse;
74  import javax.servlet.http.HttpServletRequest;
75  import javax.servlet.http.HttpServletRequestWrapper;
76  import javax.servlet.http.HttpServletResponse;
77  import javax.servlet.http.HttpServletResponseWrapper;
78  
79  
80  public class PortletInvokerImpl implements PortletInvoker
81  {
82      // XXX LUTECE: pour se passer de PortletServlet!	
83      static private Map _portletsStock = new HashMap(  );
84      static private Map _portletContextsStock = new HashMap(  );
85      static private Map _portletConfigsStock = new HashMap(  );
86      private ServletConfig servletConfig;
87      private PortletDefinition portletDefinition;
88  
89      /* This Logger can be saved due to the
90       * fact that a unique instance of PortletInvoker
91       * will be used for each request. We load it
92       * lazily since we only log exceptions at
93       * this point.
94       */
95      private Logger log = null;
96  
97      public PortletInvokerImpl( PortletDefinition portletDefinition, javax.servlet.ServletConfig servletConfig )
98      {
99          this.portletDefinition = portletDefinition;
100         this.servletConfig = servletConfig;
101     }
102 
103     // org.apache.pluto.invoker.PortletInvoker implementation -------------------------------------
104     public void action( ActionRequest request, ActionResponse response )
105         throws PortletException, IOException
106     {
107         invoke( request, response, Constants.METHOD_ACTION );
108     }
109 
110     public void render( RenderRequest request, RenderResponse response )
111         throws PortletException, IOException
112     {
113         invoke( request, response, Constants.METHOD_RENDER );
114     }
115 
116     public void load( PortletRequest request, RenderResponse response )
117         throws PortletException
118     {
119         try
120         {
121             invoke( request, response, Constants.METHOD_NOOP );
122         }
123         catch ( IOException e )
124         {
125             getLog(  ).error( "PortletInvokerImpl.load() - Error while dispatching portlet.", e );
126             throw new PortletException( e );
127         }
128     }
129 
130     // --------------------------------------------------------------------------------------------
131 
132     // additional methods -------------------------------------------------------------------------
133     /*
134      * generic method to be used called by both, action and render
135      */
136     protected void invoke( PortletRequest portletRequest, PortletResponse portletResponse, Integer methodID )
137         throws PortletException, IOException
138     {
139         InternalPortletRequest internalPortletRequest = CoreUtils.getInternalRequest( portletRequest );
140 
141         InternalPortletResponse internalPortletResponse = CoreUtils.getInternalResponse( portletResponse );
142 
143         // gather all required data from request and response
144         ServletRequest servletRequest = ( (HttpServletRequestWrapper) internalPortletRequest ).getRequest(  );
145 
146         ServletResponse servletResponse = ( (HttpServletResponseWrapper) internalPortletResponse ).getResponse(  );
147 
148         ServletDefinition servletDefinition = portletDefinition.getServletDefinition(  );
149         ServletContext servletContext = servletConfig.getServletContext(  );
150 
151         Portlet portlet;
152         PortletContext portletContext = null;
153         PortletConfig portletConfig = null;
154 
155         synchronized ( this )
156         {
157             portlet = (Portlet) _portletsStock.get( portletDefinition.getId(  ) );
158 
159             if ( portlet == null )
160             {
161                 try
162                 {
163                     portlet = (Portlet) Thread.currentThread(  ).getContextClassLoader(  )
164                                               .loadClass( portletDefinition.getClassName(  ) ).newInstance(  );
165                     _portletsStock.put( portletDefinition.getId(  ), portlet );
166                 }
167                 catch ( ClassNotFoundException e )
168                 {
169                     throw new PortletException( e );
170                 }
171                 catch ( IllegalAccessException e )
172                 {
173                     throw new PortletException( e );
174                 }
175                 catch ( InstantiationException e )
176                 {
177                     throw new PortletException( e );
178                 }
179             }
180             else
181             {
182                 portletContext = (PortletContext) _portletContextsStock.get( portletDefinition.getId(  ) );
183                 portletConfig = (PortletConfig) _portletConfigsStock.get( portletDefinition.getId(  ) );
184             }
185         }
186 
187         if ( portletContext == null )
188         {
189             synchronized ( portlet )
190             {
191                 portletContext = (PortletContext) _portletContextsStock.get( portletDefinition.getId(  ) );
192                 portletConfig = (PortletConfig) _portletConfigsStock.get( portletDefinition.getId(  ) );
193 
194                 if ( portletContext == null )
195                 {
196                     PortletDefinitionCtrl portletDefCtrl = (PortletDefinitionCtrl) ControllerObjectAccess.get( portletDefinition );
197                     portletDefCtrl.setPortletClassLoader( Thread.currentThread(  ).getContextClassLoader(  ) );
198 
199                     portletContext = PortletObjectAccess.getPortletContext( servletConfig.getServletContext(  ),
200                             portletDefinition.getPortletApplicationDefinition(  ) );
201                     portletConfig = PortletObjectAccess.getPortletConfig( servletConfig, portletContext,
202                             portletDefinition );
203 
204                     portlet.init( portletConfig );
205 
206                     _portletContextsStock.put( portletDefinition.getId(  ), portletContext );
207                     _portletConfigsStock.put( portletDefinition.getId(  ), portletConfig );
208                 }
209             }
210         }
211 
212         try
213         {
214             servletRequest.setAttribute( "javax.portlet.config", portletConfig );
215 
216             if ( Constants.METHOD_ACTION.equals( methodID ) )
217             {
218                 // prepare container objects to run in this webModule
219                 prepareActionRequest( (ActionRequest) internalPortletRequest, (HttpServletRequest) servletRequest );
220                 prepareActionResponse( (ActionResponse) internalPortletResponse, (HttpServletRequest) servletRequest,
221                     (HttpServletResponse) servletResponse );
222 
223                 portletRequest.setAttribute( Constants.PORTLET_REQUEST, portletRequest );
224                 portletRequest.setAttribute( Constants.PORTLET_RESPONSE, portletResponse );
225 
226                 portlet.processAction( (ActionRequest) portletRequest, (ActionResponse) portletResponse );
227             }
228             else if ( Constants.METHOD_RENDER.equals( methodID ) )
229             {
230                 // prepare container objects to run in this webModule
231                 prepareRenderRequest( (RenderRequest) internalPortletRequest, (HttpServletRequest) servletRequest );
232                 prepareRenderResponse( (RenderResponse) internalPortletResponse, (HttpServletRequest) servletRequest,
233                     (HttpServletResponse) servletResponse );
234 
235                 portletRequest.setAttribute( Constants.PORTLET_REQUEST, portletRequest );
236                 portletRequest.setAttribute( Constants.PORTLET_RESPONSE, portletResponse );
237 
238                 portlet.render( (RenderRequest) portletRequest, (RenderResponse) portletResponse );
239             }
240             else if ( Constants.METHOD_NOOP.equals( methodID ) )
241             {
242                 // RIEN A FAIRE
243             }
244         }
245         finally
246         {
247             servletRequest.removeAttribute( "javax.portlet.config" );
248         }
249     }
250 
251     // --------------------------------------------------------------------------------------------
252     private void prepareActionRequest( ActionRequest portletRequest, HttpServletRequest servletRequest )
253     {
254         InternalPortletRequest internalPortletRequest = CoreUtils.getInternalRequest( portletRequest );
255 
256         internalPortletRequest.lateInit( servletRequest );
257     }
258 
259     private void prepareRenderRequest( RenderRequest portletRequest, HttpServletRequest servletRequest )
260     {
261         InternalPortletRequest internalPortletRequest = CoreUtils.getInternalRequest( portletRequest );
262 
263         internalPortletRequest.lateInit( servletRequest );
264     }
265 
266     private void prepareRenderResponse( RenderResponse portletResponse, HttpServletRequest servletRequest,
267         HttpServletResponse servletResponse )
268     {
269         InternalPortletResponse internalPortletResponse = CoreUtils.getInternalResponse( portletResponse );
270 
271         internalPortletResponse.lateInit( servletRequest, servletResponse );
272     }
273 
274     private void prepareActionResponse( ActionResponse portletResponse, HttpServletRequest servletRequest,
275         HttpServletResponse servletResponse )
276     {
277         InternalPortletResponse internalPortletResponse = CoreUtils.getInternalResponse( portletResponse );
278 
279         internalPortletResponse.lateInit( servletRequest, servletResponse );
280     }
281 
282     /** Provides lazy instantiation of the Logger.
283     *  This is usefull since the log is currently only
284     *  used when an error occurs.  B/C of this, there is
285     *  no reason to retrieve the log until needed.
286     * @return
287     */
288     private Logger getLog(  )
289     {
290         if ( log == null )
291         {
292             // from here forward for this Container:
293             log = ( (LogService) PortletContainerServices.get( LogService.class ) ).getLogger( getClass(  ) );
294         }
295 
296         return log;
297     }
298 }