KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > pageflow > PageFlowPageFilter


1 /*
2 * Copyright 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 * $Header:$
17 */

18 package org.apache.beehive.netui.pageflow;
19
20 import javax.servlet.Filter JavaDoc;
21 import javax.servlet.FilterConfig JavaDoc;
22 import javax.servlet.ServletException JavaDoc;
23 import javax.servlet.ServletRequest JavaDoc;
24 import javax.servlet.ServletResponse JavaDoc;
25 import javax.servlet.FilterChain JavaDoc;
26 import javax.servlet.ServletContext JavaDoc;
27 import javax.servlet.http.HttpServletRequest JavaDoc;
28 import javax.servlet.http.HttpServletResponse JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.Map JavaDoc;
32
33 import org.apache.struts.util.RequestUtils;
34 import org.apache.struts.util.MessageResources;
35 import org.apache.struts.action.ActionServlet;
36 import org.apache.struts.action.ActionMapping;
37 import org.apache.struts.action.ActionForm;
38 import org.apache.struts.action.ActionForward;
39 import org.apache.struts.config.ModuleConfig;
40 import org.apache.struts.Globals;
41
42 import org.apache.beehive.netui.core.urls.URLRewriterService;
43 import org.apache.beehive.netui.util.logging.Logger;
44 import org.apache.beehive.netui.util.internal.FileUtils;
45 import org.apache.beehive.netui.util.internal.ServletUtils;
46 import org.apache.beehive.netui.pageflow.internal.DefaultURLRewriter;
47 import org.apache.beehive.netui.pageflow.internal.JavaControlUtils;
48 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
49 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
50 import org.apache.beehive.netui.pageflow.internal.AdapterManager;
51 import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
52 import org.apache.beehive.netui.script.common.ImplicitObjectUtil;
53
54
55 /**
56  * Base class for Servlet Filters that run before Page Flow page requests.
57  */

