KickJava   Java API By Example, From Geeks To Geeks.

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


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 org.apache.beehive.netui.util.internal.InternalStringBuilder;
21
22 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
23 import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
24 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
25 import org.apache.beehive.netui.pageflow.handler.Handlers;
26 import org.apache.beehive.netui.pageflow.handler.FlowControllerHandlerContext;
27 import org.apache.beehive.netui.pageflow.handler.ForwardRedirectHandler;
28 import org.apache.beehive.netui.pageflow.config.PageFlowControllerConfig;
29 import org.apache.beehive.netui.util.internal.ServletUtils;
30 import org.apache.beehive.netui.util.logging.Logger;
31 import org.apache.struts.config.ModuleConfig;
32 import org.apache.struts.action.RequestProcessor;
33
34 import javax.servlet.ServletException JavaDoc;
35 import javax.servlet.ServletContext JavaDoc;
36 import javax.servlet.http.HttpServletRequest JavaDoc;
37 import javax.servlet.http.HttpServletResponse JavaDoc;
38 import java.io.Serializable JavaDoc;
39 import java.io.IOException JavaDoc;
40 import java.util.Map JavaDoc;
41 import java.util.List JavaDoc;
42 import java.util.Collection JavaDoc;
43
44
45
46 /**
47  * ActionServlet that dynamically registers modules based on naming/location conventions for Struts
48  * configuration files that are generated by the Page Flow compiler. These files are located in
49  * /WEB-INF/.pageflow-struts-generated, and are named jpf-struts-config-<i>module-name</i>.xml.
50  * For auto-registration of config files in other locations, the user may specify additional
51  * {@link ModuleConfigLocator} classes in /WEB-INF/beehive-netui-config.xml using the
52  * <code>&lt;module-config-locators&gt;</code> element.
53  */

