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.FreezableMutableURI;
0022: import org.apache.beehive.netui.core.urls.MutableURI;
0023: import org.apache.beehive.netui.core.urls.URIContext;
0024: import org.apache.beehive.netui.core.urls.URLRewriterService;
0025: import org.apache.beehive.netui.core.urls.URLType;
0026: import org.apache.beehive.netui.core.urltemplates.URLTemplatesFactory;
0027: import org.apache.beehive.netui.pageflow.internal.ActionResultImpl;
0028: import org.apache.beehive.netui.pageflow.internal.InternalUtils;
0029: import org.apache.beehive.netui.pageflow.internal.InternalConstants;
0030: import org.apache.beehive.netui.pageflow.internal.AdapterManager;
0031: import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
0032: import org.apache.beehive.netui.pageflow.internal.URIContextFactory;
0033: import org.apache.beehive.netui.pageflow.internal.DefaultURLTemplatesFactory;
0034: import org.apache.beehive.netui.pageflow.scoping.ScopedRequest;
0035: import org.apache.beehive.netui.pageflow.scoping.ScopedResponse;
0036: import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
0037: import org.apache.beehive.netui.pageflow.handler.StorageHandler;
0038: import org.apache.beehive.netui.pageflow.handler.Handlers;
0039: import org.apache.beehive.netui.util.internal.InternalStringBuilder;
0040: import org.apache.beehive.netui.util.internal.FileUtils;
0041: import org.apache.beehive.netui.util.internal.ServletUtils;
0042: import org.apache.beehive.netui.util.internal.concurrent.InternalConcurrentHashMap;
0043: import org.apache.beehive.netui.util.config.ConfigUtil;
0044: import org.apache.beehive.netui.util.config.bean.UrlConfig;
0045: import org.apache.beehive.netui.util.logging.Logger;
0046: import org.apache.beehive.netui.script.common.ImplicitObjectUtil;
0047: import org.apache.struts.action.ActionForm;
0048: import org.apache.struts.action.ActionMapping;
0049: import org.apache.struts.action.ActionServlet;
0050: import org.apache.struts.action.ActionMessage;
0051: import org.apache.struts.config.FormBeanConfig;
0052: import org.apache.struts.config.ModuleConfig;
0053: import org.apache.struts.upload.MultipartRequestWrapper;
0054: import org.apache.struts.util.RequestUtils;
0055:
0056: import javax.servlet.RequestDispatcher;
0057: import javax.servlet.ServletContext;
0058: import javax.servlet.ServletRequest;
0059: import javax.servlet.http.HttpServletRequest;
0060: import javax.servlet.http.HttpServletResponse;
0061: import java.io.PrintStream;
0062: import java.net.URISyntaxException;
0063: import java.util.Collections;
0064: import java.util.HashMap;
0065: import java.util.Map;
0066: import java.util.Stack;
0067: import java.util.List;
0068: import java.util.ArrayList;
0069: import java.util.Iterator;
0070:
0071: /**
0072: * Utility methods related to Page Flow.
0073: */
0074: public class PageFlowUtils implements PageFlowConstants,
0075: InternalConstants {
0076: private static final Logger _log = Logger
0077: .getInstance(PageFlowUtils.class);
0078:
0079: private static final String PREVENT_CACHE_ATTR = InternalConstants.ATTR_PREFIX
0080: + "preventCache";
0081: private static final String ACTION_URI_ATTR = ATTR_PREFIX
0082: + "_actionURI";
0083: private static final int PAGEFLOW_EXTENSION_LEN = PAGEFLOW_EXTENSION
0084: .length();
0085: private static final String DEFAULT_AUTORESOLVE_EXTENSIONS[] = new String[] {
0086: ACTION_EXTENSION, PAGEFLOW_EXTENSION };
0087:
0088: /** Map of Struts module prefix to Map of form-type-name to form-name. */
0089: private static Map/*< String, Map< String, List< String > > >*/_formNameMaps = new InternalConcurrentHashMap/*< String, Map< String, List< String > > >*/();
0090:
0091: /**
0092: * Get the Struts module path for a URI. This is the parent directory, relative to the web
0093: * application root, of the file referenced by the URI.
0094: *
0095: * @param request the current HttpServletRequest.
0096: * @param requestURI the URI for which to get the Struts module path.
0097: */
0098: public static String getModulePath(HttpServletRequest request,
0099: String requestURI) {
0100: return getModulePathForRelativeURI(getRelativeURI(request,
0101: requestURI, null));
0102: }
0103:
0104: /**
0105: * Get the Struts module path for the current request URI. This is the parent directory,
0106: * relative to the web application root, of the file referenced by the request URI.
0107: *
0108: * @param request the current HttpServletRequest.
0109: */
0110: public static String getModulePath(HttpServletRequest request) {
0111: return getModulePathForRelativeURI(InternalUtils
0112: .getDecodedServletPath(request));
0113: }
0114:
0115: /**
0116: * Get the Struts module path for a URI that is relative to the web application root.
0117: *
0118: * @param uri the URI for which to get the module path.
0119: */
0120: public static String getModulePathForRelativeURI(String uri) {
0121: if (uri == null)
0122: return null;
0123: assert uri.length() > 0;
0124: assert uri.charAt(0) == '/' : uri;
0125:
0126: // Strip off the actual page name (e.g., some_page.jsp)
0127: int slash = uri.lastIndexOf('/');
0128: uri = uri.substring(0, slash);
0129:
0130: return uri;
0131: }
0132:
0133: /**
0134: * Get the request URI, relative to the URI of the given PageFlowController.
0135: *
0136: * @param request the current HttpServletRequest.
0137: * @param relativeTo a PageFlowController to which the returned URI should be relative, or
0138: * <code>null</code> if the returned URI should be relative to the webapp root.
0139: */
0140: public static String getRelativeURI(HttpServletRequest request,
0141: PageFlowController relativeTo) {
0142: if (relativeTo == null)
0143: return InternalUtils.getDecodedServletPath(request);
0144: return getRelativeURI(request, InternalUtils
0145: .getDecodedURI(request), relativeTo);
0146: }
0147:
0148: /**
0149: * Get a URI relative to the URI of the given PageFlowController.
0150: *
0151: * @param request the current HttpServletRequest.
0152: * @param uri the URI which should be made relative.
0153: * @param relativeTo a PageFlowController to which the returned URI should be relative, or
0154: * <code>null</code> if the returned URI should be relative to the webapp root.
0155: */
0156: public static String getRelativeURI(HttpServletRequest request,
0157: String uri, PageFlowController relativeTo) {
0158: String contextPath = request.getContextPath();
0159: if (relativeTo != null)
0160: contextPath += relativeTo.getModulePath();
0161: int overlap = uri.indexOf(contextPath + '/');
0162: if (overlap == -1)
0163: return null;
0164: return uri.substring(overlap + contextPath.length());
0165: }
0166:
0167: /**
0168: * Get a URI for the "begin" action in the PageFlowController associated with the given
0169: * request URI.
0170: *
0171: * @return a String that is the URI for the "begin" action in the PageFlowController associated
0172: * with the given request URI.
0173: */
0174: public static String getBeginActionURI(String requestURI) {
0175: // Translate this to a request for the begin action ("begin.do") for this PageFlowController.
0176: InternalStringBuilder retVal = new InternalStringBuilder();
0177: int lastSlash = requestURI.lastIndexOf('/');
0178:
0179: if (lastSlash != -1) {
0180: retVal.append(requestURI.substring(0, lastSlash));
0181: }
0182:
0183: retVal.append('/').append(BEGIN_ACTION_NAME).append(
0184: ACTION_EXTENSION);
0185: return retVal.toString();
0186: }
0187:
0188: /**
0189: * Get the stack of nested page flows for the current user session. Create and store an empty
0190: * stack if none exists.
0191: *
0192: * @deprecated Use {@link PageFlowStack#get(HttpServletRequest, ServletContext)} instead.
0193: *
0194: * @param request the current HttpServletRequest
0195: * @return a {@link PageFlowStack} of nested page flows ({@link PageFlowController}s) for the current user session.
0196: */
0197: public static Stack getPageFlowStack(HttpServletRequest request) {
0198: ServletContext servletContext = InternalUtils
0199: .getServletContext(request);
0200: return PageFlowStack.get(request, servletContext, true)
0201: .getLegacyStack();
0202: }
0203:
0204: /**
0205: * Destroys the stack of {@link PageFlowController}s that have invoked nested page flows.
0206: *
0207: * @deprecated Use {@link PageFlowStack#destroy} instead.
0208: *
0209: * @param request the current HttpServletRequest.
0210: */
0211: public static void destroyPageFlowStack(HttpServletRequest request) {
0212: ServletContext servletContext = InternalUtils
0213: .getServletContext(request);
0214: PageFlowStack.get(request, servletContext).destroy(request);
0215: }
0216:
0217: /**
0218: * Get the {@link PageFlowController} that is nesting the current one.
0219: * @deprecated Use {@link #getNestingPageFlow(HttpServletRequest, ServletContext)} instead.
0220: *
0221: * @param request the current HttpServletRequest.
0222: * @return the nesting {@link PageFlowController}, or <code>null</code> if the current one
0223: * is not being nested.
0224: */
0225: public static PageFlowController getNestingPageFlow(
0226: HttpServletRequest request) {
0227: ServletContext servletContext = InternalUtils
0228: .getServletContext(request);
0229: return getNestingPageFlow(request, servletContext);
0230: }
0231:
0232: /**
0233: * Get the {@link PageFlowController} that is nesting the current one.
0234: *
0235: * @param request the current HttpServletRequest.
0236: * @param servletContext the current ServletContext.
0237: * @return the nesting {@link PageFlowController}, or <code>null</code> if the current one
0238: * is not being nested.
0239: */
0240: public static PageFlowController getNestingPageFlow(
0241: HttpServletRequest request, ServletContext servletContext) {
0242: PageFlowStack jpfStack = PageFlowStack.get(request,
0243: servletContext, false);
0244:
0245: if (jpfStack != null && !jpfStack.isEmpty()) {
0246: PageFlowController top = jpfStack.peek().getPageFlow();
0247: return top;
0248: }
0249:
0250: return null;
0251: }
0252:
0253: /**
0254: * Get the current {@link PageFlowController}.
0255: *
0256: * @param request the current HttpServletRequest.
0257: * @param servletContext the current ServletContext.
0258: * @return the current PageFlowController from the user session, or <code>null</code> if there is none.
0259: */
0260: public static PageFlowController getCurrentPageFlow(
0261: HttpServletRequest request, ServletContext servletContext) {
0262: ActionResolver cur = getCurrentActionResolver(request,
0263: servletContext);
0264:
0265: if (cur != null && cur.isPageFlow()) {
0266: PageFlowController pfc = (PageFlowController) cur;
0267: pfc.reinitializeIfNecessary(request, null, servletContext);
0268: return pfc;
0269: }
0270:
0271: return null;
0272: }
0273:
0274: /**
0275: /**
0276: * Get the current PageFlowController.
0277: * @deprecated Use {@link #getCurrentPageFlow(HttpServletRequest, ServletContext)} instead.
0278: *
0279: * @param request the current HttpServletRequest.
0280: * @return the current PageFlowController from the user session, or <code>null</code>
0281: * if there is none.
0282: */
0283: public static PageFlowController getCurrentPageFlow(
0284: HttpServletRequest request) {
0285: ActionResolver cur = getCurrentActionResolver(request);
0286: return cur != null && cur.isPageFlow() ? (PageFlowController) cur
0287: : null;
0288: }
0289:
0290: /**
0291: * Get the current ActionResolver.
0292: * @deprecated Use {@link #getCurrentPageFlow(HttpServletRequest, ServletContext)} instead.
0293: *
0294: * @return the current ActionResolver from the user session, or <code>null</code> if there is none.
0295: */
0296: public static ActionResolver getCurrentActionResolver(
0297: HttpServletRequest request) {
0298: ServletContext servletContext = InternalUtils
0299: .getServletContext(request);
0300: return getCurrentActionResolver(request, servletContext);
0301: }
0302:
0303: /**
0304: * Get the current ActionResolver.
0305: * @deprecated Use {@link #getCurrentPageFlow(HttpServletRequest, ServletContext)} instead.
0306: *
0307: *
0308: * @param request the current HttpServletRequest.
0309: * @param servletContext the current ServletContext.
0310: * @return the current ActionResolver from the user session, or <code>null</code> if there is none.
0311: */
0312: public static ActionResolver getCurrentActionResolver(
0313: HttpServletRequest request, ServletContext servletContext) {
0314: StorageHandler sh = Handlers.get(servletContext)
0315: .getStorageHandler();
0316: HttpServletRequest unwrappedRequest = unwrapMultipart(request);
0317: RequestContext rc = new RequestContext(unwrappedRequest, null);
0318:
0319: //
0320: // First see if the current page flow is a long-lived, which is stored in its own attribute.
0321: //
0322: String currentLongLivedAttrName = ScopedServletUtils
0323: .getScopedSessionAttrName(CURRENT_LONGLIVED_ATTR,
0324: unwrappedRequest);
0325: String currentLongLivedModulePath = (String) sh.getAttribute(
0326: rc, currentLongLivedAttrName);
0327:
0328: if (currentLongLivedModulePath != null) {
0329: return getLongLivedPageFlow(currentLongLivedModulePath,
0330: unwrappedRequest);
0331: } else {
0332: String currentJpfAttrName = ScopedServletUtils
0333: .getScopedSessionAttrName(CURRENT_JPF_ATTR,
0334: unwrappedRequest);
0335: return (ActionResolver) sh.getAttribute(rc,
0336: currentJpfAttrName);
0337: }
0338: }
0339:
0340: /**
0341: * Get the current {@link GlobalApp} instance.
0342: *
0343: * @deprecated Use {@link #getSharedFlow} instead.
0344: * @param request the current HttpServletRequest.
0345: * @return the current {@link GlobalApp} from the user session, or <code>null</code> if none
0346: * exists.
0347: */
0348: public static GlobalApp getGlobalApp(HttpServletRequest request) {
0349: SharedFlowController sf = getSharedFlow(
0350: InternalConstants.GLOBALAPP_CLASSNAME, request);
0351: return sf instanceof GlobalApp ? (GlobalApp) sf : null;
0352: }
0353:
0354: /**
0355: * Get the a map of shared flow name to shared flow instance, based on the names defined in the
0356: * {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#sharedFlowRefs sharedFlowRefs} attribute
0357: * of the {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller @Jpf.Controller} annotation on the
0358: * <strong>current page flow</strong>.
0359: *
0360: * @param request the current HttpServletRequest, which is used to determine the current page flow.
0361: * @return a Map of shared flow name (string) to shared flow instance ({@link SharedFlowController}).
0362: */
0363: public static Map/*< String, SharedFlowController >*/getSharedFlows(
0364: HttpServletRequest request) {
0365: Map/*< String, SharedFlowController >*/sharedFlows = ImplicitObjectUtil
0366: .getSharedFlow(request);
0367: return sharedFlows != null ? sharedFlows
0368: : Collections.EMPTY_MAP;
0369: }
0370:
0371: /**
0372: * Get the shared flow with the given class name.
0373: * @deprecated Use {@link #getSharedFlow(String, HttpServletRequest, ServletContext)} instead.
0374: *
0375: * @param sharedFlowClassName the class name of the shared flow to retrieve.
0376: * @param request the current HttpServletRequest.
0377: * @return the {@link SharedFlowController} of the given class name which is stored in the user session.
0378: */
0379: public static SharedFlowController getSharedFlow(
0380: String sharedFlowClassName, HttpServletRequest request) {
0381: ServletContext servletContext = InternalUtils
0382: .getServletContext(request);
0383: return getSharedFlow(sharedFlowClassName, request,
0384: servletContext);
0385: }
0386:
0387: /**
0388: * Get the shared flow with the given class name.
0389: *
0390: * @param sharedFlowClassName the class name of the shared flow to retrieve.
0391: * @param request the current HttpServletRequest.
0392: * @return the {@link SharedFlowController} of the given class name which is stored in the user session.
0393: */
0394: public static SharedFlowController getSharedFlow(
0395: String sharedFlowClassName, HttpServletRequest request,
0396: ServletContext servletContext) {
0397: StorageHandler sh = Handlers.get(servletContext)
0398: .getStorageHandler();
0399: HttpServletRequest unwrappedRequest = unwrapMultipart(request);
0400: RequestContext rc = new RequestContext(unwrappedRequest, null);
0401: String attrName = ScopedServletUtils.getScopedSessionAttrName(
0402: InternalConstants.SHARED_FLOW_ATTR_PREFIX
0403: + sharedFlowClassName, request);
0404: SharedFlowController sf = (SharedFlowController) sh
0405: .getAttribute(rc, attrName);
0406: if (sf != null) {
0407: sf.reinitializeIfNecessary(request, null, servletContext);
0408: }
0409: return sf;
0410: }
0411:
0412: /**
0413: * Destroy the current {@link SharedFlowController} of the given class name.
0414: * @deprecated Use {@link #removeSharedFlow(String, HttpServletRequest, ServletContext)} instead.
0415: * @param sharedFlowClassName the class name of the current SharedFlowController to destroy.
0416: * @param request the current HttpServletRequest.
0417: */
0418: public static void removeSharedFlow(String sharedFlowClassName,
0419: HttpServletRequest request) {
0420: ServletContext servletContext = InternalUtils
0421: .getServletContext(request);
0422: removeSharedFlow(sharedFlowClassName, request, servletContext);
0423: }
0424:
0425: /**
0426: * Destroy the current {@link SharedFlowController} of the given class name.
0427: * @param sharedFlowClassName the class name of the current SharedFlowController to destroy.
0428: * @param request the current HttpServletRequest.
0429: */
0430: public static void removeSharedFlow(String sharedFlowClassName,
0431: HttpServletRequest request, ServletContext servletContext) {
0432: StorageHandler sh = Handlers.get(servletContext)
0433: .getStorageHandler();
0434: HttpServletRequest unwrappedRequest = unwrapMultipart(request);
0435: RequestContext rc = new RequestContext(unwrappedRequest, null);
0436: String attrName = ScopedServletUtils.getScopedSessionAttrName(
0437: InternalConstants.SHARED_FLOW_ATTR_PREFIX
0438: + sharedFlowClassName, request);
0439: sh.removeAttribute(rc, attrName);
0440: }
0441:
0442: /**
0443: * Remove a "long-lived" page flow from the session. Once it is created, a long-lived page flow
0444: * is never removed from the session unless this method or {@link PageFlowController#remove} is
0445: * called. Navigating to another page flow hides the current long-lived controller, but does not
0446: * remove it.
0447: * @deprecated Use {@link #removeLongLivedPageFlow(String, HttpServletRequest, ServletContext)} instead.
0448: */
0449: public static void removeLongLivedPageFlow(String modulePath,
0450: HttpServletRequest request) {
0451: ServletContext servletContext = InternalUtils
0452: .getServletContext(request);
0453: removeLongLivedPageFlow(modulePath, request, servletContext);
0454: }
0455:
0456: /**
0457: * Remove a "long-lived" page flow from the session. Once it is created, a long-lived page flow
0458: * is never removed from the session unless this method or {@link PageFlowController#remove} is
0459: * called. Navigating to another page flow hides the current long-lived controller, but does not
0460: * remove it.
0461: */
0462: public static void removeLongLivedPageFlow(String modulePath,
0463: HttpServletRequest request, ServletContext servletContext) {
0464: StorageHandler sh = Handlers.get(servletContext)
0465: .getStorageHandler();
0466: HttpServletRequest unwrappedRequest = unwrapMultipart(request);
0467: RequestContext rc = new RequestContext(unwrappedRequest, null);
0468:
0469: String attrName = InternalUtils
0470: .getLongLivedFlowAttr(modulePath);
0471: attrName = ScopedServletUtils.getScopedSessionAttrName(
0472: attrName, unwrappedRequest);
0473: sh.removeAttribute(rc, attrName);
0474:
0475: //
0476: // Now, if the current page flow is long-lived, remove the reference.
0477: //
0478: String currentLongLivedAttrName = ScopedServletUtils
0479: .getScopedSessionAttrName(CURRENT_LONGLIVED_ATTR,
0480: unwrappedRequest);
0481: String currentLongLivedModulePath = (String) sh.getAttribute(
0482: rc, currentLongLivedAttrName);
0483:
0484: if (modulePath.equals(currentLongLivedModulePath)) {
0485: sh.removeAttribute(rc, currentLongLivedAttrName);
0486: }
0487: }
0488:
0489: /**
0490: * Get the long-lived page flow instance associated with the given module (directory) path.
0491: * @deprecated Use {@link #getLongLivedPageFlow(String, HttpServletRequest, ServletContext)} instead.
0492: *
0493: * @param modulePath the webapp-relative path to the directory containing the long-lived page flow.
0494: * @param request the current HttpServletRequest.
0495: * @return the long-lived page flow instance associated with the given module, or <code>null</code> if none is found.
0496: */
0497: public static PageFlowController getLongLivedPageFlow(
0498: String modulePath, HttpServletRequest request) {
0499: ServletContext servletContext = InternalUtils
0500: .getServletContext(request);
0501: return getLongLivedPageFlow(modulePath, request, servletContext);
0502: }
0503:
0504: /**
0505: * Get the long-lived page flow instance associated with the given module (directory) path.
0506: *
0507: * @param modulePath the webapp-relative path to the directory containing the long-lived page flow.
0508: * @param request the current HttpServletRequest.
0509: * @param servletContext the current ServletContext.
0510: * @return the long-lived page flow instance associated with the given module, or <code>null</code> if none is found.
0511: */
0512: public static PageFlowController getLongLivedPageFlow(
0513: String modulePath, HttpServletRequest request,
0514: ServletContext servletContext) {
0515: StorageHandler sh = Handlers.get(servletContext)
0516: .getStorageHandler();
0517: HttpServletRequest unwrappedRequest = unwrapMultipart(request);
0518: RequestContext rc = new RequestContext(unwrappedRequest, null);
0519:
0520: String attrName = InternalUtils
0521: .getLongLivedFlowAttr(modulePath);
0522: attrName = ScopedServletUtils.getScopedSessionAttrName(
0523: attrName, unwrappedRequest);
0524: PageFlowController retVal = (PageFlowController) sh
0525: .getAttribute(rc, attrName);
0526: return retVal;
0527: }
0528:
0529: /**
0530: * Make any form beans in the given {@link Forward} object available as attributets in the
0531: * request/session (as appropriate).
0532: *
0533: * @param mapping the ActionMapping for the current Struts action being processed.
0534: * @param fwd the {@link Forward} object that contains the ActionForm instances to be
0535: * made available in the request/session (as appropriate).
0536: * @param request the current HttpServletRequest.
0537: * @param overwrite if <code>false</code> a form from <code>fwd</code> will only be set
0538: * in the request if there is no existing form with the same name.
0539: */
0540: public static void setOutputForms(ActionMapping mapping,
0541: Forward fwd, HttpServletRequest request, boolean overwrite) {
0542: if (fwd == null)
0543: return;
0544:
0545: //
0546: // *If* there is a target action mapping, set output forms for it.
0547: //
0548: if (mapping != null)
0549: setOutputForms(mapping, fwd.getOutputForms(), request,
0550: overwrite);
0551:
0552: InternalUtils.setForwardedFormBean(request, fwd
0553: .getFirstOutputForm(request));
0554: }
0555:
0556: /**
0557: * Make any form beans in the given {@link Forward} object available as attributets in the
0558: * request/session (as appropriate).
0559: *
0560: * @param mapping the ActionMapping for the current Struts action being processed.
0561: * @param fwd the {@link Forward} object that contains the ActionForm instances to be
0562: * made available in the request/session (as appropriate).
0563: * @param request the current HttpServletRequest.
0564: */
0565: public static void setOutputForms(ActionMapping mapping,
0566: Forward fwd, HttpServletRequest request) {
0567: if (fwd == null) {
0568: return;
0569: }
0570:
0571: if (mapping != null) {
0572: setOutputForms(mapping, fwd.getOutputForms(), request);
0573: }
0574:
0575: InternalUtils.setForwardedFormBean(request, fwd
0576: .getFirstOutputForm(request));
0577: }
0578:
0579: /**
0580: * Make a set of form beans available as attributets in the request/session (as appropriate).
0581: *
0582: * @param mapping the ActionMapping for the current Struts action being processed.
0583: * @param outputForms an array of ActionForm instances to be made available in the
0584: * request/session (as appropriate).
0585: * @param request the current HttpServletRequest.
0586: */
0587: public static void setOutputForms(ActionMapping mapping,
0588: ActionForm[] outputForms, HttpServletRequest request) {
0589: setOutputForms(mapping, outputForms, request, true);
0590: }
0591:
0592: /**
0593: * Make a set of form beans available as attributets in the request/session (as appropriate).
0594: *
0595: * @param mapping the ActionMapping for the current Struts action being processed.
0596: * @param outputForms an array of ActionForm instances to be made available in the
0597: * request/session (as appropriate).
0598: * @param overwrite if <code>false</code> a form from <code>fwd</code> will only be set
0599: * in the request if there is no existing form with the same name.
0600: * @param request the current HttpServletRequest.
0601: */
0602: public static void setOutputForms(ActionMapping mapping,
0603: ActionForm[] outputForms, HttpServletRequest request,
0604: boolean overwrite) {
0605: try {
0606: //
0607: // Now set any output forms in the request or session, as appropriate.
0608: //
0609: assert mapping.getScope() == null
0610: || mapping.getScope().equals("request")
0611: || mapping.getScope().equals("session") : mapping
0612: .getScope();
0613:
0614: for (int i = 0; i < outputForms.length; ++i) {
0615: setOutputForm(mapping, outputForms[i], request,
0616: overwrite);
0617: }
0618: } catch (Exception e) {
0619: _log.error("Error while setting Struts form-beans", e);
0620: }
0621: }
0622:
0623: private static List/*< String >*/getFormNamesFromModuleConfig(
0624: String formBeanClassName, ModuleConfig moduleConfig) {
0625: String modulePrefix = moduleConfig.getPrefix();
0626: Map/*< String, List< String > >*/formNameMap = (Map) _formNameMaps
0627: .get(modulePrefix); // map of form-type-name to form-name
0628:
0629: if (formNameMap == null) {
0630: formNameMap = new HashMap/*< String, List< String > >*/();
0631: FormBeanConfig[] formBeans = moduleConfig
0632: .findFormBeanConfigs();
0633:
0634: for (int j = 0; j < formBeans.length; ++j) {
0635: assert formBeans[j] != null;
0636: String formBeanType = InternalUtils
0637: .getFormBeanType(formBeans[j]);
0638: List/*< String >*/formBeanNames = (List) formNameMap
0639: .get(formBeanType);
0640:
0641: if (formBeanNames == null) {
0642: formBeanNames = new ArrayList/*< String >*/();
0643: formNameMap.put(formBeanType, formBeanNames);
0644: }
0645:
0646: formBeanNames.add(formBeans[j].getName());
0647: }
0648:
0649: _formNameMaps.put(modulePrefix, formNameMap);
0650: }
0651:
0652: return (List) formNameMap.get(formBeanClassName);
0653: }
0654:
0655: /**
0656: * Make a form bean available as an attributet in the request/session (as appropriate).
0657: *
0658: * @param mapping the ActionMapping for the current Struts action being processed.
0659: * @param form an ActionForm instance to be made available in the request/session
0660: * (as appropriate).
0661: * @param overwrite if <code>false</code> a form from <code>fwd</code> will only be set
0662: * in the request if there is no existing form with the same name.
0663: * @param request the current HttpServletRequest.
0664: */
0665: public static void setOutputForm(ActionMapping mapping,
0666: ActionForm form, HttpServletRequest request,
0667: boolean overwrite) {
0668: if (form != null) {
0669: ModuleConfig moduleConfig = mapping.getModuleConfig();
0670: Class formClass = InternalUtils.unwrapFormBean(form)
0671: .getClass();
0672:
0673: //
0674: // Get the names of *all* form beans of the desired type, and blast out this instance under all those names.
0675: //
0676: List formNames = getFormNamesFromModuleConfig(formClass
0677: .getName(), moduleConfig);
0678: List additionalFormNames = null;
0679:
0680: //
0681: // formNames is a statically-scoped list. Below, we create a dynamic list of form names that correspond
0682: // to *implemented interfaces* of the given form bean class.
0683: //
0684: Class[] interfaces = formClass.getInterfaces();
0685: for (int i = 0; i < interfaces.length; i++) {
0686: Class formInterface = interfaces[i];
0687: List toAdd = getFormNamesFromModuleConfig(formInterface
0688: .getName(), moduleConfig);
0689: if (toAdd != null) {
0690: if (additionalFormNames == null)
0691: additionalFormNames = new ArrayList();
0692: additionalFormNames.addAll(toAdd);
0693: }
0694: }
0695:
0696: // Do the same for all superclasses of the form bean class.
0697: for (Class i = formClass.getSuperclass(); i != null; i = i
0698: .getSuperclass()) {
0699: List toAdd = getFormNamesFromModuleConfig(i.getName(),
0700: moduleConfig);
0701: if (toAdd != null) {
0702: if (additionalFormNames == null)
0703: additionalFormNames = new ArrayList();
0704: additionalFormNames.addAll(toAdd);
0705: }
0706: }
0707:
0708: if (formNames == null && additionalFormNames == null) {
0709: String formName = generateFormBeanName(formClass,
0710: request);
0711: InternalUtils.setFormInScope(formName, form, mapping,
0712: request, overwrite);
0713: } else {
0714: if (formNames != null) {
0715: for (Iterator i = formNames.iterator(); i.hasNext();) {
0716: String formName = (String) i.next();
0717: InternalUtils.setFormInScope(formName, form,
0718: mapping, request, overwrite);
0719: }
0720: }
0721:
0722: if (additionalFormNames != null) {
0723: for (Iterator i = additionalFormNames.iterator(); i
0724: .hasNext();) {
0725: String formName = (String) i.next();
0726: InternalUtils.setFormInScope(formName, form,
0727: mapping, request, overwrite);
0728: }
0729: }
0730: }
0731: }
0732: }
0733:
0734: /**
0735: * Get the name for the type of a ActionForm instance. Use a name looked up from
0736: * the current Struts module, or, if none is found, create one.
0737: *
0738: * @param formInstance the ActionForm instance whose type will determine the name.
0739: * @param request the current HttpServletRequest, which contains a reference to the current Struts module.
0740: * @return the name found in the Struts module, or, if none is found, a name that is either:
0741: * <ul>
0742: * <li>a camel-cased version of the base class name (minus any package or outer-class
0743: * qualifiers, or, if that name is already taken,</li>
0744: * <li>the full class name, with '.' and '$' replaced by '_'.</li>
0745: * </ul>
0746: */
0747: public static String getFormBeanName(ActionForm formInstance,
0748: HttpServletRequest request) {
0749: return getFormBeanName(formInstance.getClass(), request);
0750: }
0751:
0752: /**
0753: * Get the name for an ActionForm type. Use a name looked up from the current Struts module, or,
0754: * if none is found, create one.
0755: *
0756: * @param formBeanClass the ActionForm-derived class whose type will determine the name.
0757: * @param request the current HttpServletRequest, which contains a reference to the current Struts module.
0758: * @return the name found in the Struts module, or, if none is found, a name that is either:
0759: * <ul>
0760: * <li>a camel-cased version of the base class name (minus any package or outer-class
0761: * qualifiers, or, if that name is already taken,</li>
0762: * <li>the full class name, with '.' and '$' replaced by '_'.</li>
0763: * </ul>
0764: */
0765: public static String getFormBeanName(Class formBeanClass,
0766: HttpServletRequest request) {
0767: ModuleConfig moduleConfig = RequestUtils
0768: .getRequestModuleConfig(request);
0769: List/*< String >*/names = getFormNamesFromModuleConfig(
0770: formBeanClass.getName(), moduleConfig);
0771:
0772: if (names != null) {
0773: assert names.size() > 0; // getFormNamesFromModuleConfig returns null or a nonempty list
0774: return (String) names.get(0);
0775: }
0776:
0777: return generateFormBeanName(formBeanClass, request);
0778: }
0779:
0780: /**
0781: * Create the name for a form bean type.
0782: *
0783: * @param formBeanClass the class whose type will determine the name.
0784: * @param request the current HttpServletRequest, which contains a reference to the current Struts module.
0785: * @return the name found in the Struts module, or, if none is found, a name that is either:
0786: * <ul>
0787: * <li>a camel-cased version of the base class name (minus any package or outer-class
0788: * qualifiers, or, if that name is already taken,</li>
0789: * <li>the full class name, with '.' and '$' replaced by '_'.</li>
0790: * </ul>
0791: */
0792: private static String generateFormBeanName(Class formBeanClass,
0793: HttpServletRequest request) {
0794: ModuleConfig moduleConfig = RequestUtils
0795: .getRequestModuleConfig(request);
0796: String formBeanClassName = formBeanClass.getName();
0797:
0798: //
0799: // A form-bean wasn't found for this type, so we'll create a name. First try and create
0800: // name that is a camelcased version of the classname without all of its package/outer-class
0801: // qualifiers. If one with that name already exists, munge the fully-qualified classname.
0802: //
0803: String formType = formBeanClassName;
0804: int lastQualifier = formType.lastIndexOf('$');
0805:
0806: if (lastQualifier == -1) {
0807: lastQualifier = formType.lastIndexOf('.');
0808: }
0809:
0810: String formName = formType.substring(lastQualifier + 1);
0811: formName = Character.toLowerCase(formName.charAt(0))
0812: + formName.substring(1);
0813:
0814: if (moduleConfig.findFormBeanConfig(formName) != null) {
0815: formName = formType.replace('.', '_').replace('$', '_');
0816: assert moduleConfig.findFormBeanConfig(formName) == null : formName;
0817: }
0818:
0819: return formName;
0820: }
0821:
0822: /**
0823: * Get the class name of a {@link PageFlowController}, given the URI to it.
0824: *
0825: * @param uri the URI to the {@link PageFlowController}, which should be relative to the
0826: * web application root (i.e., it should not include the context path).
0827: */
0828: public static String getPageFlowClassName(String uri) {
0829: assert uri != null;
0830: assert uri.length() > 0;
0831:
0832: if (uri.charAt(0) == '/')
0833: uri = uri.substring(1);
0834:
0835: assert FileUtils.osSensitiveEndsWith(uri, PAGEFLOW_EXTENSION) : uri;
0836: if (FileUtils.osSensitiveEndsWith(uri, PAGEFLOW_EXTENSION)) {
0837: uri = uri.substring(0, uri.length()
0838: - PAGEFLOW_EXTENSION_LEN);
0839: }
0840:
0841: return uri.replace('/', '.');
0842: }
0843:
0844: /**
0845: * Get the class name of a {@link PageFlowController}, given the URI to it.
0846: *
0847: * @deprecated Use {@link #getPageFlowClassName(String)} instead.
0848: *
0849: * @param uri the URI to the {@link PageFlowController}, which should be relative to the
0850: * web application root (i.e., it should not include the context path).
0851: */
0852: public static String getJpfClassName(String uri) {
0853: return getPageFlowClassName(uri);
0854: }
0855:
0856: /**
0857: * Get the URI for a {@link PageFlowController}, given its class name.
0858: *
0859: * @param className the name of the {@link PageFlowController} class.
0860: * @return a String that is the URI for the {@link PageFlowController}, relative to the web
0861: * application root (i.e., not including the context path).
0862: */
0863: public static String getPageFlowURI(String className) {
0864: return '/' + className.replace('.', '/') + PAGEFLOW_EXTENSION;
0865: }
0866:
0867: /**
0868: * @deprecated Use {@link PageFlowActionServlet#getModuleConfPath} instead.
0869: *
0870: * Get the path to the Struts module configration file (e.g.,
0871: * "/WEB-INF/classes/_pageflow/struts-config-someModule") for a given module
0872: * path (e.g., "someModule"), according to the PageFlow convention.
0873: *
0874: * @param modulePath the Struts module path.
0875: * @return a String that is the path to the Struts configuration file, relative to the
0876: * web application root.
0877: */
0878: public static String getModuleConfPath(String modulePath) {
0879: return new PageFlowActionServlet.DefaultModuleConfigLocator()
0880: .getModuleConfigPath(modulePath);
0881: }
0882:
0883: /**
0884: * Get the most recent action URI that was processed by {@link FlowController#execute}.
0885: *
0886: * @param request the current ServletRequest.
0887: * @return a String that is the most recent action URI. This is only valid during a request
0888: * that has been forwarded from the action URI.
0889: */
0890: public static String getActionURI(ServletRequest request) {
0891: return (String) request.getAttribute(ACTION_URI_ATTR);
0892: }
0893:
0894: /**
0895: * Sets the most recent action URI that was processed by {@link FlowController#execute}.
0896: */
0897: static void setActionURI(HttpServletRequest request) {
0898: request.setAttribute(ACTION_URI_ATTR, InternalUtils
0899: .getDecodedURI(request));
0900: }
0901:
0902: /**
0903: * Tell whether a web application resource requires a secure transport protocol. This is
0904: * determined from web.xml; for example, the following block specifies that all resources under
0905: * /login require a secure transport protocol.
0906: * <pre>
0907: * <security-constraint>
0908: * <web-resource-collection>
0909: * <web-resource-name>Secure PageFlow - begin</web-resource-name>
0910: * <url-pattern>/login/*</url-pattern>
0911: * </web-resource-collection>
0912: * <user-data-constraint>
0913: * <transport-guarantee>CONFIDENTIAL</transport-guarantee>
0914: * </user-data-constraint>
0915: * </security-constraint>
0916: * </pre>
0917: *
0918: * @param uri a webapp-relative URI for a resource. There must not be query parameters or a scheme
0919: * on the URI.
0920: * @param request the current request.
0921: * @return <code>Boolean.TRUE</code> if a transport-guarantee of <code>CONFIDENTIAL</code> or
0922: * <code>INTEGRAL</code> is associated with the given resource; <code>Boolean.FALSE</code>
0923: * a transport-guarantee of <code>NONE</code> is associated with the given resource; or
0924: * <code>null</code> if there is no transport-guarantee associated with the given resource.
0925: */
0926: public static SecurityProtocol getSecurityProtocol(String uri,
0927: ServletContext servletContext, HttpServletRequest request) {
0928: return AdapterManager
0929: .getServletContainerAdapter(servletContext)
0930: .getSecurityProtocol(uri, request);
0931: }
0932:
0933: /**
0934: * @deprecated Use {@link #getSecurityProtocol(String, ServletContext, HttpServletRequest)} instead.
0935: */
0936: public static Boolean isSecureResource(String uri,
0937: ServletContext context) {
0938: // TODO: once DefaultServletContainerAdapter has this functionality, delegate to it.
0939: return null;
0940: }
0941:
0942: /**
0943: * Set a named action output, which corresponds to an input declared by the <code>pageInput</code> JSP tag.
0944: * The actual value can be read from within a JSP using the <code>"pageInput"</code> databinding context.
0945: *
0946: * @deprecated Use {@link #addActionOutput} instead.
0947: * @param name the name of the action output.
0948: * @param value the value of the action output.
0949: * @param request the current ServletRequest.
0950: */
0951: public static void addPageInput(String name, Object value,
0952: ServletRequest request) {
0953: addActionOutput(name, value, request);
0954: }
0955:
0956: /**
0957: * Set a named action output, which corresponds to an input declared by the <code>pageInput</code> JSP tag.
0958: * The actual value can be read from within a JSP using the <code>"pageInput"</code> databinding context.
0959: *
0960: * @param name the name of the action output.
0961: * @param value the value of the action output.
0962: * @param request the current ServletRequest.
0963: */
0964: public static void addActionOutput(String name, Object value,
0965: ServletRequest request) {
0966: Map map = InternalUtils.getActionOutputMap(request, true);
0967:
0968: if (map.containsKey(name)) {
0969: if (_log.isWarnEnabled()) {
0970: _log.warn("Overwriting action output\"" + name + "\".");
0971: }
0972: }
0973:
0974: map.put(name, value);
0975: }
0976:
0977: /**
0978: * Get a named action output that was registered in the current request.
0979: *
0980: * @deprecated Use {@link #getActionOutput} instead.
0981: * @param name the name of the action output.
0982: * @param request the current ServletRequest
0983: * @see #addActionOutput
0984: */
0985: public static Object getPageInput(String name,
0986: ServletRequest request) {
0987: return getActionOutput(name, request);
0988: }
0989:
0990: /**
0991: * Get a named action output that was registered in the current request.
0992: *
0993: * @param name the name of the action output.
0994: * @param request the current ServletRequest
0995: * @see #addActionOutput
0996: */
0997: public static Object getActionOutput(String name,
0998: ServletRequest request) {
0999: Map map = InternalUtils.getActionOutputMap(request, false);
1000: return map != null ? map.get(name) : null;
1001: }
1002:
1003: /**
1004: * Add a validation error that will be shown with the Errors and Error tags.
1005: * @deprecated Use {@link #addActionError(ServletRequest, String, String, Object[])} instead.
1006: *
1007: * @param propertyName the name of the property with which to associate this error.
1008: * @param messageKey the message-resources key for the error message.
1009: * @param messageArgs an array of arguments for the error message.
1010: * @param request the current ServletRequest.
1011: */
1012: public static void addValidationError(String propertyName,
1013: String messageKey, Object[] messageArgs,
1014: ServletRequest request) {
1015: InternalUtils.addActionError(propertyName, new ActionMessage(
1016: messageKey, messageArgs), request);
1017: }
1018:
1019: /**
1020: * Add a validation error that will be shown with the Errors and Error tags.
1021: * @deprecated Use {@link #addActionError(ServletRequest, String, String, Object[])} instead.
1022: *
1023: * @param propertyName the name of the property with which to associate this error.
1024: * @param messageKey the message-resources key for the error message.
1025: * @param messageArg an argument for the error message.
1026: * @param request the current ServletRequest.
1027: */
1028: public static void addValidationError(String propertyName,
1029: String messageKey, Object messageArg, ServletRequest request) {
1030: addActionError(request, propertyName, messageKey,
1031: new Object[] { messageArg });
1032: }
1033:
1034: /**
1035: * Add a validation error that will be shown with the Errors and Error tags.
1036: * @deprecated Use {@link #addActionError(ServletRequest, String, String, Object[])} instead.
1037: *
1038: * @param propertyName the name of the property with which to associate this error.
1039: * @param messageKey the message-resources key for the error message.
1040: * @param request the current ServletRequest.
1041: */
1042: public static void addValidationError(String propertyName,
1043: String messageKey, ServletRequest request) {
1044: addActionError(request, propertyName, messageKey);
1045: }
1046:
1047: /**
1048: * Add a property-related message that will be shown with the Errors and Error tags.
1049: *
1050: * @param request the current ServletRequest.
1051: * @param propertyName the name of the property with which to associate this error.
1052: * @param messageKey the message-resources key for the message.
1053: * @param messageArgs zero or more arguments to the message.
1054: */
1055: public static void addActionError(ServletRequest request,
1056: String propertyName, String messageKey, Object[] messageArgs) {
1057: InternalUtils.addActionError(propertyName, new ActionMessage(
1058: messageKey, messageArgs), request);
1059: }
1060:
1061: /**
1062: * Add a property-related message that will be shown with the Errors and Error tags.
1063: *
1064: * @param request the current ServletRequest.
1065: * @param propertyName the name of the property with which to associate this error.
1066: * @param messageKey the message-resources key for the message.
1067: */
1068: public static void addActionError(ServletRequest request,
1069: String propertyName, String messageKey) {
1070: InternalUtils.addActionError(propertyName, new ActionMessage(
1071: messageKey, null), request);
1072: }
1073:
1074: /**
1075: * Add a property-related message that will be shown with the Errors and Error tags.
1076: *
1077: * @param request the current ServletRequest.
1078: * @param propertyName the name of the property with which to associate this error.
1079: * @param messageKey the message-resources key for the message.
1080: * @param messageArg an argument to the message
1081: */
1082: public static void addActionError(ServletRequest request,
1083: String propertyName, String messageKey, Object messageArg) {
1084: Object[] messageArgs = new Object[] { messageArg };
1085: InternalUtils.addActionError(propertyName, new ActionMessage(
1086: messageKey, messageArgs), request);
1087: }
1088:
1089: /**
1090: * Add a property-related message that will be shown with the Errors and Error tags.
1091: *
1092: * @param request the current ServletRequest.
1093: * @param propertyName the name of the property with which to associate this error.
1094: * @param messageKey the message-resources key for the message.
1095: * @param messageArg1 the first argument to the message
1096: * @param messageArg2 the second argument to the message
1097: */
1098: public static void addActionError(ServletRequest request,
1099: String propertyName, String messageKey, Object messageArg1,
1100: Object messageArg2) {
1101: Object[] messageArgs = new Object[] { messageArg1, messageArg2 };
1102: InternalUtils.addActionError(propertyName, new ActionMessage(
1103: messageKey, messageArgs), request);
1104: }
1105:
1106: /**
1107: * Add a property-related message that will be shown with the Errors and Error tags.
1108: *
1109: * @param request the current ServletRequest.
1110: * @param propertyName the name of the property with which to associate this error.
1111: * @param messageKey the message-resources key for the message.
1112: * @param messageArg1 the first argument to the message
1113: * @param messageArg2 the second argument to the message
1114: * @param messageArg3 the third argument to the message
1115: */
1116: public static void addActionError(ServletRequest request,
1117: String propertyName, String messageKey, Object messageArg1,
1118: Object messageArg2, Object messageArg3) {
1119: Object[] messageArgs = new Object[] { messageArg1, messageArg2,
1120: messageArg3 };
1121: InternalUtils.addActionError(propertyName, new ActionMessage(
1122: messageKey, messageArgs), request);
1123: }
1124:
1125: /**
1126: * Add a property-related message as an expression that will be evaluated and shown with the Errors and Error tags.
1127: *
1128: * @param request the current ServletRequest.
1129: * @param propertyName the name of the property with which to associate this error.
1130: * @param expression the JSP 2.0-style expression (e.g., <code>${pageFlow.myProperty}</code>) or literal string
1131: * that will be used as the message.
1132: * @param messageArgs zero or more arguments to the message.
1133: */
1134: public static void addActionErrorExpression(
1135: HttpServletRequest request, String propertyName,
1136: String expression, Object[] messageArgs) {
1137: ExpressionMessage msg = new ExpressionMessage(expression,
1138: messageArgs);
1139: InternalUtils.addActionError(propertyName, msg, request);
1140: }
1141:
1142: /**
1143: * Resolve the given action to a URI by running an entire request-processing cycle on the given ScopedRequest
1144: * and ScopedResponse.
1145: * @exclude
1146: *
1147: * @param context the current ServletContext
1148: * @param request the ServletRequest, which must be a {@link ScopedRequest}.
1149: * @param response the ServletResponse, which must be a {@link ScopedResponse}.
1150: * @param actionOverride if not <code>null</code>, this qualified action-path is used to construct an action
1151: * URI which is set as the request URI. The action-path <strong>must</strong> begin with '/',
1152: * which makes it qualified from the webapp root.
1153: * @param autoResolveExtensions a list of URI extensions (e.g., ".do", ".jpf") that will be auto-resolved, i.e.,
1154: * on which this method will be recursively called. If <code>null</code>, the
1155: * default extensions ".do" and ".jpf" will be used.
1156: */
1157: public static ActionResult strutsLookup(ServletContext context,
1158: ServletRequest request, HttpServletResponse response,
1159: String actionOverride, String[] autoResolveExtensions)
1160: throws Exception {
1161: ScopedRequest scopedRequest = ScopedServletUtils
1162: .unwrapRequest(request);
1163: ScopedResponse scopedResponse = ScopedServletUtils
1164: .unwrapResponse(response);
1165: assert scopedRequest != null : request.getClass().getName();
1166: assert scopedResponse != null : response.getClass().getName();
1167: assert request instanceof HttpServletRequest : request
1168: .getClass().getName();
1169:
1170: if (scopedRequest == null) {
1171: throw new IllegalArgumentException(
1172: "request must be of type "
1173: + ScopedRequest.class.getName());
1174: }
1175: if (scopedResponse == null) {
1176: throw new IllegalArgumentException(
1177: "response must be of type "
1178: + ScopedResponse.class.getName());
1179: }
1180:
1181: ActionServlet as = InternalUtils.getActionServlet(context);
1182:
1183: if (actionOverride != null) {
1184: // The action must be fully-qualified with its module path.
1185: assert actionOverride.charAt(0) == '/' : actionOverride;
1186: InternalStringBuilder uri = new InternalStringBuilder(
1187: scopedRequest.getContextPath());
1188: uri.append(actionOverride);
1189: uri.append(PageFlowConstants.ACTION_EXTENSION);
1190: scopedRequest.setRequestURI(uri.toString());
1191: }
1192:
1193: //
1194: // In case the request was already forwarded once, clear out the recorded forwarded-URI. This
1195: // will allow us to tell whether processing the request actually forwarded somewhere.
1196: //
1197: scopedRequest.setForwardedURI(null);
1198:
1199: //
1200: // Now process the request. We create a PageFlowRequestWrapper for pageflow-specific request-scoped info.
1201: //
1202: PageFlowRequestWrapper wrappedRequest = PageFlowRequestWrapper
1203: .wrapRequest((HttpServletRequest) request);
1204: wrappedRequest.setScopedLookup(true);
1205:
1206: if (as != null) {
1207: as.doGet(wrappedRequest, scopedResponse); // this just calls process() -- same as doPost()
1208: } else {
1209: // The normal servlet initialization has not completed yet
1210: // so rather than call doGet() directly, aquire the request
1211: // dispatcher from the unwrapped outer request and call
1212: // forward to trigger the servlet initialization.
1213: HttpServletRequest req = scopedRequest.getOuterRequest();
1214: RequestDispatcher rd = req
1215: .getRequestDispatcher(scopedRequest.getRequestURI());
1216: rd.forward(wrappedRequest, scopedResponse);
1217: }
1218:
1219: String returnURI;
1220:
1221: if (!scopedResponse.didRedirect()) {
1222: returnURI = scopedRequest.getForwardedURI();
1223:
1224: if (autoResolveExtensions == null) {
1225: autoResolveExtensions = DEFAULT_AUTORESOLVE_EXTENSIONS;
1226: }
1227:
1228: if (returnURI != null) {
1229: for (int i = 0; i < autoResolveExtensions.length; ++i) {
1230: if (FileUtils.uriEndsWith(returnURI,
1231: autoResolveExtensions[i])) {
1232: scopedRequest.doForward();
1233: return strutsLookup(context, wrappedRequest,
1234: scopedResponse, null,
1235: autoResolveExtensions);
1236: }
1237: }
1238: }
1239: } else {
1240: returnURI = scopedResponse.getRedirectURI();
1241: }
1242:
1243: RequestContext requestContext = new RequestContext(
1244: scopedRequest, scopedResponse);
1245: Handlers.get(context).getStorageHandler().applyChanges(
1246: requestContext);
1247:
1248: if (returnURI != null) {
1249: return new ActionResultImpl(returnURI, scopedResponse
1250: .didRedirect(), scopedResponse.getStatusCode(),
1251: scopedResponse.getStatusMessage(), scopedResponse
1252: .isError());
1253: } else {
1254: return null;
1255: }
1256: }
1257:
1258: /**
1259: * If the given request is a MultipartRequestWrapper (Struts class that doesn't extend
1260: * HttpServletRequestWrapper), return the wrapped request; otherwise, return the given request.
1261: * @exclude
1262: */
1263: public static HttpServletRequest unwrapMultipart(
1264: HttpServletRequest request) {
1265: if (request instanceof MultipartRequestWrapper) {
1266: request = ((MultipartRequestWrapper) request).getRequest();
1267: }
1268:
1269: return request;
1270: }
1271:
1272: /**
1273: * Get or create the current {@link GlobalApp} instance.
1274: * @deprecated Use {@link #getGlobalApp} instead.
1275: *
1276: * @param request the current HttpServletRequest.
1277: * @param response the current HttpServletResponse
1278: * @return the current {@link GlobalApp} from the user session, or a newly-instantiated one
1279: * (based on the user's Global.app file) if none was in the session. Failing that,
1280: * return <code>null</code>.
1281: */
1282: public static GlobalApp ensureGlobalApp(HttpServletRequest request,
1283: HttpServletResponse response) {
1284: ServletContext servletContext = InternalUtils
1285: .getServletContext(request);
1286: return ensureGlobalApp(request, response, servletContext);
1287: }
1288:
1289: /**
1290: * Get or create the current {@link GlobalApp} instance.
1291: * @deprecated Use {@link #getSharedFlow} instead.
1292: *
1293: * @param request the current HttpServletRequest.
1294: * @param response the current HttpServletResponse
1295: * @return the current {@link GlobalApp} from the user session, or a newly-instantiated one
1296: * (based on the user's Global.app file) if none was in the session. Failing that,
1297: * return <code>null</code>.
1298: */
1299: public static GlobalApp ensureGlobalApp(HttpServletRequest request,
1300: HttpServletResponse response, ServletContext servletContext) {
1301: GlobalApp ga = getGlobalApp(request);
1302:
1303: if (ga != null) {
1304: ga.reinitialize(request, response, servletContext);
1305: } else {
1306: ga = FlowControllerFactory.getGlobalApp(request, response,
1307: servletContext);
1308: }
1309:
1310: return ga;
1311: }
1312:
1313: /**
1314: * @deprecated This is an internal utility. {@link InternalUtils#getBindingUpdateErrors} can be used, but it is
1315: * not guaranteed to be supported in the future.
1316: */
1317: public static Map getBindingUpdateErrors(ServletRequest request) {
1318: return InternalUtils.getBindingUpdateErrors(request);
1319: }
1320:
1321: /**
1322: * @deprecated This is an internal utility. {@link InternalUtils#ensureModuleConfig} can be used, but it is
1323: * not guaranteed to be supported in the future.
1324: */
1325: public static ModuleConfig ensureModuleConfig(String modulePath,
1326: ServletRequest request, ServletContext context) {
1327: return InternalUtils.ensureModuleConfig(modulePath, context);
1328: }
1329:
1330: /**
1331: * @deprecated This will be removed with no replacement in a future release.
1332: */
1333: public static ModuleConfig getGlobalAppConfig(
1334: ServletContext servletContext) {
1335: return InternalUtils.getModuleConfig(
1336: GLOBALAPP_MODULE_CONTEXT_PATH, servletContext);
1337: }
1338:
1339: /**
1340: * @deprecated This is an internal utility. {@link InternalUtils#getModuleConfig} can be used, but it is
1341: * not guaranteed to be supported in the future.
1342: */
1343: public static ModuleConfig getModuleConfig(String modulePath,
1344: ServletContext context) {
1345: return InternalUtils.getModuleConfig(modulePath, context);
1346: }
1347:
1348: /**
1349: * Get the file extension from a file name.
1350: * @deprecated Use {@link FileUtils#getFileExtension} instead.
1351: *
1352: * @param filename the file name.
1353: * @return the file extension (everything after the last '.'), or the empty string if there is no file extension.
1354: */
1355: public static String getFileExtension(String filename) {
1356: return FileUtils.getFileExtension(filename);
1357: }
1358:
1359: /**
1360: * @deprecated This is an internal utility. {@link InternalUtils#getFlowControllerClassName} can be used, but it is
1361: * not guaranteed to be supported in the future.
1362: */
1363: public static String getPageFlowClassName(String modulePath,
1364: ServletRequest request, ServletContext context) {
1365: return InternalUtils.getFlowControllerClassName(modulePath,
1366: request, context);
1367: }
1368:
1369: /**
1370: * @deprecated This method no longer has any effect, and will be removed without replacement in a future release.
1371: */
1372: public static boolean ensureAppDeployment(
1373: HttpServletRequest request, HttpServletResponse response,
1374: ServletContext servletContext) {
1375: return false;
1376: }
1377:
1378: /**
1379: * Tell whether a given URI is absolute, i.e., whether it contains a scheme-part (e.g., "http:").
1380: * @deprecated Use {@link FileUtils#isAbsoluteURI} instead.
1381: *
1382: * @param uri the URI to test.
1383: * @return <code>true</code> if the given URI is absolute.
1384: */
1385: public static boolean isAbsoluteURI(String uri) {
1386: return FileUtils.isAbsoluteURI(uri);
1387: }
1388:
1389: /**
1390: * @deprecated Use {@link #getCurrentPageFlow} instead.
1391: */
1392: public static final PageFlowController ensureCurrentPageFlow(
1393: HttpServletRequest request, HttpServletResponse response,
1394: ServletContext servletContext) {
1395: try {
1396: FlowControllerFactory factory = FlowControllerFactory
1397: .get(servletContext);
1398: return factory.getPageFlowForRequest(new RequestContext(
1399: request, response));
1400: } catch (InstantiationException e) {
1401: _log.error(
1402: "Could not instantiate PageFlowController for request "
1403: + request.getRequestURI(), e);
1404: } catch (IllegalAccessException e) {
1405: _log.error(
1406: "Could not instantiate PageFlowController for request "
1407: + request.getRequestURI(), e);
1408: }
1409:
1410: return null;
1411: }
1412:
1413: /**
1414: * @deprecated Use {@link #getCurrentPageFlow} instead.
1415: */
1416: public static final PageFlowController ensureCurrentPageFlow(
1417: HttpServletRequest request, HttpServletResponse response) {
1418: ServletContext servletContext = InternalUtils
1419: .getServletContext(request);
1420:
1421: if (servletContext == null && _log.isWarnEnabled()) {
1422: _log.warn("could not get ServletContext from request "
1423: + request);
1424: }
1425:
1426: return ensureCurrentPageFlow(request, response, servletContext);
1427: }
1428:
1429: /**
1430: * @deprecated This is an internal utility. {@link InternalUtils#addBindingUpdateError} can be used, but it is
1431: * not guaranteed to be supported in the future.
1432: */
1433: public static void addBindingUpdateError(ServletRequest request,
1434: String expression, String message, Throwable e) {
1435: InternalUtils.addBindingUpdateError(request, expression,
1436: message, e);
1437: }
1438:
1439: /**
1440: * @deprecated This is an internal utility. {@link ServletUtils#dumpRequest} can be used, but it is
1441: * not guaranteed to be supported in the future.
1442: */
1443: public static void dumpRequest(HttpServletRequest request,
1444: PrintStream output) {
1445: ServletUtils.dumpRequest(request, output);
1446: }
1447:
1448: /**
1449: * @deprecated This is an internal utility. {@link ServletUtils#dumpServletContext} can be used, but it is
1450: * not guaranteed to be supported in the future.
1451: */
1452: public static void dumpServletContext(ServletContext context,
1453: PrintStream output) {
1454: ServletUtils.dumpServletContext(context, output);
1455: }
1456:
1457: /**
1458: * @deprecated Use {@link ServletUtils#preventCache} instead.
1459: */
1460: public static void preventCache(HttpServletResponse response) {
1461: ServletUtils.preventCache(response);
1462: }
1463:
1464: /**
1465: * @deprecated This is an internal utility. {@link InternalUtils#setCurrentActionResolver} can be used, but it is
1466: * not guaranteed to be supported in the future. This method will be removed in the next version.
1467: */
1468: public static void setCurrentActionResolver(
1469: ActionResolver resolver, HttpServletRequest request) {
1470: ServletContext servletContext = InternalUtils
1471: .getServletContext(request);
1472: InternalUtils.setCurrentActionResolver(resolver, request,
1473: servletContext);
1474: }
1475:
1476: /**
1477: * Create a raw action URI, which can be modified before being sent through the registered URL rewriting chain
1478: * using {@link URLRewriterService#rewriteURL}. Use {@link #getRewrittenActionURI} to get a fully-rewritten URI.
1479: *
1480: * @param servletContext the current ServletContext.
1481: * @param request the current HttpServletRequest.
1482: * @param response the current HttpServletResponse.
1483: * @param actionName the action name to convert into a MutableURI; may be qualified with a path from the webapp
1484: * root, in which case the parent directory from the current request is <i>not</i> used.
1485: * @return a MutableURI for the given action, suitable for URL rewriting.
1486: * @throws URISyntaxException if there is a problem converting the action URI (derived from processing the given
1487: * action name) into a MutableURI.
1488: */
1489: public static MutableURI getActionURI(
1490: ServletContext servletContext, HttpServletRequest request,
1491: HttpServletResponse response, String actionName)
1492: throws URISyntaxException {
1493: if (actionName.length() < 1)
1494: throw new IllegalArgumentException(
1495: "actionName must be non-empty");
1496:
1497: /*
1498: * The implementation for HttpServletRequest method getContextPath()
1499: * is not consistant across containers. The spec says the "container
1500: * does not decode this string." However, the string returned in
1501: * Tomcat is decoded. (See Tomcat bugzilla bug 39503) Also this method
1502: * returns a decoded string in some containers if the request is a
1503: * forward where the RequestDispatcher was acquired using a relative
1504: * path. It seems that it is only the space character in the context
1505: * path that causes us issues using the java.net.URI class in our
1506: * MutableURI.setURI(). So,... check for a decoded space and encode it.
1507: */
1508: String contextPath = request.getContextPath();
1509: if (contextPath.indexOf(' ') != -1) {
1510: contextPath = contextPath.replace(" ", "%20");
1511: }
1512: InternalStringBuilder actionURI = new InternalStringBuilder(
1513: contextPath);
1514:
1515: if (actionName.charAt(0) != '/') {
1516: actionURI.append(InternalUtils
1517: .getModulePathFromReqAttr(request));
1518: actionURI.append('/');
1519: }
1520:
1521: actionURI.append(actionName);
1522: if (!actionName.endsWith(ACTION_EXTENSION))
1523: actionURI.append(ACTION_EXTENSION);
1524:
1525: FreezableMutableURI uri = new FreezableMutableURI();
1526: uri.setEncoding(response.getCharacterEncoding());
1527: uri.setPath(actionURI.toString());
1528: return uri;
1529: }
1530:
1531: /**
1532: * Create a fully-rewritten URI given an action name and parameters.
1533: *
1534: * @param servletContext the current ServletContext.
1535: * @param request the current HttpServletRequest.
1536: * @param response the current HttpServletResponse.
1537: * @param actionName the action name to convert into a fully-rewritten URI; may be qualified with a path from the
1538: * webapp root, in which case the parent directory from the current request is <i>not</i> used.
1539: * @param params the additional parameters to include in the URI query.
1540: * @param fragment the fragment (anchor or location) for this url.
1541: * @param forXML flag indicating that the query of the uri should be written
1542: * using the "&amp;" entity, rather than the character, '&'.
1543: * @return a fully-rewritten URI for the given action.
1544: * @throws URISyntaxException if there is a problem converting the action URI (derived
1545: * from processing the given action name) into a MutableURI.
1546: */
1547: public static String getRewrittenActionURI(
1548: ServletContext servletContext, HttpServletRequest request,
1549: HttpServletResponse response, String actionName,
1550: Map params, String fragment, boolean forXML)
1551: throws URISyntaxException {
1552: MutableURI uri = getActionURI(servletContext, request,
1553: response, actionName);
1554: if (params != null)
1555: uri.addParameters(params, false);
1556: if (fragment != null)
1557: uri.setFragment(uri.encode(fragment));
1558:
1559: boolean needsToBeSecure = needsToBeSecure(servletContext,
1560: request, uri.getPath(), true);
1561: URLRewriterService.rewriteURL(servletContext, request,
1562: response, uri, URLType.ACTION, needsToBeSecure);
1563: String key = getURLTemplateKey(URLType.ACTION, needsToBeSecure);
1564: URIContext uriContext = URIContextFactory.getInstance(forXML);
1565:
1566: return URLRewriterService.getTemplatedURL(servletContext,
1567: request, uri, key, uriContext);
1568: }
1569:
1570: /**
1571: * Create a fully-rewritten URI given a path and parameters.
1572: *
1573: * <p> Calls the rewriter service using a type of {@link URLType#RESOURCE}. </p>
1574: *
1575: * @param servletContext the current ServletContext.
1576: * @param request the current HttpServletRequest.
1577: * @param response the current HttpServletResponse.
1578: * @param path the path to process into a fully-rewritten URI.
1579: * @param params the additional parameters to include in the URI query.
1580: * @param fragment the fragment (anchor or location) for this URI.
1581: * @param forXML flag indicating that the query of the uri should be written
1582: * using the "&amp;" entity, rather than the character, '&'.
1583: * @return a fully-rewritten URI for the given action.
1584: * @throws URISyntaxException if there's a problem converting the action URI (derived
1585: * from processing the given action name) into a MutableURI.
1586: */
1587: public static String getRewrittenResourceURI(
1588: ServletContext servletContext, HttpServletRequest request,
1589: HttpServletResponse response, String path, Map params,
1590: String fragment, boolean forXML) throws URISyntaxException {
1591: return rewriteResourceOrHrefURL(servletContext, request,
1592: response, path, params, fragment, forXML,
1593: URLType.RESOURCE);
1594: }
1595:
1596: /**
1597: * Create a fully-rewritten URI given a path and parameters.
1598: *
1599: * <p> Calls the rewriter service using a type of {@link URLType#ACTION}. </p>
1600: *
1601: * @param servletContext the current ServletContext.
1602: * @param request the current HttpServletRequest.
1603: * @param response the current HttpServletResponse.
1604: * @param path the path to process into a fully-rewritten URI.
1605: * @param params the additional parameters to include in the URI query.
1606: * @param fragment the fragment (anchor or location) for this URI.
1607: * @param forXML flag indicating that the query of the uri should be written
1608: * using the "&amp;" entity, rather than the character, '&'.
1609: * @return a fully-rewritten URI for the given action.
1610: * @throws URISyntaxException if there's a problem converting the action URI (derived
1611: * from processing the given action name) into a MutableURI.
1612: */
1613: public static String getRewrittenHrefURI(
1614: ServletContext servletContext, HttpServletRequest request,
1615: HttpServletResponse response, String path, Map params,
1616: String fragment, boolean forXML) throws URISyntaxException {
1617: return rewriteResourceOrHrefURL(servletContext, request,
1618: response, path, params, fragment, forXML,
1619: URLType.ACTION);
1620: }
1621:
1622: private static String rewriteResourceOrHrefURL(
1623: ServletContext servletContext, HttpServletRequest request,
1624: HttpServletResponse response, String path, Map params,
1625: String fragment, boolean forXML, URLType urlType)
1626: throws URISyntaxException {
1627: boolean encoded = false;
1628: UrlConfig urlConfig = ConfigUtil.getConfig().getUrlConfig();
1629:
1630: if (urlConfig != null) {
1631: encoded = !urlConfig.isUrlEncodeUrls();
1632: }
1633:
1634: FreezableMutableURI uri = new FreezableMutableURI();
1635: uri.setEncoding(response.getCharacterEncoding());
1636: uri.setURI(path, encoded);
1637:
1638: if (params != null) {
1639: uri.addParameters(params, false);
1640: }
1641:
1642: if (fragment != null) {
1643: uri.setFragment(uri.encode(fragment));
1644: }
1645:
1646: URIContext uriContext = URIContextFactory.getInstance(forXML);
1647: if (uri.isAbsolute()) {
1648: return uri.getURIString(uriContext);
1649: }
1650:
1651: if (path.length() != 0 && path.charAt(0) != '/') {
1652: String reqUri = request.getRequestURI();
1653: String reqPath = reqUri.substring(0, reqUri
1654: .lastIndexOf('/') + 1);
1655: uri.setPath(reqPath + uri.getPath());
1656: }
1657:
1658: boolean needsToBeSecure = needsToBeSecure(servletContext,
1659: request, uri.getPath(), true);
1660: URLRewriterService.rewriteURL(servletContext, request,
1661: response, uri, urlType, needsToBeSecure);
1662: String key = getURLTemplateKey(urlType, needsToBeSecure);
1663:
1664: return URLRewriterService.getTemplatedURL(servletContext,
1665: request, uri, key, uriContext);
1666: }
1667:
1668: /**
1669: * Tell whether a given URI should be written to be secure.
1670: * @param context the current ServletContext.
1671: * @param request the current HttpServletRequest.
1672: * @param uri the URI to check.
1673: * @param stripContextPath if <code>true</code>, strip the webapp context path from the URI before
1674: * processing it.
1675: * @return <code>true</code> when:
1676: * <ul>
1677: * <li>the given URI is configured in the deployment descriptor to be secure (according to
1678: * {@link SecurityProtocol}), or
1679: * <li>the given URI is not configured in the deployment descriptor, and the current request
1680: * is secure ({@link HttpServletRequest#isSecure} returns
1681: * <code>true</code>).
1682: * </ul>
1683: * <code>false</code> when:
1684: * <ul>
1685: * <li>the given URI is configured explicitly in the deployment descriptor to be unsecure
1686: * (according to {@link SecurityProtocol}), or
1687: * <li>the given URI is not configured in the deployment descriptor, and the current request
1688: * is unsecure ({@link HttpServletRequest#isSecure} returns
1689: * <code>false</code>).
1690: * </ul>
1691: */
1692: public static boolean needsToBeSecure(ServletContext context,
1693: ServletRequest request, String uri, boolean stripContextPath) {
1694: // Get the web-app relative path for security check
1695: String secureCheck = uri;
1696: if (stripContextPath) {
1697: String contextPath = ((HttpServletRequest) request)
1698: .getContextPath();
1699: if (secureCheck.startsWith(contextPath)) {
1700: secureCheck = secureCheck.substring(contextPath
1701: .length());
1702: }
1703: }
1704:
1705: boolean secure = false;
1706: if (secureCheck.indexOf('?') > -1) {
1707: secureCheck = secureCheck.substring(0, secureCheck
1708: .indexOf('?'));
1709: }
1710:
1711: SecurityProtocol sp = getSecurityProtocol(secureCheck, context,
1712: (HttpServletRequest) request);
1713: if (sp.equals(SecurityProtocol.UNSPECIFIED)) {
1714: secure = request.isSecure();
1715: } else {
1716: secure = sp.equals(SecurityProtocol.SECURE);
1717: }
1718:
1719: return secure;
1720: }
1721:
1722: /**
1723: * Returns a key for the URL template type given the URL type and a
1724: * flag indicating a secure URL or not.
1725: *
1726: * @param urlType the type of URL (ACTION, RESOURCE).
1727: * @param needsToBeSecure indicates that the template should be for a secure URL.
1728: * @return the key/type of template to use.
1729: */
1730: public static String getURLTemplateKey(URLType urlType,
1731: boolean needsToBeSecure) {
1732: String key = URLTemplatesFactory.ACTION_TEMPLATE;
1733: if (urlType.equals(URLType.ACTION)) {
1734: if (needsToBeSecure) {
1735: key = URLTemplatesFactory.SECURE_ACTION_TEMPLATE;
1736: } else {
1737: key = URLTemplatesFactory.ACTION_TEMPLATE;
1738: }
1739: } else if (urlType.equals(URLType.RESOURCE)) {
1740: if (needsToBeSecure) {
1741: key = URLTemplatesFactory.SECURE_RESOURCE_TEMPLATE;
1742: } else {
1743: key = URLTemplatesFactory.RESOURCE_TEMPLATE;
1744: }
1745: }
1746:
1747: return key;
1748: }
1749:
1750: /**
1751: * Get an uninitialized instance of a container specific URLTemplatesFactory
1752: * from the ServletContainerAdapter. If none exists, this returns an instance
1753: * of {@link DefaultURLTemplatesFactory}. Caller should then set the known
1754: * and required tokens, call the {@link URLTemplatesFactory#load(javax.servlet.ServletContext)}
1755: * method and {@link URLTemplatesFactory#initServletContext(javax.servlet.ServletContext,
1756: * org.apache.beehive.netui.core.urltemplates.URLTemplatesFactory)}.
1757: *
1758: * <p>
1759: * IMPORTANT NOTE - Always try to get the application instance from the ServletContext
1760: * by calling {@link URLTemplatesFactory#getURLTemplatesFactory(javax.servlet.ServletContext)}.
1761: * Then, if a new URLTemplatesFactory must be created, call this method.
1762: * </p>
1763: *
1764: * @param servletContext
1765: * @return a container specific implementation of URLTemplatesFactory, or
1766: * {@link DefaultURLTemplatesFactory}.
1767: */
1768: public static URLTemplatesFactory createURLTemplatesFactory(
1769: ServletContext servletContext) {
1770: // get the URLTemplatesFactory from the containerAdapter.
1771: ServletContainerAdapter containerAdapter = AdapterManager
1772: .getServletContainerAdapter(servletContext);
1773: URLTemplatesFactory factory = (URLTemplatesFactory) containerAdapter
1774: .getFactory(URLTemplatesFactory.class, null, null);
1775:
1776: // if there's no URLTemplatesFactory, use our default impl.
1777: if (factory == null) {
1778: factory = new DefaultURLTemplatesFactory();
1779: }
1780:
1781: return factory;
1782: }
1783:
1784: /**
1785: * Make sure that when this page is rendered, it will set headers in the response to prevent caching.
1786: * Because these headers are lost on server forwards, we set a request attribute to cause the headers
1787: * to be set right before the page is rendered. This attribute can be read via
1788: * {@link #isPreventCache(javax.servlet.ServletRequest)}.
1789: *
1790: * @param request the servlet request
1791: */
1792: static void setPreventCache(ServletRequest request) {
1793: assert request != null;
1794: request.setAttribute(PREVENT_CACHE_ATTR, Boolean.TRUE);
1795: }
1796:
1797: /**
1798: * Internal getter that reports whether this request should prevent caching. This flag is set via the
1799: * {@link #setPreventCache(javax.servlet.ServletRequest)} attribute.
1800: * @param request the servlet request
1801: * @return <code>true</code> if the framework has set the prevent cache flag
1802: */
1803: static boolean isPreventCache(ServletRequest request) {
1804: assert request != null;
1805: return request.getAttribute(PREVENT_CACHE_ATTR) != null;
1806: }
1807: }
|