58 public abstract class PageFlowPageFilter implements Filter JavaDoc
59 {
60     private ServletContext JavaDoc _servletContext;
61     private ServletContainerAdapter _servletContainerAdapter;
62     private FlowControllerFactory _flowControllerFactory;
63     
64     private static final Logger _log = Logger.getInstance( PageFlowPageFilter.class );
65     
66     private static final String JavaDoc PREVENT_CACHE_ATTR = InternalConstants.ATTR_PREFIX + "preventCache";
67     
68     
69     protected PageFlowPageFilter()
70     {
71     }
72     
73     PageFlowPageFilter( ServletContext JavaDoc servletContext )
74     {
75         _servletContext = servletContext;
76         _servletContainerAdapter = AdapterManager.getServletContainerAdapter( _servletContext );
77         _flowControllerFactory = FlowControllerFactory.get( servletContext );
78     }
79
80     public void init( FilterConfig JavaDoc filterConfig ) throws ServletException JavaDoc
81     {
82         _servletContext = filterConfig.getServletContext();
83         
84         if ( ! PageFlowContextListener.isInit( _servletContext ) )
85         {
86             PageFlowContextListener.performInitializations( _servletContext );
87         }
88         
89         _servletContainerAdapter = AdapterManager.getServletContainerAdapter( _servletContext );
90         _flowControllerFactory = FlowControllerFactory.get( _servletContext );
91     }
92     
93     protected abstract Set JavaDoc getValidFileExtensions();
94     
95     public void doFilter( ServletRequest JavaDoc request, ServletResponse JavaDoc response, FilterChain JavaDoc chain )
96             throws IOException JavaDoc, ServletException JavaDoc
97     {
98         if ( request instanceof HttpServletRequest JavaDoc && response instanceof HttpServletResponse JavaDoc )
99         {
100             HttpServletRequest JavaDoc httpRequest = ( HttpServletRequest JavaDoc ) request;
101             HttpServletResponse JavaDoc httpResponse = ( HttpServletResponse JavaDoc ) response;
102             
103             //
104
// Don't do the filter if the request is in error.
105
//
106
Object JavaDoc errStatusCode = request.getAttribute( "javax.servlet.error.status_code" );
107             if ( errStatusCode != null )
108             {
109                 if ( _log.isDebugEnabled() )
110                 {
111                     _log.debug( "Request has error status code " + errStatusCode + ". Skipping filter." );
112                 }
113                 
114                 chain.doFilter( request, response );
115                 return;
116             }
117             
118             String JavaDoc servletPath = InternalUtils.getDecodedServletPath( httpRequest );
119             String JavaDoc extension = FileUtils.getFileExtension( servletPath );
120             Set JavaDoc validFileExtensions = getValidFileExtensions();
121             
122             if ( validFileExtensions != null && ! validFileExtensions.contains( extension ) )
123             {
124                 if ( _log.isDebugEnabled() )
125                 {
126                     _log.debug( "Path " + servletPath +
127                                 " does not have an appropriate file extension. Skipping filter." );
128                 }
129                 
130                 chain.doFilter( request, response );
131                 return;
132             }
133             
134             if ( _log.isDebugEnabled() ) _log.debug( "Filtering request for path " + servletPath );
135             
136             //
137
// If at an earlier stage in the request we determined that we should prevent caching,
138
// actually write the appropriate headers to the response now.
139
//
140
if ( request.getAttribute( PREVENT_CACHE_ATTR ) != null ) ServletUtils.preventCache( httpResponse );
141             
142             //
143
// Initialize the ServletContext in the request. Often, we need access to the ServletContext when we only
144
// have a ServletRequest.
145
//
146
InternalUtils.setServletContext( httpRequest, _servletContext );
147             
148             //
149
// Callback to the server adapter.
150
//
151
PageFlowEventReporter er = _servletContainerAdapter.getEventReporter();
152             _servletContainerAdapter.beginRequest( httpRequest, httpResponse );
153             er.beginPageRequest( httpRequest, httpResponse );
154             long startTime = System.currentTimeMillis();
155             
156             //
157
// Initialize the ControlBeanContext in the session.
158
//
159
JavaControlUtils.initializeControlContext( httpRequest, httpResponse, _servletContext );
160
161             //
162
// Register the default URLRewriter
163
//
164
URLRewriterService.registerURLRewriter( 0, request, new DefaultURLRewriter() );
165
166             try
167             {
168                 ModuleConfig prevModuleConfig = RequestUtils.getRequestModuleConfig( httpRequest );
169                 MessageResources prevMessageResources = ( MessageResources ) request.getAttribute( Globals.MESSAGES_KEY );
170                 initializeModule( httpRequest, httpResponse );
171                 
172                 try
173                 {
174                     //
175
// Initialize shared flows for the current request.
176
//
177
RequestContext requestContext = new RequestContext( request, response );
178                     Map JavaDoc/*< String, SharedFlowController >*/ sharedFlows =
179                             _flowControllerFactory.getSharedFlowsForRequest( requestContext );
180                     ImplicitObjectUtil.loadSharedFlow( request, sharedFlows );
181                     ImplicitObjectUtil.loadGlobalApp( request, PageFlowUtils.getGlobalApp( httpRequest ) );
182                     
183                     //
184
// Make sure that the current PageFlowController is set up for this request.
185
//
186
PageFlowController curJpf = _flowControllerFactory.getPageFlowForRequest( requestContext );
187                     
188                     //
189
// If there is no pageflow for the current Struts module, than fall back to default
190
// Struts behavior, which is *not* to allow a page request to set the current module.
191
//
192
if ( curJpf == null )
193                     {
194                         InternalUtils.setCurrentModule( prevModuleConfig, request );
195                         request.setAttribute( Globals.MESSAGES_KEY, prevMessageResources );
196                     }
197                     
198                     
199                     if ( _log.isDebugEnabled() )
200                     {
201                         _log.debug( "Current PageFlowController is: " + curJpf );
202                         _log.debug( "Continuing with filter chain..." );
203                     }
204                     
205                     runPage( curJpf, httpRequest, httpResponse, chain );
206                 }
207                 catch ( ClassNotFoundException JavaDoc e )
208                 {
209                     throw new ServletException JavaDoc( e );
210                 }
211                 catch ( InstantiationException JavaDoc e )
212                 {
213                     throw new ServletException JavaDoc( e );
214                 }
215                 catch ( IllegalAccessException JavaDoc e )
216                 {
217                     throw new ServletException JavaDoc( e );
218                 }
219             }
220             finally
221             {
222                 //
223
// Clean up the ControlBeanContext in the session.
224
//
225
JavaControlUtils.uninitializeControlContext( httpRequest, httpResponse, _servletContext );
226                 
227                 //
228
// Callback to the server adapter.
229
//
230
_servletContainerAdapter.endRequest( httpRequest, httpResponse );
231                 long timeTaken = System.currentTimeMillis() - startTime;
232                 er.endPageRequest( httpRequest, httpResponse, timeTaken );
233             }
234         }
235         else
236         {
237             chain.doFilter( request, response );
238         }
239     }
240     
241     private void runPage( PageFlowController curJpf, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response,
242                           FilterChain JavaDoc chain )
243         throws IOException JavaDoc, ServletException JavaDoc
244     {
245         //
246
// Make sure that the pageflow's getRequest() and getResponse() will work while the page
247
// is being rendered, since methods on the pageflow may be called (through databinding
248
// or tags, or through direct reference).
249
//
250
if ( curJpf != null )
251         {
252             //
253
// We're going to bail out if there are too many concurrent requests for the same JPF.
254
// This prevents an attack that takes advantage of the fact that we synchronize requests
255
// to the same pageflow.
256
//
257
if ( curJpf.incrementRequestCount( request, response, _servletContext ) )
258             {
259                 try
260                 {
261                     //
262
// Any databinding calls, indirect calls to getRequest(), etc. must be protected
263
// against conflicts from running action methods at the same time as rendering
264
// the page here. Synchronize on the JPF.
265
//
266
synchronized ( curJpf )
267                     {
268                         FlowController.PerRequestState newState =
269                                 new FlowController.PerRequestState( request, response, null );
270                         FlowController.PerRequestState prevState = curJpf.setPerRequestState( newState );
271                         ImplicitObjectUtil.loadImplicitObjects( request, response, _servletContext, curJpf );
272                                 
273                         //
274
// Tell the page flow that we're about to display a page so it can manage settings,
275
// such as previous page information, if needed in advance.
276
//
277
curJpf.beforePage();
278                                 
279                         try
280                         {
281                             chain.doFilter( request, response );
282                         }
283                         catch ( ServletException JavaDoc servletEx )
284                         {
285                             //
286
// If a ServletException escapes out of the page, let the current FlowController handle it.
287
//
288
if ( ! handleException( servletEx, curJpf, request, response ) ) throw servletEx;
289                         }
290                         catch ( IOException JavaDoc ioe )
291                         {
292                             //
293
// If an IOException escapes out of the page, let the current FlowController handle it.
294
//
295
if ( ! handleException( ioe, curJpf, request, response ) ) throw ioe;
296                         }
297                         catch ( Throwable JavaDoc th )
298                         {
299                             //
300
// If a Throwable escapes out of the page, let the current FlowController handle it.
301
//
302
if ( ! handleException( th, curJpf, request, response ) ) throw new ServletException JavaDoc( th );
303                         }
304                         finally
305                         {
306                             curJpf.setPerRequestState( prevState );
307                         }
308                     }
309                 }
310                 finally
311                 {
312                     curJpf.decrementRequestCount( request );
313                 }
314             }
315         }
316         else
317         {
318             ImplicitObjectUtil.loadImplicitObjects( request, response, _servletContext, null );
319             
320             //
321
// Remove our request wrapper -- the page doesn't need to see this.
322
//
323
if ( request instanceof PageFlowRequestWrapper )
324             {
325                 request = ( ( PageFlowRequestWrapper ) request ).getHttpRequest();
326             }
327             
328             chain.doFilter( request, response );
329         }
330     }
331     
332     private boolean handleException( Throwable JavaDoc th, FlowController fc, HttpServletRequest JavaDoc request,
333                                      HttpServletResponse JavaDoc response )
334     {
335         try
336         {
337             ActionMapping mapping = InternalUtils.getCurrentActionMapping( request );
338             ActionForm form = InternalUtils.getCurrentActionForm( request );
339             ActionForward fwd = fc.handleException( th, mapping, form, request, response );
340             fc.getRequestProcessor().doActionForward( request, response, fwd );
341             return true;
342         }
343         catch ( Throwable JavaDoc t )
344         {
345             _log.error( "Exception while handling exception " + th.getClass().getName()
346                         + ". The original exception will be thrown.", th );
347             return false;
348         }
349     }
350     
351     private void initializeModule( HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response )
352         throws IOException JavaDoc, ServletException JavaDoc
353     {
354         //
355
// Ensure that the right Struts module is selected, for use by the tags.
356
//
357
String JavaDoc curModulePath = PageFlowUtils.getModulePath( request );
358         ActionServlet as = InternalUtils.getActionServlet( _servletContext );
359                 
360         if ( as instanceof AutoRegisterActionServlet )
361         {
362             AutoRegisterActionServlet das = ( AutoRegisterActionServlet ) as;
363             das.ensureModuleRegistered( curModulePath, request );
364         }
365                 
366         ModuleConfig mc = InternalUtils.selectModule( curModulePath, request, _servletContext );
367                     
368         if ( mc == null )
369         {
370             //
371
// If we still haven't had success in selecting the module, see if we can dynamically register one.
372
//
373
if ( as instanceof AutoRegisterActionServlet )
374             {
375                 AutoRegisterActionServlet das = ( AutoRegisterActionServlet ) as;
376                 das.ensureModuleSelected( curModulePath, request, response );
377             }
378         }
379     }
380     
381     /**
382      * Make sure that when this page is rendered, it will set headers in the response to prevent caching.
383      * Because these headers are lost on server forwards, we set a request attribute to cause the headers
384      * to be set right before the page is rendered.
385      */

386     static void preventCache( HttpServletRequest JavaDoc request )
387     {
388         request.setAttribute( PREVENT_CACHE_ATTR, Boolean.TRUE );
389     }
390     
391     public void destroy()
392     {
393         _servletContext = null;
394     }
395 }
396
Popular Tags