54 public class PageFlowActionServlet extends AutoRegisterActionServlet
55 {
56     private static final Logger _log = Logger.getInstance( PageFlowActionServlet.class );
57     
58     private Handlers _handlers;
59     
60     private static final ModuleConfigLocator[] DEFAULT_MODULE_CONFIG_LOCATORS =
61             {
62                 new DefaultModuleConfigLocator(),
63                 new LegacyModuleConfigLocator()
64             };
65     
66     
67     /**
68      * Get the base list of ModuleConfigLocators, to specify locations for auto-registered Struts modules. By default,
69      * this ActionServlet auto-registers Struts modules whose configuration files are located at
70      * "/WEB-INF/.pageflow-struts-generated/jpf-struts-config-<i>&lt;module&gt;</i>". Overriding this method allows
71      * alternate locations to be specified. When an unrecognized Struts module is requested, each registered
72      * ModuleConfigLocator is queried for a possible path to the configuration file for the module. If the
73      * configuration file is found, the module is auto-registered against the file.
74      */

75     protected ModuleConfigLocator[] getDefaultModuleConfigLocators()
76     {
77         return DEFAULT_MODULE_CONFIG_LOCATORS;
78     }
79     
80     /**
81      * Default ModuleConfigLocator that looks for Struts module configuration files according to the pattern
82      * "/WEB-INF/.pageflow-struts-generated/jpf-struts-config-<i>&lt;module&gt;</i>". An instance of this class
83      * is registered by default.
84      *
85      * @see PageFlowActionServlet#getDefaultModuleConfigLocators
86      */

87     public static class DefaultModuleConfigLocator implements ModuleConfigLocator, Serializable JavaDoc
88     {
89         public String JavaDoc getModuleConfigPath( String JavaDoc moduleName )
90         {
91             InternalStringBuilder moduleConfPath = new InternalStringBuilder( getGenDir() );
92             moduleConfPath.append( '/' ).append( PageFlowConstants.PAGEFLOW_MODULE_CONFIG_PREFIX );
93             
94             if ( moduleName.length() > 1 )
95             {
96                 moduleConfPath.append( moduleName.replace( '/', '-' ) );
97             }
98             
99             moduleConfPath.append( PageFlowConstants.PAGEFLOW_MODULE_CONFIG_EXTENSION );
100             return moduleConfPath.toString();
101         }
102         
103         protected String JavaDoc getGenDir()
104         {
105             return PageFlowConstants.PAGEFLOW_MODULE_CONFIG_GEN_DIR;
106         }
107     }
108     
109     /**
110      * ModuleConfigLocator that looks for legacy Struts module configuration files according to the pattern
111      * "/WEB-INF/jpf-struts-config-<i>&lt;module&gt;</i>". An instance of this class is registered by default.
112      *
113      * @see PageFlowActionServlet#getDefaultModuleConfigLocators
114      */

115     protected static class LegacyModuleConfigLocator extends DefaultModuleConfigLocator
116     {
117         protected String JavaDoc getGenDir()
118         {
119             return InternalConstants.WEBINF_DIR;
120         }
121     }
122
123     public void init()
124             throws ServletException JavaDoc
125     {
126         //
127
// Ensure that PageFlowContextListener gets to do its initializations, even if it's not registered in web.xml.
128
//
129
ServletContext JavaDoc servletContext = getServletContext();
130         
131         if ( ! PageFlowContextListener.isInit( servletContext ) )
132         {
133             PageFlowContextListener.performInitializations( servletContext );
134         }
135         
136         _handlers = Handlers.get( servletContext );
137         
138         super.init();
139     }
140
141     protected void process( HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response )
142             throws IOException JavaDoc, ServletException JavaDoc
143     {
144         // If this is a direct request for a shared flow (.jpfs) or a Faces backing bean (.jsfb), return a 404 status.
145
// These are not web-addressable.
146
String JavaDoc servletPath = InternalUtils.getDecodedServletPath( request );
147         if ( servletPath.endsWith( InternalConstants.SHARED_FLOW_EXTENSION ) ||
148              servletPath.endsWith( InternalConstants.FACES_BACKING_EXTENSION ) )
149         {
150             if ( _log.isDebugEnabled() )
151             {
152                 _log.debug( "Attempt to hit restricted URI " + servletPath + "; 404 error returned." );
153             }
154             
155             response.sendError( HttpServletResponse.SC_NOT_FOUND );
156             return;
157         }
158         
159         // First, reinitialize the page flow classloader, for reloading when recompile occurs in dev mode.
160
FlowControllerHandlerContext handlerContext = new FlowControllerHandlerContext( request, response, null );
161         _handlers.getReloadableClassHandler().reloadClasses( handlerContext );
162         
163         super.process( request, response );
164     }
165
166     /**
167      * Get the webapp-relative path to the Struts module configration file for a given module path. By default,
168      * this is "/WEB-INF/.pageflow-struts-generated/jpf-struts-config-<i>&lt;module&gt;</i>", but alternate
169      * locations can be specified by adding {@link ModuleConfigLocator}s.
170      *
171      * @param modulePath the Struts module path.
172      * @return a String that is the path to the Struts configuration file, relative to the web application root.
173      * @see #getDefaultModuleConfigLocators
174      */

175     public String JavaDoc getModuleConfPath( String JavaDoc modulePath )
176     {
177         return super.getModuleConfPath( modulePath );
178     }
179     
180     /**
181      * Struts keeps track of the action servlet URL pattern (e.g., *.do) so it can construct action
182      * URIs. We want to prevent it from noticing *.jpf so it doesn't use that to construct the URIs.
183      *
184      * @exclude
185      */

186     public void addServletMapping( String JavaDoc servletName, String JavaDoc urlPattern )
187     {
188         if ( ! urlPattern.endsWith( PageFlowConstants.JPF_EXTENSION ) )
189         {
190             super.addServletMapping( servletName, urlPattern );
191         }
192     }
193     
194     /**
195      * Tell whether the given module can handle the given path. If this is the root module (path=="") and it's a
196      * Page Flow module, then it shouldn't try to handle any path that has a slash in it -- it only handles local
197      * actions.
198      */

199     protected boolean moduleCanHandlePath( ModuleConfig moduleConfig, RequestProcessor rp, String JavaDoc servletPath )
200     {
201         if ( moduleConfig.getPrefix().equals( "" ) && servletPath.lastIndexOf( '/' ) > 0
202              && rp instanceof PageFlowRequestProcessor )
203         {
204             return false;
205         }
206         
207         return true;
208     }
209     
210     /**
211      * Last chance to handle an unhandled action URI.
212      * @return <code>true</code> if this method handled it (by forwarding somewhere or writing to the response).
213      */

214     protected boolean processUnhandledAction( HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, String JavaDoc uri )
215         throws IOException JavaDoc, ServletException JavaDoc
216     {
217         //
218
// First check to see if we're already in a forwarded fallback request. If so, just bail.
219
//
220
PageFlowRequestWrapper rw = PageFlowRequestWrapper.get( request );
221         if ( rw.getOriginalServletPath() != null ) return false;
222         
223         SharedFlowController sharedFlowToTry = null;
224         String JavaDoc uriBaseName = ServletUtils.getBaseName( uri );
225         int firstDot = uriBaseName.indexOf( '.' );
226         int lastDot = uriBaseName.lastIndexOf( '.' );
227         
228         if ( firstDot != -1 && firstDot != lastDot )
229         {
230             String JavaDoc sharedFlowName = uriBaseName.substring( 0, firstDot );
231             
232             try
233             {
234                 RequestContext rc = new RequestContext( request, response );
235                 Map JavaDoc defaultSharedFlows = FlowControllerFactory.get( getServletContext() ).getDefaultSharedFlows( rc );
236                 
237                 if ( defaultSharedFlows != null )
238                 {
239                     sharedFlowToTry = ( SharedFlowController ) defaultSharedFlows.get( sharedFlowName );
240                     uriBaseName = uriBaseName.substring( firstDot + 1 );
241                 }
242             }
243             catch ( ClassNotFoundException JavaDoc e )
244             {
245                 throw new ServletException JavaDoc( e );
246             }
247             catch ( InstantiationException JavaDoc e )
248             {
249                 throw new ServletException JavaDoc( e );
250             }
251             catch ( IllegalAccessException JavaDoc e )
252             {
253                 throw new ServletException JavaDoc( e );
254             }
255         }
256         else
257         {
258             sharedFlowToTry = FlowControllerFactory.getGlobalApp( request, response, getServletContext() );
259         }
260         
261         //
262
// If we couldn't find an appropriate module, try raising the action on the (deprecated) Global.app.
263
//
264

265         if ( sharedFlowToTry != null )
266         {
267             InternalStringBuilder sfActionURI = new InternalStringBuilder( sharedFlowToTry.getModulePath() );
268             sfActionURI.append( '/' );
269             sfActionURI.append( uriBaseName );
270             rw.setOriginalServletPath( uri );
271             ForwardRedirectHandler frh = _handlers.getForwardRedirectHandler();
272             FlowControllerHandlerContext context = new FlowControllerHandlerContext( request, response, null );
273             frh.forward( context, sfActionURI.toString() );
274             return true;
275         }
276         
277         return false;
278     }
279 }
280
Popular Tags