Source Code Cross Referenced for PageFlowController.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 java.lang.reflect.Field;
0022:        import java.util.Map;
0023:        import javax.servlet.http.HttpServletRequest;
0024:        import javax.servlet.http.HttpServletResponse;
0025:        import javax.servlet.http.HttpSessionBindingEvent;
0026:        import javax.servlet.ServletContext;
0027:
0028:        import org.apache.struts.action.ActionForm;
0029:        import org.apache.struts.action.ActionMapping;
0030:        import org.apache.struts.action.ActionForward;
0031:        import org.apache.struts.config.ModuleConfig;
0032:        import org.apache.struts.config.ControllerConfig;
0033:        import org.apache.beehive.controls.api.context.ControlContainerContext;
0034:        import org.apache.beehive.netui.pageflow.config.PageFlowControllerConfig;
0035:        import org.apache.beehive.netui.pageflow.config.PageFlowExceptionConfig;
0036:        import org.apache.beehive.netui.pageflow.internal.CachedPageFlowInfo;
0037:        import org.apache.beehive.netui.pageflow.internal.InternalUtils;
0038:        import org.apache.beehive.netui.pageflow.internal.InternalConstants;
0039:        import org.apache.beehive.netui.pageflow.internal.CachedSharedFlowRefInfo;
0040:        import org.apache.beehive.netui.pageflow.internal.ViewRenderer;
0041:        import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
0042:        import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
0043:        import org.apache.beehive.netui.pageflow.handler.StorageHandler;
0044:        import org.apache.beehive.netui.pageflow.handler.Handlers;
0045:        import org.apache.beehive.netui.util.internal.DiscoveryUtils;
0046:        import org.apache.beehive.netui.util.internal.cache.ClassLevelCache;
0047:        import org.apache.beehive.netui.util.internal.FileUtils;
0048:        import org.apache.beehive.netui.util.internal.InternalStringBuilder;
0049:        import org.apache.beehive.netui.util.logging.Logger;
0050:
0051:        /**
0052:         * <p>
0053:         * Base class for controller logic, exception handlers, and state associated with a particular web directory path. 
0054:         * The class is configured through the
0055:         * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller} annotation.
0056:         * </p>
0057:         * 
0058:         * <p>
0059:         * When a page flow request (the page flow URI itself, or any ".do" or page URI in the directory path), arrives, an
0060:         * instance of the associated PageFlowController class is set as the <i>current page flow</i>, and remains stored in the
0061:         * session until a different one becomes active ("long lived" page flows stay in the session indefinitely;
0062:         * see {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#longLived longLived}
0063:         * on {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller}).
0064:         * </p>
0065:         * 
0066:         * <p>
0067:         * The page flow class handles <i>actions</i> that are most commonly raised by user interaction with pages.  The actions
0068:         * are handled by <i>action methods</i> or <i>action annotations</i> that determine the next URI to be displayed, after
0069:         * optionally performing arbitrary logic.
0070:         * </p>
0071:         * 
0072:         * <p>
0073:         * If the PageFlowController is a "nested page flow"
0074:         * ({@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#nested nested} is set to <code>true</code>
0075:         * on {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller}), then this
0076:         * is a reusable, modular flow that can be "nested" during other flows.  It has entry points (actions with optional form
0077:         * bean arguments), and exit points ({@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward},
0078:         * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.SimpleAction &#64;Jpf.SimpleAction}, or
0079:         * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.ConditionalForward &#64;Jpf.ConditionalForward} annotations
0080:         * that have <code>returnAction</code> attributes).
0081:         * </p>
0082:         *
0083:         * <p>
0084:         * The page flow class also handles exceptions thrown by actions or during page execution
0085:         * (see {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#catches catches} on
0086:         * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller}).  Unhandled exceptions are
0087:         * handled in order by declared {@link SharedFlowController}s
0088:         * (see {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#sharedFlowRefs sharedFlowRefs} on
0089:         * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller}).
0090:         * </p>
0091:         * 
0092:         * <p>
0093:         * Properties in the current page flow instance can be accessed from JSP 2.0-style expressions like this one:
0094:         * <code>${pageFlow.someProperty}</code>.
0095:         * </p>
0096:         * 
0097:         * <p>
0098:         * There may only be one page flow in any package.
0099:         * </p>
0100:         * 
0101:         * @see SharedFlowController
0102:         */
0103:        public abstract class PageFlowController extends FlowController
0104:                implements  InternalConstants {
0105:            /**
0106:             * A 'return-to="page"' forward brings the user back to the previous page. This object
0107:             * stores information about the current state of affairs, such as the origin URI and
0108:             * its ActionForm.
0109:             */
0110:            private PreviousPageInfo _previousPageInfo = null;
0111:            private PreviousPageInfo _currentPageInfo = null;
0112:
0113:            /**
0114:             * A 'return-to="action"' forward reruns the previous action. This object stores the previous
0115:             * action URI and its ActionForm.
0116:             */
0117:            private PreviousActionInfo _previousActionInfo;
0118:
0119:            private boolean _isOnNestingStack = false;
0120:            private ViewRenderer _returnActionViewRenderer = null;
0121:
0122:            private static final String REMOVING_PAGEFLOW_ATTR = InternalConstants.ATTR_PREFIX
0123:                    + "removingPageFlow";
0124:            private static final String SAVED_PREVIOUS_PAGE_INFO_ATTR = InternalConstants.ATTR_PREFIX
0125:                    + "savedPrevPageInfo";
0126:            private static final String CACHED_INFO_KEY = "cachedInfo";
0127:            private static final Logger _log = Logger
0128:                    .getInstance(PageFlowController.class);
0129:
0130:            /**
0131:             *  The bean context associated with this request
0132:             */
0133:            ControlContainerContext _beanContext;
0134:
0135:            /**
0136:             * Default constructor.
0137:             */
0138:            protected PageFlowController() {
0139:            }
0140:
0141:            /**
0142:             * Get the Struts module path for this page flow.
0143:             * 
0144:             * @return a String that is the Struts module path for this controller, and which is also
0145:             *         the directory path from the web application root to this PageFlowController
0146:             *         (not including the action filename).
0147:             */
0148:            public String getModulePath() {
0149:                return getCachedInfo().getModulePath();
0150:            }
0151:
0152:            /**
0153:             * Get the URI for addressing this PageFlowController.
0154:             * 
0155:             * @return a String that is the URI which will execute the begin action on this
0156:             *         PageFlowController.
0157:             */
0158:            public String getURI() {
0159:                return getCachedInfo().getURI();
0160:            }
0161:
0162:            /**
0163:             * Tell whether this PageFlowController can be "nested", i.e., if it can be invoked from another page
0164:             * flow with the intention of returning to the original one.  Page flows are declared to be nested by specifying
0165:             * <code>{@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#nested nested}=true</code> on the
0166:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller} annotation.
0167:             * 
0168:             * @return <code>true</code> if this PageFlowController can be nested.
0169:             */
0170:            protected boolean isNestable() {
0171:                return InternalUtils.isNestable(getModuleConfig());
0172:            }
0173:
0174:            /**
0175:             * Tell whether this is a "long lived" page flow.  Once it is invoked, a long lived page flow is never
0176:             * removed from the session unless {@link #remove} is called.  Navigating to another page flow hides
0177:             * the current long lived controller, but does not remove it.
0178:             */
0179:            protected boolean isLongLived() {
0180:                return InternalUtils.isLongLived(getModuleConfig());
0181:            }
0182:
0183:            /**
0184:             * Remove this instance from the session.  When inside a page flow action, {@link #remove} may be called instead.
0185:             * This method is synchronized in order to maintain single threaded semantics for the Page Flow's
0186:             * {@link #onDestroy(javax.servlet.http.HttpSession)} lifecycle method.
0187:             */
0188:            public synchronized void removeFromSession(
0189:                    HttpServletRequest request) {
0190:                // This request attribute is used in persistInSession to prevent re-saving of this instance.
0191:                request.setAttribute(REMOVING_PAGEFLOW_ATTR, this );
0192:
0193:                if (isLongLived()) {
0194:                    PageFlowUtils.removeLongLivedPageFlow(getModulePath(),
0195:                            request);
0196:                } else {
0197:                    InternalUtils.removeCurrentPageFlow(request,
0198:                            getServletContext());
0199:                }
0200:            }
0201:
0202:            /**
0203:             * Tell whether this is a PageFlowController.
0204:             * 
0205:             * @return <code>true</code>.
0206:             */
0207:            public boolean isPageFlow() {
0208:                return true;
0209:            }
0210:
0211:            /**
0212:             * Store this object in the user session, in the appropriate place.  Used by the framework; normally should not be
0213:             * called directly.
0214:             */
0215:            public void persistInSession(HttpServletRequest request,
0216:                    HttpServletResponse response) {
0217:                PageFlowController currentPageFlow = PageFlowUtils
0218:                        .getCurrentPageFlow(request, getServletContext());
0219:
0220:                //
0221:                // This code implicitly destroys the current page flow.  In order to prevent multiple threads
0222:                // from executing inside the JPF at once, synchronize on it in order to complete the "destroy"
0223:                // atomically.
0224:                //
0225:                if (currentPageFlow != null
0226:                        && !currentPageFlow.isOnNestingStack()) {
0227:                    synchronized (currentPageFlow) {
0228:                        InternalUtils.setCurrentPageFlow(this , request,
0229:                                getServletContext());
0230:                    }
0231:                }
0232:                //
0233:                // Here, there is no previous page flow to syncyronize upon before destruction
0234:                //
0235:                else {
0236:                    InternalUtils.setCurrentPageFlow(this , request,
0237:                            getServletContext());
0238:                }
0239:            }
0240:
0241:            /**
0242:             * <p>
0243:             * Ensure that any changes to this object will be replicated in a cluster (for failover), even if the
0244:             * replication scheme uses a change-detection algorithm that relies on
0245:             * {@link javax.servlet.http.HttpSession#setAttribute(String, Object)} to be aware of changes.  This method is
0246:             * used by the framework and should not be called directly in most cases.
0247:             * </p>
0248:             * <p>
0249:             * Note, this method ultimately causes the Page Flow to be persisted in the {@link StorageHandler} for this web application.
0250:             * </p>
0251:             *
0252:             * @param request the current {@link HttpServletRequest}
0253:             */
0254:            public void ensureFailover(HttpServletRequest request) {
0255:                //
0256:                // remove() puts the pageflow instance into a request attribute.  Make sure not to re-save this
0257:                // instance if it's being removed.  Also, if the session is null (after having been invalidated
0258:                // by the user), don't recreate it.
0259:                //
0260:                if (request.getAttribute(REMOVING_PAGEFLOW_ATTR) != this 
0261:                        && request.getSession(false) != null) {
0262:                    StorageHandler sh = Handlers.get(getServletContext())
0263:                            .getStorageHandler();
0264:                    HttpServletRequest unwrappedRequest = PageFlowUtils
0265:                            .unwrapMultipart(request);
0266:                    RequestContext rc = new RequestContext(unwrappedRequest,
0267:                            null);
0268:
0269:                    //
0270:                    // If this is a long-lived page flow, there are two attributes to deal with, and ensure that
0271:                    // both failover correctly.
0272:                    //
0273:                    if (isLongLived()) {
0274:                        String longLivedAttrName = InternalUtils
0275:                                .getLongLivedFlowAttr(getModulePath());
0276:                        longLivedAttrName = ScopedServletUtils
0277:                                .getScopedSessionAttrName(longLivedAttrName,
0278:                                        unwrappedRequest);
0279:                        String currentLongLivedAttrName = ScopedServletUtils
0280:                                .getScopedSessionAttrName(
0281:                                        CURRENT_LONGLIVED_ATTR,
0282:                                        unwrappedRequest);
0283:                        sh.ensureFailover(rc, longLivedAttrName, this );
0284:                        sh.ensureFailover(rc, currentLongLivedAttrName,
0285:                                getModulePath());
0286:                    }
0287:                    //
0288:                    // This Page Flow is not long lived, so just the Page Flow itself needs to be added to the session.
0289:                    //
0290:                    else {
0291:                        String attrName = ScopedServletUtils
0292:                                .getScopedSessionAttrName(CURRENT_JPF_ATTR,
0293:                                        unwrappedRequest);
0294:                        sh.ensureFailover(rc, attrName, this );
0295:                    }
0296:                }
0297:            }
0298:
0299:            /**
0300:             * @exclude
0301:             */
0302:            protected ActionForward internalExecute(ActionMapping mapping,
0303:                    ActionForm form, HttpServletRequest request,
0304:                    HttpServletResponse response) throws Exception {
0305:                initializeSharedFlowFields(request);
0306:                return super .internalExecute(mapping, form, request, response);
0307:            }
0308:
0309:            private void initializeSharedFlowFields(HttpServletRequest request) {
0310:                //
0311:                // Initialize the shared flow fields.
0312:                //
0313:                CachedSharedFlowRefInfo.SharedFlowFieldInfo[] sharedFlowMemberFields = getCachedInfo()
0314:                        .getSharedFlowMemberFields();
0315:
0316:                if (sharedFlowMemberFields != null) {
0317:                    for (int i = 0; i < sharedFlowMemberFields.length; i++) {
0318:                        CachedSharedFlowRefInfo.SharedFlowFieldInfo fi = sharedFlowMemberFields[i];
0319:                        Field field = fi.field;
0320:
0321:                        if (fieldIsUninitialized(field)) {
0322:                            Map/*< String, SharedFlowController >*/sharedFlows = PageFlowUtils
0323:                                    .getSharedFlows(request);
0324:                            String name = fi.sharedFlowName;
0325:                            SharedFlowController sf = name != null ? (SharedFlowController) sharedFlows
0326:                                    .get(name)
0327:                                    : PageFlowUtils.getGlobalApp(request);
0328:
0329:                            if (sf != null) {
0330:                                initializeField(field, sf);
0331:                            } else {
0332:                                _log
0333:                                        .error("Could not find shared flow with name \""
0334:                                                + fi.sharedFlowName
0335:                                                + "\" to initialize field "
0336:                                                + field.getName()
0337:                                                + " in "
0338:                                                + getClass().getName());
0339:                            }
0340:                        }
0341:                    }
0342:                }
0343:            }
0344:
0345:            /**
0346:             * Get the a map of shared flow name to shared flow instance.
0347:             * @return a Map of shared flow name (string) to shared flow instance ({@link SharedFlowController}).
0348:             */
0349:            protected Map/*< String, SharedFlowController >*/getSharedFlows() {
0350:                return PageFlowUtils.getSharedFlows(getRequest());
0351:            }
0352:
0353:            /**
0354:             * This is a non-property public accessor that will return the property value <code>sharedFlows</code>.
0355:             * This is a non-property method because properties are exposed to databinding and that would expose
0356:             * internal data structures to attack.
0357:             * @return a Map of shared flow name (string) to shared flow instance ({@link SharedFlowController}).
0358:             */
0359:            public final Map theSharedFlows() {
0360:                return getSharedFlows();
0361:            }
0362:
0363:            /**
0364:             * Get a shared flow, based on its name as defined in this page flow's
0365:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#sharedFlowRefs sharedFlowRefs}
0366:             * attribute on {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller}.
0367:             * To retrieve any shared flow based on its class name, use {@link PageFlowUtils#getSharedFlow}.
0368:             * 
0369:             * @param sharedFlowName the name of the shared flow, as in this page flows's
0370:             *        {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#sharedFlowRefs sharedFlowRefs}
0371:             *        attribute on the {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller}
0372:             *        annotation.
0373:             * @return the {@link SharedFlowController} with the given name.
0374:             */
0375:            public SharedFlowController getSharedFlow(String sharedFlowName) {
0376:                return (SharedFlowController) PageFlowUtils.getSharedFlows(
0377:                        getRequest()).get(sharedFlowName);
0378:            }
0379:
0380:            /**
0381:             * Remove a shared flow from the session, based on its name as defined in this page flow's
0382:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#sharedFlowRefs sharedFlowRefs}
0383:             * attribute on {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller}.
0384:             * To remove any shared flow based on its class name, use {@link PageFlowUtils#removeSharedFlow}.
0385:             * 
0386:             * @param sharedFlowName the name of the shared flow, as in this page flows's
0387:             *        {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#sharedFlowRefs sharedFlowRefs}
0388:             *        attribute on the {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller}
0389:             *        annotation.
0390:             */
0391:            public void removeSharedFlow(String sharedFlowName) {
0392:                SharedFlowController sf = getSharedFlow(sharedFlowName);
0393:                if (sf != null)
0394:                    sf.removeFromSession(getRequest());
0395:            }
0396:
0397:            /**
0398:             * This is a framework method for initializing a newly-created page flow, and should not normally be called
0399:             * directly.
0400:             */
0401:            public final synchronized void create(HttpServletRequest request,
0402:                    HttpServletResponse response, ServletContext servletContext) {
0403:                reinitialize(request, response, servletContext);
0404:                initializeSharedFlowFields(request);
0405:
0406:                if (isNestable()) {
0407:                    // Initialize a ViewRenderer for exiting the nested page flow.  This is used (currently) as part of popup
0408:                    // window support -- when exiting a popup nested page flow, a special view renderer writes out javascript
0409:                    // that maps output values to the original window and closes the popup window.
0410:                    String vrClassName = request
0411:                            .getParameter(InternalConstants.RETURN_ACTION_VIEW_RENDERER_PARAM);
0412:
0413:                    if (vrClassName != null) {
0414:                        ViewRenderer vr = (ViewRenderer) DiscoveryUtils
0415:                                .newImplementorInstance(vrClassName,
0416:                                        ViewRenderer.class);
0417:
0418:                        if (vr != null) {
0419:                            vr.init(request);
0420:                            PageFlowController nestingPageFlow = PageFlowUtils
0421:                                    .getCurrentPageFlow(request, servletContext);
0422:                            nestingPageFlow.setReturnActionViewRenderer(vr);
0423:                        }
0424:                    }
0425:                }
0426:
0427:                super .create(request, response, servletContext);
0428:            }
0429:
0430:            /**
0431:             * Get the "resource taxonomy": a period-separated list that starts with the current
0432:             * web application name, continues through all of this PageFlowController's parent directories,
0433:             * and ends with this PageFlowController's class name.
0434:             */
0435:            protected String getTaxonomy() {
0436:                assert getRequest() != null : "this method can only be called during execute()";
0437:                String contextPath = getRequest().getContextPath();
0438:                assert contextPath.startsWith("/") : contextPath;
0439:                return contextPath.substring(1) + '.' + getClass().getName();
0440:            }
0441:
0442:            /**
0443:             * Get the submitted form bean from the most recent action execution in this PageFlowController.
0444:             * <p>
0445:             * <i>Note: if the current page flow does not contain a
0446:             * </i>{@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward}<i> or a
0447:             * </i>{@link org.apache.beehive.netui.pageflow.annotations.Jpf.SimpleAction &#64;Jpf.SimpleAction}<i> with
0448:             * </i><code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousAction Jpf.NavigateTo.previousAction}</code><i>,
0449:             * then this method will always return </i><code>null</code><i> by default.  To enable it in this
0450:             * situation, add the following method to the page flow:</i><br>
0451:             * <blockquote>
0452:             *     <code>
0453:             *     protected boolean alwaysTrackPreviousAction()<br>
0454:             *     {<br>
0455:             *     &nbsp;&nbsp;&nbsp;&nbsp;return true;<br>
0456:             *     }<br>
0457:             *     </code>
0458:             * </blockquote>
0459:             * 
0460:             * @deprecated This method may return an <code>ActionForm</code> wrapper when the form bean type does not extend
0461:             *             <code>ActionForm</code>.  Use {@link #getPreviousFormBean} instead.
0462:             * @return the ActionForm instance from the most recent action execution, or <code>null</code>
0463:             *         if there was no form bean submitted.
0464:             * @see #getPreviousPageInfo
0465:             * @see #getCurrentPageInfo
0466:             * @see #getPreviousActionInfo
0467:             * @see #getPreviousActionURI
0468:             * @see #getPreviousForwardPath
0469:             * @see #getCurrentForwardPath
0470:             */
0471:            protected ActionForm getPreviousForm() {
0472:                checkPreviousActionInfoDisabled();
0473:                return _previousActionInfo != null ? _previousActionInfo
0474:                        .getForm() : null;
0475:            }
0476:
0477:            /**
0478:             * Get the submitted form bean from the most recent action execution in this PageFlowController.
0479:             * <p>
0480:             * <i>Note: if the current page flow does not contain a
0481:             * </i>{@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward}<i> or a
0482:             * </i>{@link org.apache.beehive.netui.pageflow.annotations.Jpf.SimpleAction &#64;Jpf.SimpleAction}<i> with
0483:             * </i><code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousAction Jpf.NavigateTo.previousAction}</code><i>,
0484:             * then this method will always return </i><code>null</code><i> by default.  To enable it in this
0485:             * situation, add the following method to the page flow:</i><br>
0486:             * <blockquote>
0487:             *     <code>
0488:             *     protected boolean alwaysTrackPreviousAction()<br>
0489:             *     {<br>
0490:             *     &nbsp;&nbsp;&nbsp;&nbsp;return true;<br>
0491:             *     }<br>
0492:             *     </code>
0493:             * </blockquote>
0494:             * 
0495:             * @return the form bean instance from the most recent action execution, or <code>null</code>
0496:             *         if there was no form bean submitted.
0497:             * @see #getPreviousPageInfo
0498:             * @see #getCurrentPageInfo
0499:             * @see #getPreviousActionInfo
0500:             * @see #getPreviousActionURI
0501:             * @see #getPreviousForwardPath
0502:             * @see #getCurrentForwardPath
0503:             */
0504:            protected Object getPreviousFormBean() {
0505:                checkPreviousActionInfoDisabled();
0506:                return _previousActionInfo != null ? InternalUtils
0507:                        .unwrapFormBean(_previousActionInfo.getForm()) : null;
0508:            }
0509:
0510:            /**
0511:             * Get the URI for the most recent action in this PageFlowController.
0512:             * <p>
0513:             * <i>Note: if the current page flow does not use a
0514:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward},
0515:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.SimpleAction &#64;Jpf.SimpleAction}, or
0516:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.ConditionalForward &#64;Jpf.ConditionalForward}
0517:             * with <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousAction previousAction}</code>,
0518:             * then this method will always return </i><code>null</code><i> by default.  To enable it in this situation, add the
0519:             * following method to the page flow:</i><br>
0520:             * <blockquote>
0521:             *     <code>
0522:             *     protected boolean alwaysTrackPreviousAction()<br>
0523:             *     {<br>
0524:             *     &nbsp;&nbsp;&nbsp;&nbsp;return true;<br>
0525:             *     }<br>
0526:             *     </code>
0527:             * </blockquote>
0528:             * 
0529:             * @return a String that is the most recent URI.
0530:             * @see #getPreviousPageInfo
0531:             * @see #getCurrentPageInfo
0532:             * @see #getPreviousActionInfo
0533:             * @see #getPreviousFormBean
0534:             * @see #getPreviousForwardPath
0535:             * @see #getCurrentForwardPath
0536:             */
0537:            protected String getPreviousActionURI() {
0538:                checkPreviousActionInfoDisabled();
0539:                return _previousActionInfo != null ? _previousActionInfo
0540:                        .getActionURI() : null;
0541:            }
0542:
0543:            /**
0544:             * Get the webapp-relative URI for the most recent page (in this page flow) shown to the user.
0545:             * <p>
0546:             * <i>Note: if the current page flow does not use a
0547:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward},
0548:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.SimpleAction &#64;Jpf.SimpleAction}, or
0549:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.ConditionalForward &#64;Jpf.ConditionalForward}
0550:             * with <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#currentPage currentPage}</code>
0551:             * or <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousPage previousPage}</code>,
0552:             * then this method will always return </i><code>null</code><i> by default.  To enable it in this situation, add the
0553:             * following method to the page flow:</i><br>
0554:             * <blockquote>
0555:             *     <code>
0556:             *     protected boolean alwaysTrackPreviousPage()<br>
0557:             *     {<br>
0558:             *     &nbsp;&nbsp;&nbsp;&nbsp;return true;<br>
0559:             *     }<br>
0560:             *     </code>
0561:             * </blockquote>
0562:             * 
0563:             * @return a String that is the URI path for the most recent page shown to the user.
0564:             * @see #getPreviousPageInfo
0565:             * @see #getCurrentPageInfo
0566:             * @see #getPreviousActionInfo
0567:             * @see #getPreviousActionURI
0568:             * @see #getPreviousFormBean
0569:             * @see #getPreviousForwardPath
0570:             */
0571:            public String getCurrentForwardPath() {
0572:                PreviousPageInfo curPageInfo = getCurrentPageInfo();
0573:                String path = null;
0574:
0575:                if (curPageInfo != null) {
0576:                    ActionForward curForward = curPageInfo.getForward();
0577:                    if (curForward != null) {
0578:                        if (curForward.getContextRelative()) {
0579:                            path = curForward.getPath();
0580:                        } else {
0581:                            path = getModulePath() + curForward.getPath();
0582:                        }
0583:                    }
0584:                }
0585:                return path;
0586:            }
0587:
0588:            /**
0589:             * Get the webapp-relative URI for the previous page (in this page flow) shown to the user.
0590:             * The previous page is the one shown before the most recent page.
0591:             * <p>
0592:             * <i>Note: if the current page flow does not use a
0593:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward},
0594:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.SimpleAction &#64;Jpf.SimpleAction}, or
0595:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.ConditionalForward &#64;Jpf.ConditionalForward}
0596:             * with <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#currentPage currentPage}</code>
0597:             * or <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousPage previousPage}</code>,
0598:             * then this method will always return </i><code>null</code><i> by default.  To enable it in this situation, add the
0599:             * following method to the page flow:</i><br>
0600:             * <blockquote>
0601:             *     <code>
0602:             *     protected boolean alwaysTrackPreviousPage()<br>
0603:             *     {<br>
0604:             *     &nbsp;&nbsp;&nbsp;&nbsp;return true;<br>
0605:             *     }<br>
0606:             *     </code>
0607:             * </blockquote>
0608:             * 
0609:             * @return a String that is the URI path for the previous page shown to the user.
0610:             * @see #getPreviousPageInfo
0611:             * @see #getCurrentPageInfo
0612:             * @see #getPreviousActionInfo
0613:             * @see #getPreviousActionURI
0614:             * @see #getPreviousFormBean
0615:             * @see #getCurrentForwardPath
0616:             */
0617:            protected String getPreviousForwardPath() {
0618:                PreviousPageInfo prevPageInfo = getPreviousPageInfo();
0619:
0620:                if (prevPageInfo != null) {
0621:                    ActionForward prevForward = prevPageInfo.getForward();
0622:                    return prevForward != null ? prevForward.getPath() : null;
0623:                } else {
0624:                    return null;
0625:                }
0626:            }
0627:
0628:            /**
0629:             * Get a legacy PreviousPageInfo.
0630:             * @deprecated This method will be removed without replacement in the next release.
0631:             */
0632:            public final PreviousPageInfo getPreviousPageInfoLegacy(
0633:                    PageFlowController curJpf, HttpServletRequest request) {
0634:                if (PageFlowRequestWrapper.get(request)
0635:                        .isReturningFromNesting()) {
0636:                    return getCurrentPageInfo();
0637:                } else {
0638:                    return getPreviousPageInfo();
0639:                }
0640:            }
0641:
0642:            /**
0643:             * Get information about the most recent page (in this page flow) shown to the user.
0644:             * <p>
0645:             * <i>Note: if the current page flow does not use a
0646:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward},
0647:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.SimpleAction &#64;Jpf.SimpleAction}, or
0648:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.ConditionalForward &#64;Jpf.ConditionalForward}
0649:             * with <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#currentPage currentPage}</code>
0650:             * or <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousPage previousPage}</code>,
0651:             * then this method will always return </i><code>null</code><i> by default.  To enable it in this situation, add the
0652:             * following method to the page flow:</i><br>
0653:             * <blockquote>
0654:             *     <code>
0655:             *     protected boolean alwaysTrackPreviousPage()<br>
0656:             *     {<br>
0657:             *     &nbsp;&nbsp;&nbsp;&nbsp;return true;<br>
0658:             *     }<br>
0659:             *     </code>
0660:             * </blockquote>
0661:             * 
0662:             * @return a PreviousPageInfo with information about the most recent page shown to the user.
0663:             * @see #getPreviousPageInfo
0664:             * @see #getPreviousActionInfo
0665:             * @see #getPreviousActionURI
0666:             * @see #getPreviousFormBean
0667:             * @see #getPreviousForwardPath
0668:             * @see #getCurrentForwardPath
0669:             */
0670:            protected final PreviousPageInfo getCurrentPageInfo() {
0671:                checkPreviousPageInfoDisabled();
0672:
0673:                if (_currentPageInfo != null) {
0674:                    // Allows it to reconstruct transient members after session failover
0675:                    _currentPageInfo.reinitialize(this );
0676:                }
0677:
0678:                return _currentPageInfo;
0679:            }
0680:
0681:            /**
0682:             * This is a non-property public accessor that will return the property value <code>currrentPageInfo</code>.
0683:             * This is a non-property method because properties are exposed to databinding and that would expose
0684:             * internal data structures to attack.
0685:             * @return a PreviousPageInfo with information about the most recent page shown to the user.
0686:             */
0687:            public final PreviousPageInfo theCurrentPageInfo() {
0688:                return getCurrentPageInfo();
0689:            }
0690:
0691:            /**
0692:             * Get information about the previous page (in this page flow) shown to the user.  The previous
0693:             * page is the one shown before the most recent page.
0694:             * <p>
0695:             * <i>Note: if the current page flow does not use a
0696:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward},
0697:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.SimpleAction &#64;Jpf.SimpleAction}, or
0698:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.ConditionalForward &#64;Jpf.ConditionalForward}
0699:             * with <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#currentPage currentPage}</code>
0700:             * or <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousPage previousPage}</code>,
0701:             * then this method will always return </i><code>null</code><i> by default.  To enable it in this situation, add the
0702:             * following method to the page flow:</i><br>
0703:             * </blockquote>
0704:             * 
0705:             * @return a PreviousPageInfo with information about the previous page shown to the user.
0706:             * @see #getCurrentPageInfo
0707:             * @see #getPreviousActionInfo
0708:             * @see #getPreviousActionURI
0709:             * @see #getPreviousFormBean
0710:             * @see #getPreviousForwardPath
0711:             * @see #getCurrentForwardPath
0712:             */
0713:            protected final PreviousPageInfo getPreviousPageInfo() {
0714:                checkPreviousPageInfoDisabled();
0715:
0716:                PreviousPageInfo ret = _previousPageInfo != null ? _previousPageInfo
0717:                        : _currentPageInfo;
0718:
0719:                if (ret != null) {
0720:                    ret.reinitialize(this ); // Allows it to reconstruct transient members after session failover
0721:                }
0722:
0723:                return ret;
0724:            }
0725:
0726:            /**
0727:             * This is a non-property public accessor that will return the property value <code>previousPageInfo</code>.
0728:             * This is a non-property method because properties are exposed to databinding and that would expose
0729:             * internal data structures to attack.
0730:             * @return a PreviousPageInfo with information about the previous page shown to the user.
0731:             */
0732:            public final PreviousPageInfo thePreviousPageInfo() {
0733:                return getPreviousPageInfo();
0734:            }
0735:
0736:            /**
0737:             * Get information about the most recent action run in this page flow.
0738:             * <p>
0739:             * <i>Note: if the current page flow does not use a
0740:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Forward &#64;Jpf.Forward},
0741:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.SimpleAction &#64;Jpf.SimpleAction}, or
0742:             * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.ConditionalForward &#64;Jpf.ConditionalForward}
0743:             * with <code>navigateTo={@link org.apache.beehive.netui.pageflow.annotations.Jpf.NavigateTo#previousAction previousAction}</code>,
0744:             * then this method will always return </i><code>null</code><i> by default.  To enable it in this situation, add the
0745:             * following method to the page flow:</i><br>
0746:             * <blockquote>
0747:             *     <code>
0748:             *     protected boolean alwaysTrackPreviousAction()<br>
0749:             *     {<br>
0750:             *     &nbsp;&nbsp;&nbsp;&nbsp;return true;<br>
0751:             *     }<br>
0752:             *     </code>
0753:             * </blockquote>
0754:             * 
0755:             * @return a PreviousActionInfo with information about the most recent action run in this page flow.
0756:             * @see #getPreviousPageInfo
0757:             * @see #getCurrentPageInfo
0758:             * @see #getPreviousActionURI
0759:             * @see #getPreviousFormBean
0760:             * @see #getPreviousForwardPath
0761:             * @see #getCurrentForwardPath
0762:             */
0763:            protected final PreviousActionInfo getPreviousActionInfo() {
0764:                checkPreviousActionInfoDisabled();
0765:                return _previousActionInfo;
0766:            }
0767:
0768:            /**
0769:             * This is a non-property public accessor that will return the property value <code>previousActionInfo</code>.
0770:             * This is a non-property method because properties are exposed to databinding and that would expose
0771:             * internal data structures to attack.
0772:             * @return a PreviousActionInfo with information about the most recent action run in this page flow.
0773:             */
0774:            public final PreviousActionInfo thePreviousActionInfo() {
0775:                return getPreviousActionInfo();
0776:            }
0777:
0778:            private void checkPreviousActionInfoDisabled() {
0779:                if (isPreviousActionInfoDisabled()) {
0780:                    throw new IllegalStateException(
0781:                            "Previous action information has been disabled in this page flow.  Override alwaysTrackPreviousAction() to enable it.");
0782:                }
0783:            }
0784:
0785:            private void checkPreviousPageInfoDisabled() {
0786:                if (isPreviousPageInfoDisabled()) {
0787:                    throw new IllegalStateException(
0788:                            "Previous page information has been disabled in this page flow.  Override alwaysTrackPreviousPage() to enable it.");
0789:                }
0790:            }
0791:
0792:            /**
0793:             * Get the display name of this page flow.
0794:             * @return the display name (the URI) of this page flow.
0795:             */
0796:            public String getDisplayName() {
0797:                return getURI();
0798:            }
0799:
0800:            public boolean isPreviousActionInfoDisabled() {
0801:                if (alwaysTrackPreviousAction())
0802:                    return false;
0803:
0804:                ModuleConfig mc = getModuleConfig();
0805:                ControllerConfig cc = mc.getControllerConfig();
0806:                return cc instanceof  PageFlowControllerConfig
0807:                        && ((PageFlowControllerConfig) cc)
0808:                                .isReturnToActionDisabled();
0809:            }
0810:
0811:            public boolean isPreviousPageInfoDisabled() {
0812:                if (alwaysTrackPreviousPage())
0813:                    return false;
0814:
0815:                ModuleConfig mc = getModuleConfig();
0816:                ControllerConfig cc = mc.getControllerConfig();
0817:                return cc instanceof  PageFlowControllerConfig
0818:                        && ((PageFlowControllerConfig) cc)
0819:                                .isReturnToPageDisabled();
0820:            }
0821:
0822:            /**
0823:             * Called from {@link FlowController#execute}.
0824:             */
0825:            void savePreviousActionInfo(ActionForm form,
0826:                    HttpServletRequest request, ActionMapping mapping,
0827:                    ServletContext servletContext) {
0828:                //
0829:                // If previous-action is disabled (unused in this pageflow), just return.
0830:                //
0831:                if (isPreviousActionInfoDisabled())
0832:                    return;
0833:                String actionURI = InternalUtils.getDecodedServletPath(request);
0834:                _previousActionInfo = new PreviousActionInfo(form, actionURI,
0835:                        request.getQueryString());
0836:            }
0837:
0838:            /**
0839:             * Store information about recent pages displayed.  This is a framework-invoked method that should not normally be
0840:             * called directly.
0841:             */
0842:            public void savePreviousPageInfo(ActionForward forward,
0843:                    ActionForm form, ActionMapping mapping,
0844:                    HttpServletRequest request, ServletContext servletContext,
0845:                    boolean isSpecialForward) {
0846:                if (forward != null) {
0847:                    //
0848:                    // If previous-page is disabled (unused in this pageflow), or if we've already saved prevous-page info in
0849:                    // this request (for example, forward to foo.faces which forwards to foo.jsp), just return.
0850:                    //
0851:                    if (request.getAttribute(SAVED_PREVIOUS_PAGE_INFO_ATTR) != null
0852:                            || isPreviousPageInfoDisabled())
0853:                        return;
0854:
0855:                    String path = forward.getPath();
0856:                    int queryPos = path.indexOf('?');
0857:                    if (queryPos != -1)
0858:                        path = path.substring(0, queryPos);
0859:
0860:                    //
0861:                    // If a form bean was generated in this request, add it to the most recent PreviousPageInfo, so when we
0862:                    // go back to that page, the *updated* field values are restored (i.e., we don't revert to the values of
0863:                    // the form that was passed into the page originally).
0864:                    //
0865:                    if (form != null && _currentPageInfo != null) {
0866:                        ActionForm oldForm = _currentPageInfo.getForm();
0867:                        if (oldForm == null
0868:                                || oldForm.getClass().equals(form.getClass())) {
0869:                            _currentPageInfo.setForm(form);
0870:                            _currentPageInfo.setMapping(mapping);
0871:                        }
0872:                    }
0873:
0874:                    //
0875:                    // Only keep track of *pages* forwarded to -- not actions or pageflows.
0876:                    //
0877:                    if (!FileUtils.osSensitiveEndsWith(path, ACTION_EXTENSION)) {
0878:                        //
0879:                        // Only save previous-page info if the page is within this pageflow.
0880:                        //
0881:                        if (isLocalFile(forward)) // || PageFlowUtils.osSensitiveEndsWith( path, JPF_EXTENSION ) )
0882:                        {
0883:                            _previousPageInfo = _currentPageInfo;
0884:                            _currentPageInfo = new PreviousPageInfo(forward,
0885:                                    form, mapping, request.getQueryString());
0886:                            request.setAttribute(SAVED_PREVIOUS_PAGE_INFO_ATTR,
0887:                                    Boolean.TRUE);
0888:                        }
0889:                    }
0890:                }
0891:            }
0892:
0893:            private boolean isLocalFile(ActionForward forward) {
0894:                String path = forward.getPath();
0895:
0896:                if (!forward.getContextRelative()) {
0897:                    return path.indexOf('/', 1) == -1; // all paths in Struts start with '/'
0898:                } else {
0899:                    String modulePath = getModulePath();
0900:
0901:                    if (!path.startsWith(modulePath)) {
0902:                        return false;
0903:                    } else {
0904:                        return path.indexOf('/', modulePath.length() + 1) == -1;
0905:                    }
0906:                }
0907:            }
0908:
0909:            private boolean isOnNestingStack() {
0910:                return _isOnNestingStack;
0911:            }
0912:
0913:            /**
0914:             * Callback when this object is removed from the user session.  Causes {@link #onDestroy} to be called.  This is a
0915:             * framework-invoked method that should not be called directly.
0916:             */
0917:            public void valueUnbound(HttpSessionBindingEvent event) {
0918:                //
0919:                // Unless this pageflow has been pushed onto the nesting stack, do the onDestroy() callback.
0920:                //
0921:                if (!_isOnNestingStack) {
0922:                    super .valueUnbound(event);
0923:                }
0924:            }
0925:
0926:            void setIsOnNestingStack(boolean isOnNestingStack) {
0927:                _isOnNestingStack = isOnNestingStack;
0928:            }
0929:
0930:            ActionForward forwardTo(ActionForward fwd, ActionMapping mapping,
0931:                    PageFlowExceptionConfig exceptionConfig, String actionName,
0932:                    ModuleConfig altModuleConfig, ActionForm form,
0933:                    HttpServletRequest request, HttpServletResponse response,
0934:                    ServletContext servletContext) {
0935:                ActionForward super Fwd = super .forwardTo(fwd, mapping,
0936:                        exceptionConfig, actionName, altModuleConfig, form,
0937:                        request, response, servletContext);
0938:
0939:                //
0940:                // Special case: the *only* way for a nested pageflow to nest itself is for it
0941:                // to forward to itself as a .jpf.  Simply executing an action in the .jpf isn't
0942:                // enough, obviously, since it's impossible to tell whether it should be executed
0943:                // in the current pageflow or a new nested one.
0944:                //
0945:                if (super Fwd != null
0946:                        && InternalUtils.isNestable(getModuleConfig())) {
0947:                    boolean selfNesting = false;
0948:
0949:                    if (super Fwd.getContextRelative()) {
0950:                        if (super Fwd.getPath().equals(getURI())) {
0951:                            selfNesting = true;
0952:                        }
0953:                    } else {
0954:                        if (super Fwd.getPath().equals(getStrutsLocalURI())) {
0955:                            selfNesting = true;
0956:                        }
0957:                    }
0958:
0959:                    if (selfNesting) {
0960:                        if (_log.isDebugEnabled()) {
0961:                            _log.debug("Self-nesting page flow " + getURI());
0962:                        }
0963:
0964:                        try {
0965:                            // This will cause the right pageflow stack stuff to happen.
0966:                            RequestContext rc = new RequestContext(request,
0967:                                    response);
0968:                            FlowControllerFactory.get(getServletContext())
0969:                                    .createPageFlow(rc, getClass());
0970:                        } catch (IllegalAccessException e) {
0971:                            // This should never happen -- if we successfully created this page flow once, we can do it again.
0972:                            assert false : e;
0973:                            _log.error(e);
0974:                        } catch (InstantiationException e) {
0975:                            _log.error(
0976:                                    "Could not create PageFlowController instance of type "
0977:                                            + getClass().getName(), e);
0978:                        }
0979:                    }
0980:                }
0981:
0982:                return super Fwd;
0983:            }
0984:
0985:            private String getStrutsLocalURI() {
0986:                String className = getClass().getName();
0987:                int lastDot = className.lastIndexOf('.');
0988:                InternalStringBuilder ret = new InternalStringBuilder("/");
0989:                return ret.append(className.substring(lastDot + 1)).append(
0990:                        PAGEFLOW_EXTENSION).toString();
0991:            }
0992:
0993:            private CachedPageFlowInfo getCachedInfo() {
0994:                ClassLevelCache cache = ClassLevelCache.getCache(getClass());
0995:                CachedPageFlowInfo info = (CachedPageFlowInfo) cache
0996:                        .getCacheObject(CACHED_INFO_KEY);
0997:
0998:                if (info == null) {
0999:                    info = new CachedPageFlowInfo(getClass(),
1000:                            getServletContext());
1001:                    cache.setCacheObject(CACHED_INFO_KEY, info);
1002:                }
1003:
1004:                return info;
1005:            }
1006:
1007:            final void beforePage() {
1008:                //
1009:                // We may need to save the previous page info if the page was called directly (not forwarded through an action)
1010:                // and we do not yet have the forward path in the page flow or it is a different path.
1011:                //
1012:                if (!isPreviousPageInfoDisabled()) {
1013:                    HttpServletRequest request = getRequest();
1014:                    String relativeUri = InternalUtils
1015:                            .getDecodedServletPath(request);
1016:
1017:                    String path = getCurrentForwardPath();
1018:                    if (path == null || !path.equals(relativeUri)) {
1019:                        ActionForward actionForward = new ActionForward(
1020:                                relativeUri);
1021:                        actionForward.setContextRelative(true);
1022:                        actionForward.setRedirect(false);
1023:                        savePreviousPageInfo(actionForward, null, null,
1024:                                request, getServletContext(), false);
1025:                    }
1026:                }
1027:            }
1028:
1029:            /**
1030:             * @exclude
1031:             */
1032:            public ActionForward exitNesting(HttpServletRequest request,
1033:                    HttpServletResponse response, ActionMapping mapping,
1034:                    ActionForm form) {
1035:                // Get any return-action view renderer from the original ("nesting") page flow.  If there is one, we'll
1036:                // use it later to render the view.
1037:                PageFlowController nestingPageFlow = PageFlowUtils
1038:                        .getNestingPageFlow(request, getServletContext());
1039:                ViewRenderer returnActionViewRenderer = nestingPageFlow
1040:                        .getReturnActionViewRenderer();
1041:
1042:                if (returnActionViewRenderer != null) {
1043:                    PageFlowRequestWrapper.get(request).setViewRenderer(
1044:                            returnActionViewRenderer);
1045:                    nestingPageFlow.setReturnActionViewRenderer(null); // we don't need it anymore
1046:                }
1047:
1048:                PerRequestState prevState = setPerRequestState(new PerRequestState(
1049:                        request, response, mapping));
1050:
1051:                try {
1052:                    onExitNesting();
1053:                } catch (Throwable th) {
1054:                    try {
1055:                        return handleException(th, mapping, form, request,
1056:                                response);
1057:                    } catch (Exception e) {
1058:                        _log
1059:                                .error(
1060:                                        "Exception thrown while handling exception.",
1061:                                        e);
1062:                    }
1063:                } finally {
1064:                    setPerRequestState(prevState);
1065:                }
1066:
1067:                return null;
1068:            }
1069:
1070:            /**
1071:             * Callback that is invoked when this controller instance is exiting nesting through a return action.
1072:             * {@link FlowController#getRequest}, {@link FlowController#getResponse}, {@link FlowController#getSession}
1073:             * may all be used during this method.
1074:             */
1075:            protected void onExitNesting() throws Exception {
1076:            }
1077:
1078:            private ViewRenderer getReturnActionViewRenderer() {
1079:                return _returnActionViewRenderer;
1080:            }
1081:
1082:            private void setReturnActionViewRenderer(
1083:                    ViewRenderer returnActionViewRenderer) {
1084:                _returnActionViewRenderer = returnActionViewRenderer;
1085:            }
1086:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.