Source Code Cross Referenced for FlowController.java in  » Library » Apache-beehive-1.0.2-src » org » apache » beehive » netui » pageflow » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache beehive 1.0.2 src » org.apache.beehive.netui.pageflow 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         *
0017:         * $Header:$
0018:         */
0019:        package org.apache.beehive.netui.pageflow;
0020:
0021:        import org.apache.beehive.netui.core.urls.MutableURI;
0022:        import org.apache.beehive.netui.pageflow.config.PageFlowActionMapping;
0023:        import org.apache.beehive.netui.pageflow.config.PageFlowExceptionConfig;
0024:        import org.apache.beehive.netui.pageflow.handler.ActionForwardHandler;
0025:        import org.apache.beehive.netui.pageflow.handler.ExceptionsHandler;
0026:        import org.apache.beehive.netui.pageflow.handler.FlowControllerHandlerContext;
0027:        import org.apache.beehive.netui.pageflow.handler.Handlers;
0028:        import org.apache.beehive.netui.pageflow.handler.LoginHandler;
0029:        import org.apache.beehive.netui.pageflow.internal.*;
0030:        import org.apache.beehive.netui.pageflow.scoping.ScopedRequest;
0031:        import org.apache.beehive.netui.util.internal.FileUtils;
0032:        import org.apache.beehive.netui.util.internal.InternalStringBuilder;
0033:        import org.apache.beehive.netui.util.internal.cache.ClassLevelCache;
0034:        import org.apache.beehive.netui.util.logging.Logger;
0035:        import org.apache.struts.Globals;
0036:        import org.apache.struts.action.ActionForm;
0037:        import org.apache.struts.action.ActionForward;
0038:        import org.apache.struts.action.ActionMapping;
0039:        import org.apache.struts.action.ActionMessage;
0040:        import org.apache.struts.action.ActionMessages;
0041:        import org.apache.struts.action.ActionServlet;
0042:        import org.apache.struts.action.RequestProcessor;
0043:        import org.apache.struts.config.ActionConfig;
0044:        import org.apache.struts.config.ControllerConfig;
0045:        import org.apache.struts.config.ModuleConfig;
0046:        import org.apache.struts.util.MessageResources;
0047:        import org.apache.struts.util.RequestUtils;
0048:        import org.apache.struts.util.TokenProcessor;
0049:
0050:        import javax.security.auth.login.LoginException;
0051:        import javax.servlet.ServletContext;
0052:        import javax.servlet.ServletException;
0053:        import javax.servlet.http.HttpServletRequest;
0054:        import javax.servlet.http.HttpServletResponse;
0055:        import javax.servlet.http.HttpSession;
0056:        import javax.sql.DataSource;
0057:        import java.io.IOException;
0058:        import java.lang.reflect.Field;
0059:        import java.lang.reflect.InvocationTargetException;
0060:        import java.lang.reflect.Method;
0061:        import java.lang.reflect.Modifier;
0062:        import java.net.URISyntaxException;
0063:        import java.util.ArrayList;
0064:        import java.util.Iterator;
0065:        import java.util.Locale;
0066:        import java.util.Map;
0067:        import java.security.Principal;
0068:
0069:        /**
0070:         * Base class for user-written flow controllers - {@link PageFlowController}s and {@link SharedFlowController}s.
0071:         */
0072:        public abstract class FlowController extends PageFlowManagedObject
0073:                implements  PageFlowConstants, ActionResolver {
0074:            private static final Logger _log = Logger
0075:                    .getInstance(FlowController.class);
0076:
0077:            private static final String ONCREATE_EXCEPTION_FORWARD = InternalConstants.ATTR_PREFIX
0078:                    + "onCreateException";
0079:            private static final String CACHEID_ACTION_METHODS = InternalConstants.ATTR_PREFIX
0080:                    + "actionMethods";
0081:            private static final int DEFAULT_MAX_CONCURRENT_REQUEST_COUNT = 4;
0082:            private static final String MAX_CONCURRENT_REQUESTS_PARAM = "pageflow-max-concurrent-requests";
0083:            private static final int EXCEEDED_MAX_CONCURRENT_REQUESTS_ERRORCODE = 503;
0084:            private static final Locale DEFAULT_LOCALE = Locale.getDefault();
0085:            private static final ActionForward NULL_ACTION_FORWARD = new ActionForward();
0086:            private static final TokenProcessor TOKEN_PROCESSOR = TokenProcessor
0087:                    .getInstance();
0088:
0089:            /**
0090:             * The system default Locale.
0091:             * 
0092:             * @deprecated Use {@link #getDefaultLocale}.
0093:             */
0094:            protected static Locale defaultLocale = DEFAULT_LOCALE;
0095:
0096:            static class PerRequestState {
0097:                private HttpServletRequest _request;
0098:                private HttpServletResponse _response;
0099:                private ActionMapping _actionMapping;
0100:
0101:                public PerRequestState(HttpServletRequest request,
0102:                        HttpServletResponse response,
0103:                        ActionMapping actionMapping) {
0104:                    _request = request;
0105:                    _response = response;
0106:                    _actionMapping = actionMapping;
0107:                }
0108:
0109:                public HttpServletRequest getRequest() {
0110:                    return _request;
0111:                }
0112:
0113:                public HttpServletResponse getResponse() {
0114:                    return _response;
0115:                }
0116:
0117:                public ActionMapping getActionMapping() {
0118:                    return _actionMapping;
0119:                }
0120:            }
0121:
0122:            /**
0123:             * Stores per-request state, which is <i>only valid during calls to {@link FlowController#execute} or {@link FlowController#handleException}</i>.
0124:             */
0125:            private transient PerRequestState _perRequestState;
0126:
0127:            /**
0128:             * Cached reference to the associated Struts ModuleConfig.
0129:             */
0130:            private transient ModuleConfig _moduleConfig = null;
0131:
0132:            /**
0133:             * @see #incrementRequestCount
0134:             */
0135:            private transient int _requestCount = 0;
0136:
0137:            /**
0138:             * @see #incrementRequestCount
0139:             */
0140:            private static int _maxConcurrentRequestCount = -1;
0141:
0142:            /**
0143:             * Default constructor.
0144:             */
0145:            protected FlowController() {
0146:            }
0147:
0148:            /**
0149:             * Reinitialize the object for a new request.  Used by the framework; normally should not be called directly.
0150:             */
0151:            public void reinitialize(HttpServletRequest request,
0152:                    HttpServletResponse response, ServletContext servletContext) {
0153:                //
0154:                // Cache the associated ModuleConfig.  This is used throughout the code, in places where the request
0155:                // isn't available to do a lazy initialization.
0156:                //
0157:                super .reinitialize(request, response, servletContext);
0158:            }
0159:
0160:            /**
0161:             * Log in the user, using "weak" username/password authentication.  Goes through a custom {@link LoginHandler}, if
0162:             * one has been configured in beehive-netui-config.xml.
0163:             *
0164:             * @param username the user's login name
0165:             * @param password the user's password
0166:             * 
0167:             * @exception LoginException if the authentication failed
0168:             */
0169:            public void login(String username, String password)
0170:                    throws LoginException {
0171:                LoginHandler lh = Handlers.get(getServletContext())
0172:                        .getLoginHandler();
0173:                lh.login(getHandlerContext(), username, password);
0174:            }
0175:
0176:            /**
0177:             * Log out the current user.  Goes through a custom {@link LoginHandler}, if one has been configured in
0178:             * beehive-netui-config.xml.
0179:             * 
0180:             * @param invalidateSessions if true, the session is invalidated (on all single-signon webapps); 
0181:             *            otherwise the session and its data are left intact (except for authentication
0182:             *            information used internally by the server).  To invalidate the session in only the
0183:             *            current webapp, set this parameter to <code>false</code> and call
0184:             *            {@link FlowController#getSession}.invalidate().
0185:             */
0186:            public void logout(boolean invalidateSessions) {
0187:                LoginHandler lh = Handlers.get(getServletContext())
0188:                        .getLoginHandler();
0189:                lh.logout(getHandlerContext(), invalidateSessions);
0190:            }
0191:
0192:            /**
0193:             * Get the current logged-in user.  Goes through a custom {@link LoginHandler}, if one has been configured in
0194:             * beehive-netui-config.xml.
0195:             * 
0196:             * @return the current logged-in <code>Principal</code>, or <code>null</code> if there is no logged-in user.
0197:             */
0198:            public Principal getUserPrincipal() {
0199:                LoginHandler lh = Handlers.get(getServletContext())
0200:                        .getLoginHandler();
0201:                return lh.getUserPrincipal(getHandlerContext());
0202:            }
0203:
0204:            /**
0205:             * Tell whether the current logged-in user is a member of a given role.  Goes through a custom {@link LoginHandler},
0206:             * if one has been configured in beehive-netui-config.xml.
0207:             * 
0208:             * @param roleName the name of the role to test.
0209:             * @return <code>true</code> if there is a current logged-in user and the user is a member of the given role.
0210:             * @see #getUserPrincipal
0211:             */
0212:            public boolean isUserInRole(String roleName) {
0213:                LoginHandler lh = Handlers.get(getServletContext())
0214:                        .getLoginHandler();
0215:                return lh.isUserInRole(getHandlerContext(), roleName);
0216:            }
0217:
0218:            /**
0219:             * Send a Page Flow error to the browser.
0220:             * 
0221:             * @deprecated Use {@link FlowController#sendError(String, HttpServletRequest, HttpServletResponse)} instead.
0222:             * @param errText the error message to display.
0223:             * @param response the current HttpServletResponse.
0224:             */
0225:            protected void sendError(String errText,
0226:                    HttpServletResponse response) throws IOException {
0227:                sendError(errText, null, response);
0228:            }
0229:
0230:            /**
0231:             * Send a Page Flow error to the browser.
0232:             * 
0233:             * @param errText the error message to display.
0234:             * @param response the current HttpServletResponse.
0235:             */
0236:            protected void sendError(String errText,
0237:                    HttpServletRequest request, HttpServletResponse response)
0238:                    throws IOException {
0239:                InternalUtils.sendError("PageFlow_Custom_Error", null, request,
0240:                        response, new Object[] { getDisplayName(), errText });
0241:            }
0242:
0243:            /**
0244:             * Handle the given exception - invoke user code if appropriate and return a destination URI.
0245:             * 
0246:             * @param ex the Exception to handle.
0247:             * @param mapping the Struts action mapping for current Struts action being processed.
0248:             * @param form the form-bean (if any) associated with the Struts action being processed.  May be null.
0249:             * @param request the current HttpServletRequest.
0250:             * @param response the current HttpServletResponse.
0251:             * @return a Struts ActionForward object that specifies the URI that should be displayed.
0252:             * @throws ServletException if another Exception is thrown during handling of <code>ex</code>.
0253:             */
0254:            public synchronized ActionForward handleException(Throwable ex,
0255:                    ActionMapping mapping, ActionForm form,
0256:                    HttpServletRequest request, HttpServletResponse response)
0257:                    throws IOException, ServletException {
0258:                PerRequestState prevState = setPerRequestState(new PerRequestState(
0259:                        request, response, mapping));
0260:
0261:                try {
0262:                    ExceptionsHandler eh = Handlers.get(getServletContext())
0263:                            .getExceptionsHandler();
0264:                    FlowControllerHandlerContext context = getHandlerContext();
0265:
0266:                    // First, put the exception into the request (or other applicable context).
0267:                    Throwable unwrapped = eh.unwrapException(context, ex);
0268:                    eh.exposeException(context, unwrapped, mapping);
0269:                    return eh
0270:                            .handleException(context, unwrapped, mapping, form);
0271:                } finally {
0272:                    setPerRequestState(prevState);
0273:                }
0274:            }
0275:
0276:            /**
0277:             * Get the name of the current action being executed.  This call is only valid
0278:             * during {@link FlowController#execute} (where any user action method is invoked), and during the lifecycle
0279:             * methods {@link FlowController#beforeAction} and {@link FlowController#afterAction}.
0280:             * 
0281:             * @return the name of the current action being executed.
0282:             * @throws IllegalStateException if this method is invoked outside of action method
0283:             *             execution (i.e., outside of the call to {@link FlowController#execute}, and outside of
0284:             *             {@link FlowController#onCreate}, {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
0285:             */
0286:
0287:            protected String getCurrentActionName() {
0288:                return InternalUtils.getActionName(getActionMapping());
0289:            }
0290:
0291:            /**
0292:             * Perform decision logic to determine the next URI to be displayed.
0293:             * 
0294:             * @param mapping the Struts ActionMapping for the current action being processed.
0295:             * @param form the form-bean (if any) associated with the Struts action being processed.  May be null.
0296:             * @param request the current HttpServletRequest.
0297:             * @param response the current HttpServletResponse.
0298:             * @return a Struts ActionForward object that specifies the next URI to be displayed.
0299:             * @throws Exception if an Exception was thrown during user action-handling code.
0300:             */
0301:            public ActionForward execute(ActionMapping mapping,
0302:                    ActionForm form, HttpServletRequest request,
0303:                    HttpServletResponse response) throws Exception {
0304:                //
0305:                // Don't actually run the action (and perform the associated synchronization) if there are too many
0306:                // concurrent requests to this instance.
0307:                //
0308:                if (incrementRequestCount(request, response,
0309:                        getServletContext())) {
0310:                    try {
0311:                        // netui:sync-point
0312:                        synchronized (this ) {
0313:                            ActionForward ret = null;
0314:
0315:                            // establish the control context for running the beginAction, Action, afterAction code
0316:                            PageFlowControlContainer pfcc = null;
0317:                            try {
0318:                                pfcc = PageFlowControlContainerFactory
0319:                                        .getControlContainer(request,
0320:                                                getServletContext());
0321:                                pfcc.beginContextOnPageFlow(this , request,
0322:                                        response, getServletContext());
0323:                            } catch (Exception e) {
0324:                                return handleException(e, mapping, form,
0325:                                        request, response);
0326:                            }
0327:
0328:                            try {
0329:                                // execute the beginAction, Action, afterAction code
0330:                                ret = internalExecute(mapping, form, request,
0331:                                        response);
0332:                            } finally {
0333:                                try {
0334:                                    pfcc.endContextOnPageFlow(this );
0335:                                } catch (Exception e) {
0336:                                    // if already handling an exception during execute, then just log
0337:                                    PageFlowRequestWrapper rw = PageFlowRequestWrapper
0338:                                            .get(request);
0339:                                    Throwable alreadyBeingHandled = rw
0340:                                            .getExceptionBeingHandled();
0341:                                    if (alreadyBeingHandled != null) {
0342:                                        _log
0343:                                                .error(
0344:                                                        "Exception thrown while ending context on page flow in execute()",
0345:                                                        e);
0346:                                    } else {
0347:                                        return handleException(e, mapping,
0348:                                                form, request, response);
0349:                                    }
0350:                                }
0351:                            }
0352:                            return ret;
0353:                        }
0354:                    } finally {
0355:                        decrementRequestCount(request);
0356:                    }
0357:                } else {
0358:                    return null; // error was written to the response by incrementRequestCount()
0359:                }
0360:            }
0361:
0362:            /**
0363:             * Internal method used to execute an action on a FlowController.  This is where the magic generally happens as
0364:             * the {@link #beforeAction()}, login, action execution (simple and normal), and {@link #afterAction()} are
0365:             * all executed by this method.  This method is considered <i>internal</i> and should not be invoked direclty.
0366:             */
0367:            protected ActionForward internalExecute(ActionMapping mapping,
0368:                    ActionForm form, HttpServletRequest request,
0369:                    HttpServletResponse response) throws Exception {
0370:                ServletContainerAdapter sca = AdapterManager
0371:                        .getServletContainerAdapter(getServletContext());
0372:                PageFlowEventReporter eventReporter = sca.getEventReporter();
0373:                RequestContext requestContext = new RequestContext(request,
0374:                        response);
0375:                eventReporter.actionRaised(requestContext, this , mapping, form);
0376:                long startTime = System.currentTimeMillis();
0377:
0378:                //
0379:                // If we handled an exception in onCreate, just forward to the result of that.
0380:                //
0381:                ActionForward onCreateFwd = (ActionForward) request
0382:                        .getAttribute(ONCREATE_EXCEPTION_FORWARD);
0383:
0384:                if (onCreateFwd != null) {
0385:                    return onCreateFwd == NULL_ACTION_FORWARD ? null
0386:                            : onCreateFwd;
0387:                }
0388:
0389:                PageFlowUtils.setActionURI(request);
0390:
0391:                //
0392:                // First change the actionPath (path) so that it lines up with our naming convention
0393:                // for action methods.
0394:                //
0395:                boolean gotPastBeforeAction = false;
0396:                ServletContext servletContext = getServletContext();
0397:                PerRequestState prevState = setPerRequestState(new PerRequestState(
0398:                        request, response, mapping));
0399:
0400:                try {
0401:                    //
0402:                    // beforeAction callback
0403:                    //
0404:                    beforeAction();
0405:                    gotPastBeforeAction = true;
0406:
0407:                    PageFlowActionMapping pfActionMapping = mapping instanceof  PageFlowActionMapping ? (PageFlowActionMapping) mapping
0408:                            : null;
0409:                    Object unwrappedForm = InternalUtils.unwrapFormBean(form);
0410:
0411:                    //
0412:                    // mapping.isOverloaded() means it's the base mapping for a set of overloaded mappings.
0413:                    // Find the one appropriate to the passed-in form.
0414:                    //
0415:                    if (unwrappedForm != null && pfActionMapping != null) {
0416:                        if (pfActionMapping.isOverloaded()) {
0417:                            String mappingPath = pfActionMapping.getPath();
0418:
0419:                            //
0420:                            // Try the form class and all superclasses to get an overloaded action path.
0421:                            //
0422:                            for (Class i = unwrappedForm.getClass(); i != null; i = i
0423:                                    .getSuperclass()) {
0424:                                String formQualifiedActionPath = getFormQualifiedActionPath(
0425:                                        i, mappingPath);
0426:                                ActionConfig cf = pfActionMapping
0427:                                        .getModuleConfig().findActionConfig(
0428:                                                formQualifiedActionPath);
0429:
0430:                                if (cf != null) {
0431:                                    assert cf instanceof  PageFlowActionMapping : cf
0432:                                            .getClass().getName();
0433:
0434:                                    if (_log.isDebugEnabled()) {
0435:                                        _log
0436:                                                .debug("Found form-specific mapping "
0437:                                                        + cf.getPath()
0438:                                                        + " -- choosing this one over current mapping "
0439:                                                        + mappingPath);
0440:                                    }
0441:
0442:                                    pfActionMapping = (PageFlowActionMapping) cf;
0443:                                    mapping = pfActionMapping;
0444:                                    break;
0445:                                }
0446:                            }
0447:                        }
0448:                    }
0449:
0450:                    String actionName = InternalUtils.getActionName(mapping);
0451:
0452:                    //
0453:                    // Check whether isLoginRequired=true for this action.
0454:                    //
0455:                    LoginHandler loginHandler = Handlers.get(
0456:                            getServletContext()).getLoginHandler();
0457:
0458:                    if (pfActionMapping != null
0459:                            && pfActionMapping.isLoginRequired()
0460:                            && loginHandler
0461:                                    .getUserPrincipal(getHandlerContext()) == null) {
0462:                        NotLoggedInException ex = createNotLoggedInException(
0463:                                actionName, request);
0464:                        return handleException(ex, mapping, form, request,
0465:                                response);
0466:                    }
0467:
0468:                    //
0469:                    // Now delegate to the appropriate action method, or if it's a simple action, handle it that way.
0470:                    //
0471:                    ActionForward retVal;
0472:                    if (pfActionMapping != null
0473:                            && pfActionMapping.isSimpleAction()) {
0474:                        retVal = handleSimpleAction(pfActionMapping, form,
0475:                                request, servletContext);
0476:                    } else {
0477:                        retVal = getActionMethodForward(actionName,
0478:                                unwrappedForm, request, response, mapping);
0479:                    }
0480:
0481:                    ActionForward ret = forwardTo(retVal, mapping, null,
0482:                            actionName, null, form, request, response,
0483:                            servletContext);
0484:                    long timeTaken = System.currentTimeMillis() - startTime;
0485:                    eventReporter.actionSuccess(requestContext, this , mapping,
0486:                            form, ret, timeTaken);
0487:                    return ret;
0488:                } catch (Exception e) {
0489:                    //
0490:                    // Even though we handle any Throwable thrown by the user's action method, we don't need
0491:                    // to catch Throwable here, because anything thrown by the action method will be wrapped
0492:                    // in an InvocationTargetException.  Any Error (or other Throwable) that appears here
0493:                    // should not be handled by handleException() -- it's probably a framework problem and
0494:                    // should bubble out to the container.
0495:                    //
0496:                    return handleException(e, mapping, form, request, response);
0497:                } finally {
0498:                    try {
0499:                        ActionForward overrideReturn = null;
0500:
0501:                        if (gotPastBeforeAction) {
0502:                            //
0503:                            // afterAction callback
0504:                            //
0505:                            try {
0506:                                afterAction();
0507:                            } catch (Throwable th) {
0508:                                overrideReturn = handleException(th, mapping,
0509:                                        form, request, response);
0510:                            }
0511:                        }
0512:
0513:                        //
0514:                        // Store information on this action for use with navigateTo=Jpf.NavigateTo.previousAction.
0515:                        //
0516:                        savePreviousActionInfo(form, request, mapping,
0517:                                getServletContext());
0518:
0519:                        if (overrideReturn != null) {
0520:                            return overrideReturn;
0521:                        }
0522:                    } finally {
0523:                        setPerRequestState(prevState);
0524:                    }
0525:                }
0526:            }
0527:
0528:            ActionForward forwardTo(ActionForward fwd, ActionMapping mapping,
0529:                    PageFlowExceptionConfig exceptionConfig, String actionName,
0530:                    ModuleConfig altModuleConfig, ActionForm form,
0531:                    HttpServletRequest request, HttpServletResponse response,
0532:                    ServletContext servletContext) {
0533:                // This method is overridden in PageFlowController. Even though we're just delegating here, we can't remove it.
0534:                ActionForwardHandler handler = Handlers.get(servletContext)
0535:                        .getActionForwardHandler();
0536:                FlowControllerHandlerContext context = new FlowControllerHandlerContext(
0537:                        request, response, this );
0538:                return handler.processForward(context, fwd, mapping,
0539:                        exceptionConfig, actionName, altModuleConfig, form);
0540:            }
0541:
0542:            NotLoggedInException createNotLoggedInException(String actionName,
0543:                    HttpServletRequest request) {
0544:                if (InternalUtils.sessionExpired(request)) {
0545:                    return new LoginExpiredException(actionName, this );
0546:                } else {
0547:                    return new NotLoggedInException(actionName, this );
0548:                }
0549:            }
0550:
0551:            /**
0552:             * Initialize after object creation.  This is a framework-invoked method; it should not normally be called directly.
0553:             */
0554:            public synchronized void create(HttpServletRequest request,
0555:                    HttpServletResponse response, ServletContext servletContext) {
0556:                PerRequestState prevState = setPerRequestState(new PerRequestState(
0557:                        request, response, null));
0558:
0559:                try {
0560:                    try {
0561:                        // we start the context on the bean so user control can run against Controls in the onCreate() method
0562:                        super .create(request, response, servletContext);
0563:                    } catch (Throwable th) {
0564:                        try {
0565:                            _log.info(
0566:                                    "Handling exception in onCreate(), FlowController "
0567:                                            + this , th);
0568:                            reinitialize(request, response, servletContext);
0569:                            ActionForward fwd = handleException(th, null, null,
0570:                                    request, response);
0571:                            if (fwd == null)
0572:                                fwd = NULL_ACTION_FORWARD;
0573:                            request.setAttribute(ONCREATE_EXCEPTION_FORWARD,
0574:                                    fwd);
0575:                        } catch (Exception e) {
0576:                            _log.error(
0577:                                    "Exception thrown while handling exception in onCreate(): "
0578:                                            + e.getMessage(), th);
0579:                        }
0580:                    }
0581:                } finally {
0582:                    setPerRequestState(prevState);
0583:
0584:                    PageFlowControlContainer pfcc = PageFlowControlContainerFactory
0585:                            .getControlContainer(request, getServletContext());
0586:                    pfcc.endContextOnPageFlow(this );
0587:                }
0588:
0589:                PageFlowEventReporter er = AdapterManager
0590:                        .getServletContainerAdapter(servletContext)
0591:                        .getEventReporter();
0592:                RequestContext requestContext = new RequestContext(request,
0593:                        response);
0594:                er.flowControllerCreated(requestContext, this );
0595:            }
0596:
0597:            /**
0598:             * Internal destroy method that is invoked when this object is being removed from the session.  This is a
0599:             * framework-invoked method; it should not normally be called directly.
0600:             */
0601:            void destroy(HttpSession session) {
0602:                onDestroy(); // for backwards compatiblity
0603:                super .destroy(session);
0604:
0605:                //
0606:                // We may have lost our transient ServletContext reference.  Try to get the ServletContext reference from the
0607:                // HttpSession object if necessary.
0608:                //
0609:                ServletContext servletContext = getServletContext();
0610:                if (servletContext == null && session != null)
0611:                    servletContext = session.getServletContext();
0612:
0613:                if (servletContext != null) {
0614:                    PageFlowEventReporter er = AdapterManager
0615:                            .getServletContainerAdapter(servletContext)
0616:                            .getEventReporter();
0617:                    er.flowControllerDestroyed(this , session);
0618:                }
0619:            }
0620:
0621:            /**
0622:             * Get the Struts module path for this controller.
0623:             * 
0624:             * @return a String that is the Struts module path for this controller.
0625:             */
0626:            public abstract String getModulePath();
0627:
0628:            /**
0629:             * Callback that occurs before any user action method is invoked.  {@link FlowController#getRequest},
0630:             * {@link FlowController#getResponse}, {@link FlowController#getSession}, and
0631:             * {@link FlowController#getActionMapping} may all be used during this method.  The action to be run can be
0632:             * discovered by calling {@link ActionMapping#getPath} on the value returned from
0633:             * {@link FlowController#getActionMapping}.
0634:             */
0635:            protected synchronized void beforeAction() throws Exception {
0636:            }
0637:
0638:            /**
0639:             * Callback that occurs after any user action method is invoked.  {@link FlowController#getRequest},
0640:             * {@link FlowController#getResponse}, {@link FlowController#getSession}, and 
0641:             * {@link FlowController#getActionMapping} may all be used during this method.  The action that was run can be
0642:             * discovered by calling {@link ActionMapping#getPath} on the value returned from
0643:             * {@link FlowController#getActionMapping}.
0644:             */
0645:            protected synchronized void afterAction() throws Exception {
0646:            }
0647:
0648:            /**
0649:             * Callback that is invoked when this controller instance is created.  {@link FlowController#getRequest},
0650:             * {@link FlowController#getResponse}, {@link FlowController#getSession} may all be used during this method.
0651:             */
0652:            protected void onCreate() throws Exception {
0653:            }
0654:
0655:            /**
0656:             * Callback that is invoked when this controller instance is "destroyed", i.e., removed from the user session. 
0657:             * {@link FlowController#getRequest}, {@link FlowController#getResponse}, and {@link FlowController#getActionMapping}
0658:             * may <i>not</i> be used during this method, since it may be called due to session termination outside of a
0659:             * request.  {@link FlowController#getSession} also may not be used, but the session is passed as an argument
0660:             * to {@link FlowController#onDestroy(HttpSession)}, which should be used in place of this method.
0661:             * <br>
0662:             * Note that this method is <strong>not synchronized</strong>.  It is dangerous to synchronize your override of
0663:             * this method because it is invoked during a callback from the Servlet container.  Depending on the container,
0664:             * synchronization here can cause deadlocks.
0665:             *
0666:             * @deprecated {@link FlowController#onDestroy(HttpSession)} should be used instead. 
0667:             */
0668:            protected void onDestroy() {
0669:            }
0670:
0671:            /**
0672:             * Callback that is invoked when this controller instance is "destroyed", i.e., removed from the user session. 
0673:             * {@link FlowController#getRequest}, {@link FlowController#getResponse}, and {@link FlowController#getActionMapping}
0674:             * may <i>not</i> be used during this method, since it may be called due to session termination outside of a
0675:             * request.  {@link FlowController#getSession} also may not be used, but the session is passed as an argument.
0676:             * <br>
0677:             * Note that this method is <strong>not synchronized</strong>.  It is dangerous to synchronize your override of
0678:             * this method because it is invoked during a callback from the Servlet container.  Depending on the container,
0679:             * synchronization here can cause deadlocks.
0680:             */
0681:            protected void onDestroy(HttpSession session) {
0682:            }
0683:
0684:            /**
0685:             * Get a legacy PreviousPageInfo.
0686:             * @deprecated This method will be removed without replacement in a future release.
0687:             */
0688:            public abstract PreviousPageInfo getPreviousPageInfoLegacy(
0689:                    PageFlowController curJpf, HttpServletRequest request);
0690:
0691:            /**
0692:             * Get an action handler method of the given name/signature.
0693:             *  
0694:             * @param methodName the name of the action handler method to query.
0695:             * @param argType the type of the argument to the action handler method; if <code>null</code>,
0696:             *            the method takes no arguments.
0697:             * @return the desired Method, or <code>null</code> if it doesn't exist.
0698:             */
0699:            protected Method getActionMethod(String methodName, Class argType) {
0700:                String cacheKey = argType != null ? methodName + '/'
0701:                        + argType.getName() : methodName;
0702:                Class this Class = getClass();
0703:                ClassLevelCache cache = ClassLevelCache.getCache(this Class);
0704:                Method actionMethod = (Method) cache.get(
0705:                        CACHEID_ACTION_METHODS, cacheKey);
0706:
0707:                if (actionMethod != null) {
0708:                    return actionMethod;
0709:                } else {
0710:                    //
0711:                    // We didn't find it in the cache.  Look for it reflectively.
0712:                    //
0713:                    if (argType == null) {
0714:                        //
0715:                        // No form -- look for a method with no arguments.
0716:                        //
0717:                        actionMethod = InternalUtils.lookupMethod(this Class,
0718:                                methodName, null);
0719:                    } else {
0720:                        //
0721:                        // Has a form.  Look for a method with a single argument -- either the given type
0722:                        // or any superclass.
0723:                        //
0724:                        while (argType != null) {
0725:                            actionMethod = InternalUtils.lookupMethod(
0726:                                    this Class, methodName,
0727:                                    new Class[] { argType });
0728:
0729:                            if (actionMethod != null) {
0730:                                break;
0731:                            }
0732:
0733:                            argType = argType.getSuperclass();
0734:                        }
0735:                    }
0736:
0737:                    if (actionMethod != null
0738:                            && actionMethod.getReturnType().equals(
0739:                                    Forward.class)) {
0740:                        if (!Modifier.isPublic(actionMethod.getModifiers()))
0741:                            actionMethod.setAccessible(true);
0742:                        cache.put(CACHEID_ACTION_METHODS, cacheKey,
0743:                                actionMethod);
0744:                        return actionMethod;
0745:                    }
0746:                }
0747:
0748:                return null;
0749:            }
0750:
0751:            private Class getFormClass(Object form, ActionMapping mapping,
0752:                    HttpServletRequest request) throws ClassNotFoundException {
0753:                if (mapping instanceof  PageFlowActionMapping) {
0754:                    String formClassName = ((PageFlowActionMapping) mapping)
0755:                            .getFormClass();
0756:
0757:                    if (formClassName != null) {
0758:                        return InternalUtils.getReloadableClass(formClassName,
0759:                                getServletContext());
0760:                    }
0761:                }
0762:
0763:                return form != null ? form.getClass() : null;
0764:            }
0765:
0766:            /**
0767:             * Get the ActionForward returned by the action handler method that corresponds to the
0768:             * given action name and form-bean, or send an error to the browser if there is no
0769:             * matching method.
0770:             * 
0771:             * @param actionName the name of the Struts action to handle.
0772:             * @param inputForm the form-bean associated with the action.  May be <code>null</code>.
0773:             * @param response the current HttpServletResponse.
0774:             * @return the ActionForward returned by the action handler method, or <code>null</code> if
0775:             *             there was no matching method (in which case an error was written to the
0776:             *             browser.
0777:             * @throws Exception if an Exception was raised in user code.
0778:             */
0779:            ActionForward getActionMethodForward(String actionName,
0780:                    Object inputForm, HttpServletRequest request,
0781:                    HttpServletResponse response, ActionMapping mapping)
0782:                    throws Exception {
0783:                //
0784:                // Find the method.
0785:                //
0786:                Class formClass = getFormClass(inputForm, mapping, request);
0787:                Method actionMethod = getActionMethod(actionName, formClass);
0788:
0789:                //
0790:                // Invoke the method.
0791:                //
0792:                if (actionMethod != null) {
0793:                    return invokeActionMethod(actionMethod, inputForm, request,
0794:                            mapping);
0795:                }
0796:
0797:                if (_log.isWarnEnabled()) {
0798:                    InternalStringBuilder msg = new InternalStringBuilder(
0799:                            "Could not find matching action method for action=");
0800:                    msg.append(actionName).append(", form=");
0801:                    msg.append(inputForm != null ? inputForm.getClass()
0802:                            .getName() : "[none]");
0803:                    _log.warn(msg.toString());
0804:                }
0805:
0806:                PageFlowException ex = new NoMatchingActionMethodException(
0807:                        actionName, inputForm, this );
0808:                InternalUtils.throwPageFlowException(ex, request);
0809:                return null;
0810:            }
0811:
0812:            private static String getFormQualifiedActionPath(Class formClass,
0813:                    String actionPath) {
0814:                InternalStringBuilder ret = new InternalStringBuilder(
0815:                        actionPath);
0816:                ret.append('_');
0817:                ret.append(formClass.getName().replace('.', '_').replace('$',
0818:                        '_'));
0819:                return ret.toString();
0820:            }
0821:
0822:            /**
0823:             * Invoke the given action handler method, passing it an argument if appropriate.
0824:             * 
0825:             * @param method the action handler method to invoke.
0826:             * @param arg the form-bean to pass; may be <code>null</code>.
0827:             * @return the ActionForward returned by the action handler method.
0828:             * @throws Exception if an Exception was raised in user code.
0829:             */
0830:            protected ActionForward invokeActionMethod(Method method, Object arg)
0831:                    throws Exception {
0832:                return invokeActionMethod(method, arg, getRequest(),
0833:                        getActionMapping());
0834:            }
0835:
0836:            /**
0837:             * Invoke the given action handler method, passing it an argument if appropriate.
0838:             * 
0839:             * @param method the action handler method to invoke.
0840:             * @param arg the form-bean to pass; may be <code>null</code>.
0841:             * @param request the current HttpServletRequest.
0842:             * @return the ActionForward returned by the action handler method.
0843:             * @throws Exception if an Exception was raised in user code.
0844:             */
0845:            ActionForward invokeActionMethod(Method method, Object arg,
0846:                    HttpServletRequest request, ActionMapping mapping)
0847:                    throws Exception {
0848:                Class[] paramTypes = method.getParameterTypes();
0849:
0850:                try {
0851:                    if (paramTypes.length > 0 && paramTypes[0].isInstance(arg)) {
0852:                        if (_log.isDebugEnabled()) {
0853:                            _log.debug("Invoking action method "
0854:                                    + method.getName() + '('
0855:                                    + paramTypes[0].getName() + ')');
0856:                        }
0857:
0858:                        return (ActionForward) method.invoke(this ,
0859:                                new Object[] { arg });
0860:                    } else if (paramTypes.length == 0) {
0861:                        if (_log.isDebugEnabled()) {
0862:                            _log.debug("Invoking action method "
0863:                                    + method.getName() + "()");
0864:                        }
0865:
0866:                        return (ActionForward) method.invoke(this , null);
0867:                    }
0868:                } finally {
0869:                    boolean readonly = false;
0870:
0871:                    if (mapping instanceof  PageFlowActionMapping) {
0872:                        PageFlowActionMapping pfam = (PageFlowActionMapping) mapping;
0873:                        readonly = pfam.isReadonly();
0874:                    }
0875:
0876:                    /*
0877:                    A read only Flow Controller is one that is marked as such via metadata.  If a FlowController
0878:                    is read only, no steps need to be taken to ensure that it fails over into the session for
0879:                    serialization in a cluster.
0880:                     */
0881:                    if (!readonly) {
0882:                        ensureFailover(getRequest());
0883:                    }
0884:                }
0885:
0886:                if (_log.isWarnEnabled()) {
0887:                    _log
0888:                            .warn("Could not find action method "
0889:                                    + method.getName()
0890:                                    + " with appropriate signature.");
0891:                }
0892:
0893:                return null;
0894:            }
0895:
0896:            /**
0897:             * Get the current HttpServletRequest.  This call is only valid during {@link FlowController#execute} (where
0898:             * any user action method is invoked), and during the lifecycle methods {@link FlowController#onCreate},
0899:             * {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
0900:             * 
0901:             * @return the current HttpServletRequest.
0902:             * @throws IllegalStateException if this method is invoked outside of action method
0903:             *             execution (i.e., outside of the call to {@link FlowController#execute}, and outside of
0904:             *             {@link FlowController#onCreate}, {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
0905:             */
0906:            protected final HttpServletRequest getRequest() {
0907:                if (_perRequestState == null) {
0908:                    throw new IllegalStateException(
0909:                            "getRequest was called outside of a valid context.");
0910:                }
0911:
0912:                return _perRequestState.getRequest();
0913:            }
0914:
0915:            /**
0916:             * Get the current HttpServletResponse.  This call is only valid during {@link FlowController#execute} (where
0917:             * any user action method is invoked), and during the lifecycle methods {@link FlowController#onCreate},
0918:             * {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
0919:             * 
0920:             * @return the current HttpServletResponse.
0921:             * @throws IllegalStateException if this method is invoked outside of action method
0922:             *             execution (i.e., outside of the call to {@link FlowController#execute}, and outside of
0923:             *             {@link FlowController#onCreate}, {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
0924:             */
0925:            protected final HttpServletResponse getResponse() {
0926:                if (_perRequestState == null) {
0927:                    throw new IllegalStateException(
0928:                            "getResponse was called outside of a valid context.");
0929:                }
0930:
0931:                return _perRequestState.getResponse();
0932:            }
0933:
0934:            /**
0935:             * Get the current Struts ActionMapping, which is information from the Struts-XML &lt;action&gt;
0936:             * tag that corresponds to the current action being executed.  This call is only valid during
0937:             * {@link FlowController#execute} (where any user action method is invoked), and during the lifecycle
0938:             * methods {@link FlowController#beforeAction} and {@link FlowController#afterAction}.
0939:             * @deprecated Use {@link FlowController#getActionMapping} instead.
0940:             * 
0941:             * @return the current Struts ActionMapping.
0942:             * @throws IllegalStateException if this method is invoked outside of action method
0943:             *             execution (i.e., outside of the call to {@link FlowController#execute}, and outside of
0944:             *             {@link FlowController#onCreate}, {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
0945:             */
0946:            protected final ActionMapping getMapping() {
0947:                return getActionMapping();
0948:            }
0949:
0950:            /**
0951:             * Get the current Struts ActionMapping, which is information from the Struts-XML &lt;action&gt;
0952:             * tag that corresponds to the current action being executed.  This call is only valid
0953:             * during {@link FlowController#execute} (where any user action method is invoked), and during the lifecycle
0954:             * methods {@link FlowController#beforeAction} and {@link FlowController#afterAction}.
0955:             * 
0956:             * @return the current Struts ActionMapping.
0957:             * @throws IllegalStateException if this method is invoked outside of action method
0958:             *             execution (i.e., outside of the call to {@link FlowController#execute}, and outside of
0959:             *             {@link FlowController#onCreate}, {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
0960:             */
0961:            protected final ActionMapping getActionMapping() {
0962:                if (_perRequestState == null) {
0963:                    throw new IllegalStateException(
0964:                            "getActionMapping was called outside of a valid context.");
0965:                }
0966:
0967:                return _perRequestState.getActionMapping();
0968:            }
0969:
0970:            /**
0971:             * Get the current user session.  This call is only valid during {@link FlowController#execute} (where
0972:             * any user action method is invoked), and during the lifecycle methods {@link FlowController#onCreate},
0973:             * {@link FlowController#onDestroy}, {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
0974:             * 
0975:             * @return the HttpSession for the current user session.
0976:             * @throws IllegalStateException if this method is invoked outside of action method
0977:             *             execution (i.e., outside of the call to {@link FlowController#execute}, and outside of
0978:             *             {@link FlowController#onCreate}, {@link FlowController#onDestroy}, {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
0979:             */
0980:            protected final HttpSession getSession() {
0981:                if (_perRequestState == null) {
0982:                    throw new IllegalStateException(
0983:                            "getSession was called outside of a valid context.");
0984:                }
0985:
0986:                return _perRequestState.getRequest().getSession(true);
0987:            }
0988:
0989:            PerRequestState setPerRequestState(PerRequestState state) {
0990:                if (state != null) {
0991:                    assert state.getRequest() != null;
0992:                    assert state.getResponse() != null;
0993:                }
0994:
0995:                PerRequestState prevState = _perRequestState;
0996:                _perRequestState = state;
0997:                return prevState;
0998:            }
0999:
1000:            /**
1001:             * Get the Struts ModuleConfig object associated with this FlowController.
1002:             */
1003:            protected final ModuleConfig getModuleConfig() {
1004:                if (_moduleConfig == null) {
1005:                    _moduleConfig = InternalUtils.ensureModuleConfig(
1006:                            getModulePath(), getServletContext());
1007:                    assert _moduleConfig != null : getModulePath() + "; "
1008:                            + getClass().getName();
1009:                }
1010:                return _moduleConfig;
1011:            }
1012:
1013:            /**
1014:             * This is a non-property public accessor that will return the property value <code>moduleConfig</code>.
1015:             * This is a non-property method because properties are exposed to databinding and that would expose
1016:             * internal data structures to attack.
1017:             * @return the ModuleConfig for this FlowController
1018:             */
1019:            public final ModuleConfig theModuleConfig() {
1020:                return getModuleConfig();
1021:            }
1022:
1023:            /**
1024:             * Gets the Struts module configuration associated with this controller.
1025:             * @deprecated Use {@link #getModuleConfig()} instead.
1026:             * 
1027:             * @param servletContext the current ServletContext.
1028:             * @return the Struts ModuleConfig for this controller.
1029:             */
1030:            public ModuleConfig getModuleConfig(ServletContext servletContext,
1031:                    HttpServletRequest request) {
1032:                return getModuleConfig();
1033:            }
1034:
1035:            /**
1036:             * Resolve the given action name to a URI.  This version assumes that the ActionServlet
1037:             * class should be {@link PageFlowActionServlet}.
1038:             * Note: this method invokes the full action-processing cycle on a {@link ScopedRequest}.  Use
1039:             *             {@link FlowController#resolveAction} to resolve the URI for an action in the current page flow.
1040:             * @deprecated Use {@link PageFlowUtils#strutsLookup} instead.  This method will be removed in v1.1.
1041:             */
1042:            public static ActionResult lookup(String actionName,
1043:                    ServletContext context, HttpServletRequest request,
1044:                    HttpServletResponse response) throws Exception {
1045:                return PageFlowUtils.strutsLookup(context, request, response,
1046:                        actionName, null);
1047:            }
1048:
1049:            /**
1050:             * Resolve the given action name to a URI.
1051:             * Note: this method invokes the full action-processing cycle on a {@link ScopedRequest}.  Use
1052:             *             {@link FlowController#resolveAction} to resolve the URI for an action in the current page flow.
1053:             * @deprecated Use {@link PageFlowUtils#strutsLookup} instead.  This method will be removed in v1.1.
1054:             */
1055:            public static ActionResult lookup(String actionName,
1056:                    ServletContext context, HttpServletRequest request,
1057:                    HttpServletResponse response, String actionServletClassName)
1058:                    throws Exception {
1059:                return PageFlowUtils.strutsLookup(context, request, response,
1060:                        actionName, null);
1061:            }
1062:
1063:            /**
1064:             * Call an action and return the result URI.
1065:             * 
1066:             * @param actionName the name of the action to run.
1067:             * @param form the form bean instance to pass to the action, or <code>null</code> if none should be passed.
1068:             * @return the result webapp-relative URI, as a String.
1069:             * @throws ActionNotFoundException when the given action does not exist in this FlowController.
1070:             * @throws Exception if the action method throws an Exception.
1071:             */
1072:            public String resolveAction(String actionName, Object form,
1073:                    HttpServletRequest request, HttpServletResponse response)
1074:                    throws Exception {
1075:                ActionMapping mapping = (ActionMapping) getModuleConfig()
1076:                        .findActionConfig('/' + actionName);
1077:
1078:                if (mapping == null) {
1079:                    InternalUtils
1080:                            .throwPageFlowException(
1081:                                    new ActionNotFoundException(actionName,
1082:                                            this , form), request);
1083:                }
1084:
1085:                ActionForward fwd = getActionMethodForward(actionName, form,
1086:                        request, response, mapping);
1087:
1088:                if (fwd instanceof  Forward) {
1089:                    ((Forward) fwd).initialize(mapping, this , request);
1090:                }
1091:
1092:                String path = fwd.getPath();
1093:                if (fwd.getContextRelative() || FileUtils.isAbsoluteURI(path)) {
1094:                    return path;
1095:                } else {
1096:                    return getModulePath() + path;
1097:                }
1098:            }
1099:
1100:            /**
1101:             * Call an action and return the result URI.
1102:             * 
1103:             * @deprecated Use {@link FlowController#resolveAction(String, Object, HttpServletRequest, HttpServletResponse)} instead.
1104:             * @param actionName the name of the action to run.
1105:             * @param form the form bean instance to pass to the action, or <code>null</code> if none should be passed.
1106:             * @return the result webapp-relative URI, as a String.
1107:             * @throws ActionNotFoundException when the given action does not exist in this FlowController.
1108:             * @throws Exception if the action method throws an Exception.
1109:             */
1110:            public String resolveAction(String actionName, Object form)
1111:                    throws Exception {
1112:                return resolveAction(actionName, form, getRequest(),
1113:                        getResponse());
1114:            }
1115:
1116:            /**
1117:             * Get a list of the names of actions handled by methods in this PageFlowController.
1118:             * 
1119:             * @return a String array containing the names of actions handled by methods in this PageFlowController.
1120:             */
1121:            protected String[] getActions() {
1122:                ActionConfig[] actionConfigs = getModuleConfig()
1123:                        .findActionConfigs();
1124:                ArrayList actionNames = new ArrayList();
1125:
1126:                for (int i = 0; i < actionConfigs.length; i++) {
1127:                    ActionConfig ac = actionConfigs[i];
1128:                    actionNames.add(ac.getPath().substring(1)); // every action path has a '/' in front of it
1129:                }
1130:
1131:                return (String[]) actionNames.toArray(new String[0]);
1132:            }
1133:
1134:            /**
1135:             * Tell whether a given String is the name of an action handled by a method in this PageFlowController.
1136:             * 
1137:             * @param name the action-name to query.
1138:             * @return <code>true</code> if <code>name</code> is the name of an action handled by a method in this
1139:             *         PageFlowController.
1140:             */
1141:            public boolean isAction(String name) {
1142:                return getModuleConfig().findActionConfig('/' + name) != null;
1143:            }
1144:
1145:            /**
1146:             * Tell whether this is a {@link PageFlowController}.
1147:             * 
1148:             * @return <code>true</code> if this is a {@link PageFlowController}.
1149:             */
1150:            public boolean isPageFlow() {
1151:                return false;
1152:            }
1153:
1154:            /**
1155:             * Get the current Struts ActionServlet.
1156:             * 
1157:             * @deprecated This method will be removed with no replacement.  In most cases, {@link FlowController#getServletContext()} is
1158:             *             sufficient; for other cases, the ActionServlet itself is in the ServletContext attribute
1159:             *             {@link Globals#ACTION_SERVLET_KEY}.
1160:             * @return the ActionServlet.
1161:             */
1162:            protected ActionServlet getServlet() {
1163:                return InternalUtils.getActionServlet(getServletContext());
1164:            }
1165:
1166:            /**
1167:             * Called on this object for non-lookup (refresh) requests.  This is a framework-invoked method that should not
1168:             * normally be called directly.
1169:             */
1170:            public final synchronized void refresh(HttpServletRequest request,
1171:                    HttpServletResponse response) {
1172:                PerRequestState prevState = setPerRequestState(new PerRequestState(
1173:                        request, response, null));
1174:
1175:                try {
1176:                    onRefresh();
1177:                } finally {
1178:                    setPerRequestState(prevState);
1179:                }
1180:            }
1181:
1182:            /**
1183:             * Callback that is invoked when this controller is involved in a refresh request, as can happen in a portal
1184:             * environment on a request where no action is run in the current page flow, but a previously-displayed page in the
1185:             * page flow is re-rendered.
1186:             */
1187:            protected void onRefresh() {
1188:            }
1189:
1190:            /**
1191:             * Remove this instance from the user session.
1192:             */
1193:            protected void remove() {
1194:                removeFromSession(getRequest());
1195:            }
1196:
1197:            /**
1198:             * Used by derived classes to store information on the most recent action executed.
1199:             */
1200:            void savePreviousActionInfo(ActionForm form,
1201:                    HttpServletRequest request, ActionMapping mapping,
1202:                    ServletContext servletContext) {
1203:            }
1204:
1205:            /**
1206:             * Store information about recent pages displayed.  This is a framework-invoked method that should not normally be
1207:             * called directly.
1208:             */
1209:            public void savePreviousPageInfo(ActionForward forward,
1210:                    ActionForm form, ActionMapping mapping,
1211:                    HttpServletRequest request, ServletContext servletContext,
1212:                    boolean isSpecialForward) {
1213:            }
1214:
1215:            /**
1216:             * When this FlowController does not use a {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward}
1217:             * annotation with a
1218:             * <code>navigateTo=</code>{@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousAction Jpf.NavigateTo.previousAction}
1219:             * attribute, the following methods always return <code>null</code> by default.
1220:             * <ul>
1221:             *     <li>getPreviousActionInfo</li>
1222:             *     <li>getPreviousActionURI</li>
1223:             *     <li>getPreviousForm</li>
1224:             * </ul>
1225:             * Override <code>alwaysTrackPreviousAction</code> (which always returns <code>false</code>) to enable these methods
1226:             * in all cases.
1227:             * 
1228:             * @return <code>true</code> if the previous action should always be tracked, regardless of whether
1229:             * <code>return-to="previousAction"</code> is used.
1230:             * @see PageFlowController#getPreviousActionInfo
1231:             * @see PageFlowController#getPreviousActionURI
1232:             * @see PageFlowController#getPreviousFormBean
1233:             */
1234:            protected boolean alwaysTrackPreviousAction() {
1235:                return false;
1236:            }
1237:
1238:            /**
1239:             * When this FlowController does not use a {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward}
1240:             * annotation with either a
1241:             * <code>navigateTo</code>={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#currentPage Jpf.NavigateTo.currentPage}
1242:             * attribute or a
1243:             * <code>navigateTo</code>={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousPage Jpf.NavigateTo.previousPage}
1244:             * attribute, the following methods always return <code>null</code> by default.
1245:             * <ul>
1246:             *     <li>getCurrentPageInfo</li>
1247:             *     <li>getPreviousPageInfo</li>
1248:             *     <li>getCurrentForwardPath</li>
1249:             *     <li>getPreviousForwardPath</li>
1250:             * </ul>
1251:             * Override <code>alwaysTrackPreviousPage</code> (which always returns <code>false</code>) to enable these methods
1252:             * in all cases.
1253:             * 
1254:             * @return <code>true</code> if the previous page should always be tracked, regardless
1255:             *         of whether <code>return-to="currentPage"</code> or <code>return-to="previousPage"</code>
1256:             *         is used.
1257:             * @see PageFlowController#getCurrentPageInfo
1258:             * @see PageFlowController#getPreviousPageInfo
1259:             * @see PageFlowController#getCurrentForwardPath
1260:             * @see PageFlowController#getPreviousForwardPath
1261:             */
1262:            protected boolean alwaysTrackPreviousPage() {
1263:                return false;
1264:            }
1265:
1266:            /**
1267:             * Increment the count of concurrent requests to this FlowController.  Note that this method
1268:             * is not synchronized -- we use it to decide whether to synchronize on this instance,
1269:             * or to bail out with an error message about too many concurrent requests.
1270:             */
1271:            boolean incrementRequestCount(HttpServletRequest request,
1272:                    HttpServletResponse response, ServletContext servletContext)
1273:                    throws IOException {
1274:                //
1275:                // First cache the max-concurrent-request-count value.
1276:                //
1277:                if (_maxConcurrentRequestCount == -1) {
1278:                    _maxConcurrentRequestCount = DEFAULT_MAX_CONCURRENT_REQUEST_COUNT;
1279:                    assert servletContext != null;
1280:
1281:                    String countStr = servletContext
1282:                            .getInitParameter(MAX_CONCURRENT_REQUESTS_PARAM);
1283:                    if (countStr != null) {
1284:                        try {
1285:                            _maxConcurrentRequestCount = Integer
1286:                                    .parseInt(countStr);
1287:                        } catch (NumberFormatException e) {
1288:                            _log.error(
1289:                                    "Invalid value for servlet context parameter"
1290:                                            + MAX_CONCURRENT_REQUESTS_PARAM
1291:                                            + ": " + countStr, e);
1292:                        }
1293:
1294:                        if (_maxConcurrentRequestCount < 1) {
1295:                            _maxConcurrentRequestCount = DEFAULT_MAX_CONCURRENT_REQUEST_COUNT;
1296:                            _log
1297:                                    .error("Invalid value for servlet context parameter"
1298:                                            + MAX_CONCURRENT_REQUESTS_PARAM
1299:                                            + ": " + countStr);
1300:                        }
1301:                    }
1302:                }
1303:
1304:                //
1305:                // Now, if the current count of concurrent requests to this instance is greater than the max,
1306:                // send an error on the response.
1307:                //
1308:                if (_requestCount >= _maxConcurrentRequestCount) {
1309:                    if (_log.isInfoEnabled()) {
1310:                        _log.info("Too many requests to FlowController "
1311:                                + getDisplayName() + " (" + (_requestCount + 1)
1312:                                + '>' + _maxConcurrentRequestCount
1313:                                + "); returning error code "
1314:                                + EXCEEDED_MAX_CONCURRENT_REQUESTS_ERRORCODE);
1315:                    }
1316:
1317:                    response
1318:                            .sendError(EXCEEDED_MAX_CONCURRENT_REQUESTS_ERRORCODE);
1319:                    return false;
1320:                }
1321:
1322:                //
1323:                // We're ok -- increment the count and continue.
1324:                //
1325:                ++_requestCount;
1326:                return true;
1327:            }
1328:
1329:            void decrementRequestCount(HttpServletRequest request) {
1330:                assert _requestCount > 0 : request.getRequestURI();
1331:                --_requestCount;
1332:            }
1333:
1334:            /**
1335:             * Invoke the given exception handler method.  This is a framework-invoked method that should not normally be called
1336:             * directly
1337:             * 
1338:             * @param method the action handler method to invoke.
1339:             * @param ex the Throwable that is to be handled.
1340:             * @param message the String message that is to be passed to the handler method.
1341:             * @param wrappedFormBean the wrapped form bean that is associated with the action being processed; may be <code>null</code>.
1342:             * @param exceptionConfig the exception configuration object for the current exception handler.
1343:             * @param actionMapping the action configuration object for the requested action.
1344:             * @param request the current HttpServletRequest.
1345:             * @param response the current HttpServletResponse.
1346:             * @return the ActionForward returned by the exception handler method.
1347:             */
1348:            public synchronized ActionForward invokeExceptionHandler(
1349:                    Method method, Throwable ex, String message,
1350:                    ActionForm wrappedFormBean,
1351:                    PageFlowExceptionConfig exceptionConfig,
1352:                    ActionMapping actionMapping, HttpServletRequest request,
1353:                    HttpServletResponse response) throws IOException,
1354:                    ServletException {
1355:                PerRequestState prevState = setPerRequestState(new PerRequestState(
1356:                        request, response, actionMapping));
1357:
1358:                try {
1359:                    if (_log.isDebugEnabled()) {
1360:                        _log.debug("Invoking exception handler method "
1361:                                + method.getName() + '('
1362:                                + method.getParameterTypes()[0].getName()
1363:                                + ", ...)");
1364:                    }
1365:
1366:                    try {
1367:                        ActionForward retVal = null;
1368:                        String actionName = InternalUtils
1369:                                .getActionName(actionMapping);
1370:
1371:                        if (actionName == null
1372:                                && ex instanceof  PageFlowException) {
1373:                            actionName = ((PageFlowException) ex)
1374:                                    .getActionName();
1375:                        }
1376:
1377:                        try {
1378:                            Object formBean = InternalUtils
1379:                                    .unwrapFormBean(wrappedFormBean);
1380:                            Object[] args = new Object[] { ex, actionName,
1381:                                    message, formBean };
1382:                            retVal = (ActionForward) method.invoke(this , args);
1383:                        } finally {
1384:                            if (!exceptionConfig.isReadonly()) {
1385:                                ensureFailover(request);
1386:                            }
1387:                        }
1388:
1389:                        return retVal;
1390:                    } catch (InvocationTargetException e) {
1391:                        Throwable target = e.getTargetException();
1392:
1393:                        if (target instanceof  Exception) {
1394:                            throw (Exception) target;
1395:                        } else {
1396:                            throw e;
1397:                        }
1398:                    }
1399:                } catch (Throwable e) {
1400:                    _log.error("Exception while handling exception "
1401:                            + ex.getClass().getName()
1402:                            + ".  The original exception will be thrown.", e);
1403:
1404:                    ExceptionsHandler eh = Handlers.get(getServletContext())
1405:                            .getExceptionsHandler();
1406:                    FlowControllerHandlerContext context = new FlowControllerHandlerContext(
1407:                            request, response, this );
1408:                    Throwable unwrapped = eh.unwrapException(context, e);
1409:
1410:                    if (!eh.eatUnhandledException(context, unwrapped)) {
1411:                        if (ex instanceof  ServletException)
1412:                            throw (ServletException) ex;
1413:                        if (ex instanceof  IOException)
1414:                            throw (IOException) ex;
1415:                        if (ex instanceof  Error)
1416:                            throw (Error) ex;
1417:                        throw new UnhandledException(ex);
1418:                    }
1419:
1420:                    return null;
1421:                } finally {
1422:                    setPerRequestState(prevState);
1423:                }
1424:            }
1425:
1426:            /**
1427:             * Add a property-related message that will be shown with the Errors and Error tags.
1428:             * 
1429:             * @param propertyName the name of the property with which to associate this error.
1430:             * @param messageKey the message-resources key for the message.
1431:             * @param messageArgs zero or more arguments to the message.
1432:             */
1433:            protected void addActionError(String propertyName,
1434:                    String messageKey, Object[] messageArgs) {
1435:                InternalUtils.addActionError(propertyName, new ActionMessage(
1436:                        messageKey, messageArgs), getRequest());
1437:            }
1438:
1439:            /**
1440:             * Add a property-related message as an expression that will be evaluated and shown with the Errors and Error tags.
1441:             * 
1442:             * @param propertyName the name of the property with which to associate this error.
1443:             * @param expression the expression that will be evaluated to generate the error message.
1444:             * @param messageArgs zero or more arguments to the message; may be expressions.
1445:             */
1446:            protected void addActionErrorExpression(String propertyName,
1447:                    String expression, Object[] messageArgs) {
1448:                PageFlowUtils.addActionErrorExpression(getRequest(),
1449:                        propertyName, expression, messageArgs);
1450:            }
1451:
1452:            /**
1453:             * Add a validation error that will be shown with the Errors and Error tags.
1454:             * @deprecated Use {@link #addActionError} instead.
1455:             * 
1456:             * @param propertyName the name of the property with which to associate this error.
1457:             * @param messageKey the message-resources key for the error message.
1458:             * @param messageArgs an array of arguments for the error message.
1459:             */
1460:            protected void addValidationError(String propertyName,
1461:                    String messageKey, Object[] messageArgs) {
1462:                PageFlowUtils.addValidationError(propertyName, messageKey,
1463:                        messageArgs, getRequest());
1464:            }
1465:
1466:            /**
1467:             * Add a validation error that will be shown with the Errors and Error tags.
1468:             * @deprecated Use {@link #addActionError} instead.
1469:             * 
1470:             * @param propertyName the name of the property with which to associate this error.
1471:             * @param messageKey the message-resources key for the error message.
1472:             */
1473:            protected void addValidationError(String propertyName,
1474:                    String messageKey) {
1475:                PageFlowUtils.addValidationError(propertyName, messageKey,
1476:                        getRequest());
1477:            }
1478:
1479:            private static ActionForward handleSimpleAction(
1480:                    PageFlowActionMapping mapping, ActionForm wrappedFormBean,
1481:                    HttpServletRequest request, ServletContext servletContext) {
1482:
1483:                Map/*< String, String >*/conditionalForwards = mapping
1484:                        .getConditionalForwardsMap();
1485:
1486:                if (!conditionalForwards.isEmpty()) {
1487:                    Object formBean = InternalUtils
1488:                            .unwrapFormBean(wrappedFormBean);
1489:
1490:                    for (Iterator/*< Map.Entry< String, String > >*/i = conditionalForwards
1491:                            .entrySet().iterator(); i.hasNext();) {
1492:                        Map.Entry/*< String, String >*/entry = (Map.Entry) i
1493:                                .next();
1494:                        String expression = (String) entry.getKey();
1495:                        String forwardName = (String) entry.getValue();
1496:
1497:                        try {
1498:                            if (InternalExpressionUtils.evaluateCondition(
1499:                                    expression, formBean, request,
1500:                                    servletContext)) {
1501:                                if (_log.isTraceEnabled()) {
1502:                                    _log
1503:                                            .trace("Expression '"
1504:                                                    + expression
1505:                                                    + "' evaluated to true on simple action "
1506:                                                    + mapping.getPath()
1507:                                                    + "; using forward "
1508:                                                    + forwardName + '.');
1509:                                }
1510:
1511:                                return new Forward(forwardName);
1512:                            }
1513:                        } catch (Exception e) // ELException
1514:                        {
1515:                            if (_log.isErrorEnabled()) {
1516:                                _log.error(
1517:                                        "Exception occurred evaluating navigation expression '"
1518:                                                + expression + "'.  Cause: "
1519:                                                + e.getCause(), e);
1520:                            }
1521:                        }
1522:                    }
1523:                }
1524:
1525:                String defaultForwardName = mapping.getDefaultForward();
1526:                assert defaultForwardName != null : "defaultForwardName is null on Simple Action "
1527:                        + mapping.getPath();
1528:
1529:                if (_log.isTraceEnabled()) {
1530:                    _log
1531:                            .trace("No expression evaluated to true on simple action "
1532:                                    + mapping.getPath()
1533:                                    + "; using forward "
1534:                                    + defaultForwardName + '.');
1535:                }
1536:
1537:                return new Forward(defaultForwardName);
1538:            }
1539:
1540:            /**
1541:             * Get the system default locale.
1542:             * 
1543:             * @return the system default locale.
1544:             */
1545:            protected static Locale getDefaultLocale() {
1546:                return defaultLocale;
1547:            }
1548:
1549:            /**
1550:             * Return the default data source for the Struts module associated with this FlowController.
1551:             *
1552:             * @param request the current request.
1553:             */
1554:            protected DataSource getDataSource(HttpServletRequest request) {
1555:                return getDataSource(request, Globals.DATA_SOURCE_KEY);
1556:            }
1557:
1558:            /**
1559:             * Return the specified data source for the current Struts module.
1560:             *
1561:             * @param request The servlet request we are processing
1562:             * @param key     The key specified in the
1563:             *                <code>&lt;message-resources&gt;</code> element for the
1564:             *                requested bundle
1565:             */
1566:            protected DataSource getDataSource(HttpServletRequest request,
1567:                    String key) {
1568:                // Return the requested data source instance
1569:                return (DataSource) getServletContext().getAttribute(
1570:                        key + getModuleConfig().getPrefix());
1571:            }
1572:
1573:            /**
1574:             * Return the user's currently selected Locale.
1575:             *
1576:             * @param request the current request.
1577:             * @return the user's currently selected Locale, stored in the session.
1578:             * @deprecated Use {@link #getLocale} or {@link #retrieveUserLocale}.
1579:             */
1580:            protected Locale getLocale(HttpServletRequest request) {
1581:
1582:                HttpSession session = request.getSession();
1583:                Locale locale = (Locale) session
1584:                        .getAttribute(Globals.LOCALE_KEY);
1585:                return locale != null ? locale : DEFAULT_LOCALE;
1586:            }
1587:
1588:            /**
1589:             * Get the user's currently selected Locale.
1590:             *
1591:             * @return the user's currently selected Locale, stored in the session.
1592:             */
1593:            protected Locale getLocale() {
1594:                return retrieveUserLocale(getRequest(), null);
1595:            }
1596:
1597:            public static Locale retrieveUserLocale(HttpServletRequest request,
1598:                    String locale) {
1599:                if (locale == null)
1600:                    locale = Globals.LOCALE_KEY;
1601:                HttpSession session = request.getSession(false);
1602:                Locale userLocale = null;
1603:                if (session != null)
1604:                    userLocale = (Locale) session.getAttribute(locale);
1605:                if (userLocale == null)
1606:                    userLocale = DEFAULT_LOCALE;
1607:                return userLocale;
1608:            }
1609:
1610:            /**
1611:             * Return the message resources for the default module.
1612:             *
1613:             * @deprecated This method can only return the resources for the default
1614:             *             module.  Use {@link #getMessageResources()} to get the
1615:             *             resources for this FlowController.
1616:             */
1617:            protected MessageResources getResources() {
1618:                return (MessageResources) getServletContext().getAttribute(
1619:                        Globals.MESSAGES_KEY);
1620:            }
1621:
1622:            /**
1623:             * Return the default message resources for the current module.
1624:             * @deprecated Use {@link #getMessageResources()} instead.
1625:             *
1626:             * @param request The servlet request we are processing
1627:             */
1628:            protected MessageResources getResources(HttpServletRequest request) {
1629:                return getMessageResources();
1630:            }
1631:
1632:            /**
1633:             * Return the specified message resources for the current module.
1634:             * @deprecated Use {@link #getMessageResources(String)} instead.
1635:             *
1636:             * @param request the current request.
1637:             * @param key     The bundle key specified in a
1638:             *                {@link org.apache.beehive.netui.pageflow.annotations.Jpf.MessageBundle &#64;Jpf.MessageBundle} annotation.
1639:             */
1640:            protected MessageResources getResources(HttpServletRequest request,
1641:                    String key) {
1642:                return getMessageResources(key);
1643:            }
1644:
1645:            /**
1646:             * Get the default message resources for this FlowController.
1647:             */
1648:            protected MessageResources getMessageResources() {
1649:                return getMessageResources(Globals.MESSAGES_KEY);
1650:            }
1651:
1652:            /**
1653:             * Get the specified message resources for this FlowController.
1654:             *
1655:             * @param key The bundle key specified in a
1656:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.MessageBundle &#64;Jpf.MessageBundle} annotation.
1657:             */
1658:            protected MessageResources getMessageResources(String key) {
1659:                return (MessageResources) getServletContext().getAttribute(
1660:                        key + getModuleConfig().getPrefix());
1661:            }
1662:
1663:            /**
1664:             * <p>Returns <code>true</code> if the current form's cancel button was
1665:             * pressed.  This method will check if the <code>Globals.CANCEL_KEY</code>
1666:             * request attribute has been set, which normally occurs if the cancel
1667:             * button generated by the Struts <strong>CancelTag</strong> was pressed by the user
1668:             * in the current request.  If <code>true</code>, validation performed
1669:             * by an <strong>ActionForm</strong>'s <code>validate()</code> method
1670:             * will have been skipped by the controller servlet.</p>
1671:             * @deprecated This method will be removed without replacement in a future release.  The normal method for
1672:             *     cancelling in a form is to use the <code>action</code> attribute on
1673:             *     {@link org.apache.beehive.netui.tags.html.Button}, rather than avoiding validation on the current action.
1674:             *
1675:             * @param request The servlet request we are processing
1676:             * @see org.apache.struts.taglib.html.CancelTag
1677:             */
1678:            protected boolean isCancelled(HttpServletRequest request) {
1679:
1680:                return request.getAttribute(Globals.CANCEL_KEY) != null;
1681:
1682:            }
1683:
1684:            /**
1685:             * Generate a new transaction token, to be used for enforcing a single request for a particular transaction.
1686:             *
1687:             * @param request the current request.
1688:             * @deprecated Use {@link #generateToken()} instead.
1689:             */
1690:            protected String generateToken(HttpServletRequest request) {
1691:                return TOKEN_PROCESSOR.generateToken(request);
1692:            }
1693:
1694:            /**
1695:             * Generate a new transaction token, to be used for enforcing a single request for a particular transaction.
1696:             * 
1697:             * @see #isTokenValid()
1698:             * @see #isTokenValid(boolean)
1699:             * @see #resetToken()
1700:             */
1701:            protected String generateToken() {
1702:                return TOKEN_PROCESSOR.generateToken(getRequest());
1703:            }
1704:
1705:            /**
1706:             * Return <code>true</code> if there is a transaction token stored in
1707:             * the user's current session, and the value submitted as a request
1708:             * parameter with this action matches it.  Returns <code>false</code>
1709:             * under any of the following circumstances:
1710:             * <ul>
1711:             * <li>No session associated with this request</li>
1712:             * <li>No transaction token saved in the session</li>
1713:             * <li>No transaction token included as a request parameter</li>
1714:             * <li>The included transaction token value does not match the
1715:             * transaction token in the user's session</li>
1716:             * </ul>
1717:             * @deprecated Use {@link #isTokenValid()} instead.
1718:             *
1719:             * @param request The servlet request we are processing
1720:             */
1721:            protected boolean isTokenValid(HttpServletRequest request) {
1722:
1723:                return TOKEN_PROCESSOR.isTokenValid(request, false);
1724:
1725:            }
1726:
1727:            /**
1728:             * Return <code>true</code> if there is a transaction token stored in
1729:             * the user's current session, and the value submitted as a request
1730:             * parameter with this action matches it.  Returns <code>false</code>
1731:             * under any of the following circumstances:
1732:             * <ul>
1733:             * <li>No session associated with this request</li>
1734:             * <li>No transaction token saved in the session</li>
1735:             * <li>No transaction token included as a request parameter</li>
1736:             * <li>The included transaction token value does not match the
1737:             * transaction token in the user's session</li>
1738:             * </ul>
1739:             * 
1740:             * @see #generateToken()
1741:             * @see #resetToken()
1742:             */
1743:            protected boolean isTokenValid() {
1744:
1745:                return TOKEN_PROCESSOR.isTokenValid(getRequest(), false);
1746:
1747:            }
1748:
1749:            /**
1750:             * Return <code>true</code> if there is a transaction token stored in
1751:             * the user's current session, and the value submitted as a request
1752:             * parameter with this action matches it.  Returns <code>false</code>
1753:             * <ul>
1754:             * <li>No session associated with this request</li>
1755:             * <li>No transaction token saved in the session</li>
1756:             * <li>No transaction token included as a request parameter</li>
1757:             * <li>The included transaction token value does not match the
1758:             * transaction token in the user's session</li>
1759:             * </ul>
1760:             * @deprecated Use {@link #isTokenValid(boolean)} instead.
1761:             *
1762:             * @param request The servlet request we are processing
1763:             * @param reset   Should we reset the token after checking it?
1764:             */
1765:            protected boolean isTokenValid(HttpServletRequest request,
1766:                    boolean reset) {
1767:                return TOKEN_PROCESSOR.isTokenValid(request, reset);
1768:            }
1769:
1770:            /**
1771:             * Return <code>true</code> if there is a transaction token stored in
1772:             * the user's current session, and the value submitted as a request
1773:             * parameter with this action matches it.  Returns <code>false</code>
1774:             * <ul>
1775:             * <li>No session associated with this request</li>
1776:             * <li>No transaction token saved in the session</li>
1777:             * <li>No transaction token included as a request parameter</li>
1778:             * <li>The included transaction token value does not match the
1779:             * transaction token in the user's session</li>
1780:             * </ul>
1781:             *
1782:             * @param reset   Should we reset the token after checking it?
1783:             * @see #generateToken()
1784:             * @see #resetToken()
1785:             */
1786:            protected boolean isTokenValid(boolean reset) {
1787:
1788:                return TOKEN_PROCESSOR.isTokenValid(getRequest(), reset);
1789:            }
1790:
1791:            /**
1792:             * Reset the saved transaction token in the user's session.  This
1793:             * indicates that transactional token checking will not be needed
1794:             * on the next request that is submitted.
1795:             * @deprecated Use {@link #resetToken()} instead.
1796:             *
1797:             * @param request The servlet request we are processing
1798:             */
1799:            protected void resetToken(HttpServletRequest request) {
1800:                TOKEN_PROCESSOR.resetToken(request);
1801:            }
1802:
1803:            /**
1804:             * Reset the saved transaction token in the user's session.  This
1805:             * indicates that transactional token checking will not be needed
1806:             * on the next request that is submitted.
1807:             * 
1808:             * @see #isTokenValid()
1809:             * @see #isTokenValid(boolean)
1810:             * @see #generateToken()
1811:             */
1812:            protected void resetToken() {
1813:                TOKEN_PROCESSOR.resetToken(getRequest());
1814:            }
1815:
1816:            /**
1817:             * Save the specified messages keys into the request for use by the &lt;netui:error&gt; or &lt;netui:errors&gt; tags.
1818:             * @deprecated Use {@link #saveActionErrors} instead.
1819:             *
1820:             * @param errors the ActionMessages to save in the request.
1821:             */
1822:            protected void saveErrors(HttpServletRequest request,
1823:                    ActionMessages errors) {
1824:                saveActionErrors(errors);
1825:            }
1826:
1827:            /**
1828:             * Save the specified messages keys into the appropriate request
1829:             * attribute for use by the Struts &lt;html:messages&gt; tag (if
1830:             * messages="true" is set), if any messages are required.  Otherwise,
1831:             * ensure that the request attribute is not created.
1832:             * @deprecated This method will be removed without replacement in a future release.
1833:             *
1834:             * @param request  The servlet request we are processing
1835:             * @param messages Messages object
1836:             */
1837:            protected void saveMessages(HttpServletRequest request,
1838:                    ActionMessages messages) {
1839:
1840:                // Remove any messages attribute if none are required
1841:                if (messages == null || messages.isEmpty()) {
1842:                    request.removeAttribute(Globals.MESSAGE_KEY);
1843:                    return;
1844:                }
1845:
1846:                // Save the messages we need
1847:                request.setAttribute(Globals.MESSAGE_KEY, messages);
1848:
1849:            }
1850:
1851:            /**
1852:             * Save the specified messages keys into the request for use by the &lt;netui:error&gt; or &lt;netui:errors&gt; tags.
1853:             *
1854:             * @param errors the ActionMessages to save in the request.
1855:             */
1856:            protected void saveActionErrors(ActionMessages errors) {
1857:                // Remove any messages attribute if none are required
1858:                if (errors == null || errors.isEmpty()) {
1859:                    getRequest().removeAttribute(Globals.ERROR_KEY);
1860:                } else {
1861:                    getRequest().setAttribute(Globals.ERROR_KEY, errors);
1862:                }
1863:            }
1864:
1865:            /**
1866:             * Save a new transaction token in the user's current session, creating
1867:             * a new session if necessary.
1868:             *
1869:             * @param request The servlet request we are processing
1870:             */
1871:            protected void saveToken(HttpServletRequest request) {
1872:                TOKEN_PROCESSOR.saveToken(request);
1873:            }
1874:
1875:            /**
1876:             * Set the user's currently selected Locale.
1877:             *
1878:             * @param request The request we are processing
1879:             * @param locale  The user's selected Locale to be set, or null
1880:             *                to select the server's default Locale
1881:             * @deprecated Use {@link #setLocale(Locale)}.
1882:             */
1883:            protected void setLocale(HttpServletRequest request, Locale locale) {
1884:
1885:                HttpSession session = request.getSession();
1886:                if (locale == null) {
1887:                    locale = getDefaultLocale();
1888:                }
1889:                session.setAttribute(Globals.LOCALE_KEY, locale);
1890:
1891:            }
1892:
1893:            /**
1894:             * Set the user's currently selected Locale.
1895:             *
1896:             * @param locale  The user's selected Locale to be set, or null to select the server's default Locale
1897:             */
1898:            protected void setLocale(Locale locale) {
1899:                if (locale == null)
1900:                    locale = getDefaultLocale();
1901:                getSession().setAttribute(Globals.LOCALE_KEY, locale);
1902:            }
1903:
1904:            /**
1905:             * Get the flow-scoped form bean member associated with the given ActionMapping.  This is a framework-invoked
1906:             * method that should not normally be called directly.
1907:             */
1908:            public ActionForm getFormBean(ActionMapping mapping) {
1909:                if (mapping instanceof  PageFlowActionMapping) {
1910:                    PageFlowActionMapping pfam = (PageFlowActionMapping) mapping;
1911:                    String formMember = pfam.getFormMember();
1912:                    if (formMember == null)
1913:                        return null;
1914:
1915:                    Field field = null;
1916:                    try {
1917:                        field = getClass().getDeclaredField(formMember);
1918:                    } catch (NoSuchFieldException e) {
1919:                        // try finding a non-private field from the class hierarchy
1920:                        field = InternalUtils.lookupField(getClass(),
1921:                                formMember);
1922:                        if (field == null
1923:                                || Modifier.isPrivate(field.getModifiers())) {
1924:                            _log.error("Could not find member field "
1925:                                    + formMember + " as the form bean.");
1926:                            return null;
1927:                        }
1928:                    }
1929:
1930:                    try {
1931:                        field.setAccessible(true);
1932:                        return InternalUtils.wrapFormBean(field.get(this ));
1933:                    } catch (Exception e) {
1934:                        _log.error("Could not use member field " + formMember
1935:                                + " as the form bean.", e);
1936:                    }
1937:                }
1938:
1939:                return null;
1940:            }
1941:
1942:            PageFlowRequestProcessor getRequestProcessor() {
1943:                ModuleConfig mc = getModuleConfig();
1944:                String key = Globals.REQUEST_PROCESSOR_KEY + mc.getPrefix();
1945:                RequestProcessor rp = (RequestProcessor) getServletContext()
1946:                        .getAttribute(key);
1947:
1948:                //
1949:                // The RequestProcessor may not have been initialized -- if so, just return a new (temporary) one.
1950:                //
1951:                if (rp == null) {
1952:                    try {
1953:                        ControllerConfig cc = mc.getControllerConfig();
1954:                        rp = (RequestProcessor) RequestUtils
1955:                                .applicationInstance(cc.getProcessorClass());
1956:                        rp.init(InternalUtils
1957:                                .getActionServlet(getServletContext()), mc);
1958:                    } catch (Exception e) {
1959:                        _log.error(
1960:                                "Could not initialize request processor for module "
1961:                                        + mc.getPrefix(), e);
1962:                    }
1963:                }
1964:
1965:                assert rp == null || rp instanceof  PageFlowRequestProcessor : rp
1966:                        .getClass().getName();
1967:                return (PageFlowRequestProcessor) rp;
1968:            }
1969:
1970:            /**
1971:             * Create a raw action URI, which can be modified before being sent through the registered URL rewriting chain
1972:             * using {@link org.apache.beehive.netui.core.urls.URLRewriterService#rewriteURL}.
1973:             *
1974:             * @param actionName the action name to convert into a MutableURI; may be qualified with a path from the webapp
1975:             *            root, in which case the parent directory from the current request is <i>not</i> used.
1976:             * @return a MutableURI for the given action, suitable for URL rewriting.
1977:             * @throws URISyntaxException    if there is a problem converting the action URI (derived
1978:             *                               from processing the given action name) into a MutableURI.
1979:             * @throws IllegalStateException if this method is invoked outside of action method
1980:             *                               execution (i.e., outside of the call to {@link FlowController#execute},
1981:             *                               and outside of {@link FlowController#onCreate},
1982:             *                               {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
1983:             */
1984:            public MutableURI getActionURI(String actionName)
1985:                    throws URISyntaxException {
1986:                if (_perRequestState == null) {
1987:                    throw new IllegalStateException(
1988:                            "getActionURI was called outside of a valid context.");
1989:                }
1990:                ServletContext servletContext = getServletContext();
1991:                HttpServletRequest request = getRequest();
1992:                HttpServletResponse response = getResponse();
1993:
1994:                return PageFlowUtils.getActionURI(servletContext, request,
1995:                        response, actionName);
1996:            }
1997:
1998:            /**
1999:             * Create a fully-rewritten URI given an action and parameters.
2000:             *
2001:             * @param actionName the action name to convert into a fully-rewritten URI; may be qualified with a path from the
2002:             *            webapp root, in which case the parent directory from the current request is <i>not</i> used.
2003:             * @param parameters the additional parameters to include in the URI query.
2004:             * @param asValidXml flag indicating that the query of the uri should be written
2005:             *                   using the &quot;&amp;amp;&quot; entity, rather than the character, '&amp;'
2006:             * @return a fully-rewritten URI for the given action.
2007:             * @throws URISyntaxException    if there is a problem converting the action url (derived
2008:             *                               from processing the given action name) into a URI.
2009:             * @throws IllegalStateException if this method is invoked outside of action method
2010:             *                               execution (i.e., outside of the call to {@link FlowController#execute},
2011:             *                               and outside of {@link FlowController#onCreate},
2012:             *                               {@link FlowController#beforeAction}, {@link FlowController#afterAction}.
2013:             */
2014:            public String getRewrittenActionURI(String actionName,
2015:                    Map parameters, boolean asValidXml)
2016:                    throws URISyntaxException {
2017:                if (_perRequestState == null) {
2018:                    throw new IllegalStateException(
2019:                            "getRewrittenActionURI was called outside of a valid context.");
2020:                }
2021:                ServletContext servletContext = getServletContext();
2022:                HttpServletRequest request = getRequest();
2023:                HttpServletResponse response = getResponse();
2024:
2025:                return PageFlowUtils.getRewrittenActionURI(servletContext,
2026:                        request, response, actionName, parameters, null,
2027:                        asValidXml);
2028:            }
2029:
2030:            FlowControllerHandlerContext getHandlerContext() {
2031:                return new FlowControllerHandlerContext(getRequest(),
2032:                        getResponse(), this);
2033:            }
2034:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.