summaryrefslogtreecommitdiffstats
path: root/sonar-duplications/src/test/files/java/RequestUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'sonar-duplications/src/test/files/java/RequestUtils.java')
-rw-r--r--sonar-duplications/src/test/files/java/RequestUtils.java1161
1 files changed, 1161 insertions, 0 deletions
diff --git a/sonar-duplications/src/test/files/java/RequestUtils.java b/sonar-duplications/src/test/files/java/RequestUtils.java
new file mode 100644
index 00000000000..2591a0d190a
--- /dev/null
+++ b/sonar-duplications/src/test/files/java/RequestUtils.java
@@ -0,0 +1,1161 @@
+/*
+ * $Id: RequestUtils.java 727180 2008-12-16 21:54:10Z niallp $
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts.util;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.Globals;
+import org.apache.struts.action.*;
+import org.apache.struts.config.ActionConfig;
+import org.apache.struts.config.FormBeanConfig;
+import org.apache.struts.config.ForwardConfig;
+import org.apache.struts.config.ModuleConfig;
+import org.apache.struts.upload.FormFile;
+import org.apache.struts.upload.MultipartRequestHandler;
+import org.apache.struts.upload.MultipartRequestWrapper;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * <p>General purpose utility methods related to processing a servlet request
+ * in the Struts controller framework.</p>
+ *
+ * @version $Rev: 727180 $ $Date: 2008-12-17 00:54:10 +0300 (Ср., 17 дек. 2008) $
+ */
+public class RequestUtils {
+ // ------------------------------------------------------- Static Variables
+
+ /**
+ * <p>Commons Logging instance.</p>
+ */
+ protected static Log log = LogFactory.getLog(RequestUtils.class);
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * <p>Create and return an absolute URL for the specified context-relative
+ * path, based on the server and context information in the specified
+ * request.</p>
+ *
+ * @param request The servlet request we are processing
+ * @param path The context-relative path (must start with '/')
+ * @return absolute URL based on context-relative path
+ * @throws MalformedURLException if we cannot create an absolute URL
+ */
+ public static URL absoluteURL(HttpServletRequest request, String path)
+ throws MalformedURLException {
+ return (new URL(serverURL(request), request.getContextPath() + path));
+ }
+
+ /**
+ * <p>Return the <code>Class</code> object for the specified fully
+ * qualified class name, from this web application's class loader.</p>
+ *
+ * @param className Fully qualified class name to be loaded
+ * @return Class object
+ * @throws ClassNotFoundException if the class cannot be found
+ */
+ public static Class applicationClass(String className)
+ throws ClassNotFoundException {
+ return applicationClass(className, null);
+ }
+
+ /**
+ * <p>Return the <code>Class</code> object for the specified fully
+ * qualified class name, from this web application's class loader.</p>
+ *
+ * @param className Fully qualified class name to be loaded
+ * @param classLoader The desired classloader to use
+ * @return Class object
+ * @throws ClassNotFoundException if the class cannot be found
+ */
+ public static Class applicationClass(String className,
+ ClassLoader classLoader)
+ throws ClassNotFoundException {
+ if (classLoader == null) {
+ // Look up the class loader to be used
+ classLoader = Thread.currentThread().getContextClassLoader();
+
+ if (classLoader == null) {
+ classLoader = RequestUtils.class.getClassLoader();
+ }
+ }
+
+ // Attempt to load the specified class
+ return (classLoader.loadClass(className));
+ }
+
+ /**
+ * <p>Return a new instance of the specified fully qualified class name,
+ * after loading the class from this web application's class loader. The
+ * specified class <strong>MUST</strong> have a public zero-arguments
+ * constructor.</p>
+ *
+ * @param className Fully qualified class name to use
+ * @return new instance of class
+ * @throws ClassNotFoundException if the class cannot be found
+ * @throws IllegalAccessException if the class or its constructor is not
+ * accessible
+ * @throws InstantiationException if this class represents an abstract
+ * class, an interface, an array class, a
+ * primitive type, or void
+ * @throws InstantiationException if this class has no zero-arguments
+ * constructor
+ */
+ public static Object applicationInstance(String className)
+ throws ClassNotFoundException, IllegalAccessException,
+ InstantiationException {
+ return applicationInstance(className, null);
+ }
+
+ /**
+ * <p>Return a new instance of the specified fully qualified class name,
+ * after loading the class from this web application's class loader. The
+ * specified class <strong>MUST</strong> have a public zero-arguments
+ * constructor.</p>
+ *
+ * @param className Fully qualified class name to use
+ * @param classLoader The desired classloader to use
+ * @return new instance of class
+ * @throws ClassNotFoundException if the class cannot be found
+ * @throws IllegalAccessException if the class or its constructor is not
+ * accessible
+ * @throws InstantiationException if this class represents an abstract
+ * class, an interface, an array class, a
+ * primitive type, or void
+ * @throws InstantiationException if this class has no zero-arguments
+ * constructor
+ */
+ public static Object applicationInstance(String className,
+ ClassLoader classLoader)
+ throws ClassNotFoundException, IllegalAccessException,
+ InstantiationException {
+ return (applicationClass(className, classLoader).newInstance());
+ }
+
+ /**
+ * <p>Create (if necessary) and return an <code>ActionForm</code> instance
+ * appropriate for this request. If no <code>ActionForm</code> instance
+ * is required, return <code>null</code>.</p>
+ *
+ * @param request The servlet request we are processing
+ * @param mapping The action mapping for this request
+ * @param moduleConfig The configuration for this module
+ * @param servlet The action servlet
+ * @return ActionForm instance associated with this request
+ */
+ public static ActionForm createActionForm(HttpServletRequest request,
+ ActionMapping mapping, ModuleConfig moduleConfig, ActionServlet servlet) {
+ // Is there a form bean associated with this mapping?
+ String attribute = mapping.getAttribute();
+
+ if (attribute == null) {
+ return (null);
+ }
+
+ // Look up the form bean configuration information to use
+ String name = mapping.getName();
+ FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
+
+ if (config == null) {
+ log.warn("No FormBeanConfig found under '" + name + "'");
+
+ return (null);
+ }
+
+ ActionForm instance =
+ lookupActionForm(request, attribute, mapping.getScope());
+
+ // Can we recycle the existing form bean instance (if there is one)?
+ if ((instance != null) && config.canReuse(instance)) {
+ return (instance);
+ }
+
+ return createActionForm(config, servlet);
+ }
+
+ private static ActionForm lookupActionForm(HttpServletRequest request,
+ String attribute, String scope) {
+ // Look up any existing form bean instance
+ if (log.isDebugEnabled()) {
+ log.debug(" Looking for ActionForm bean instance in scope '"
+ + scope + "' under attribute key '" + attribute + "'");
+ }
+
+ ActionForm instance = null;
+ HttpSession session = null;
+
+ if ("request".equals(scope)) {
+ instance = (ActionForm) request.getAttribute(attribute);
+ } else {
+ session = request.getSession();
+ instance = (ActionForm) session.getAttribute(attribute);
+ }
+
+ return (instance);
+ }
+
+ /**
+ * <p>Create and return an <code>ActionForm</code> instance appropriate to
+ * the information in <code>config</code>.</p>
+ * <p/>
+ * <p>Does not perform any checks to see if an existing ActionForm exists
+ * which could be reused.</p>
+ *
+ * @param config The configuration for the Form bean which is to be
+ * created.
+ * @param servlet The action servlet
+ * @return ActionForm instance associated with this request
+ */
+ public static ActionForm createActionForm(FormBeanConfig config,
+ ActionServlet servlet) {
+ if (config == null) {
+ return (null);
+ }
+
+ ActionForm instance = null;
+
+ // Create and return a new form bean instance
+ try {
+ instance = config.createActionForm(servlet);
+
+ if (log.isDebugEnabled()) {
+ log.debug(" Creating new "
+ + (config.getDynamic() ? "DynaActionForm" : "ActionForm")
+ + " instance of type '" + config.getType() + "'");
+ log.trace(" --> " + instance);
+ }
+ } catch (Throwable t) {
+ log.error(servlet.getInternal().getMessage("formBean",
+ config.getType()), t);
+ }
+
+ return (instance);
+ }
+
+ /**
+ * <p>Retrieves the servlet mapping pattern for the specified {@link ActionServlet}.</p>
+ *
+ * @return the servlet mapping
+ * @see Globals#SERVLET_KEY
+ * @since Struts 1.3.6
+ */
+ public static String getServletMapping(ActionServlet servlet) {
+ ServletContext servletContext = servlet.getServletConfig().getServletContext();
+ return (String) servletContext.getAttribute(Globals.SERVLET_KEY);
+ }
+
+ /**
+ * <p>Look up and return current user locale, based on the specified
+ * parameters.</p>
+ *
+ * @param request The request used to lookup the Locale
+ * @param locale Name of the session attribute for our user's Locale. If
+ * this is <code>null</code>, the default locale key is
+ * used for the lookup.
+ * @return current user locale
+ * @since Struts 1.2
+ */
+ public static Locale getUserLocale(HttpServletRequest request, String locale) {
+ Locale userLocale = null;
+ HttpSession session = request.getSession(false);
+
+ if (locale == null) {
+ locale = Globals.LOCALE_KEY;
+ }
+
+ // Only check session if sessions are enabled
+ if (session != null) {
+ userLocale = (Locale) session.getAttribute(locale);
+ }
+
+ if (userLocale == null) {
+ // Returns Locale based on Accept-Language header or the server default
+ userLocale = request.getLocale();
+ }
+
+ return userLocale;
+ }
+
+ /**
+ * <p>Populate the properties of the specified JavaBean from the specified
+ * HTTP request, based on matching each parameter name against the
+ * corresponding JavaBeans "property setter" methods in the bean's class.
+ * Suitable conversion is done for argument types as described under
+ * <code>convert()</code>.</p>
+ *
+ * @param bean The JavaBean whose properties are to be set
+ * @param request The HTTP request whose parameters are to be used to
+ * populate bean properties
+ * @throws ServletException if an exception is thrown while setting
+ * property values
+ */
+ public static void populate(Object bean, HttpServletRequest request)
+ throws ServletException {
+ populate(bean, null, null, request);
+ }
+
+ /**
+ * <p>Populate the properties of the specified JavaBean from the specified
+ * HTTP request, based on matching each parameter name (plus an optional
+ * prefix and/or suffix) against the corresponding JavaBeans "property
+ * setter" methods in the bean's class. Suitable conversion is done for
+ * argument types as described under <code>setProperties</code>.</p>
+ * <p/>
+ * <p>If you specify a non-null <code>prefix</code> and a non-null
+ * <code>suffix</code>, the parameter name must match
+ * <strong>both</strong> conditions for its value(s) to be used in
+ * populating bean properties. If the request's content type is
+ * "multipart/form-data" and the method is "POST", the
+ * <code>HttpServletRequest</code> object will be wrapped in a
+ * <code>MultipartRequestWrapper</code object.</p>
+ *
+ * @param bean The JavaBean whose properties are to be set
+ * @param prefix The prefix (if any) to be prepend to bean property names
+ * when looking for matching parameters
+ * @param suffix The suffix (if any) to be appended to bean property
+ * names when looking for matching parameters
+ * @param request The HTTP request whose parameters are to be used to
+ * populate bean properties
+ * @throws ServletException if an exception is thrown while setting
+ * property values
+ */
+ public static void populate(Object bean, String prefix, String suffix,
+ HttpServletRequest request)
+ throws ServletException {
+ // Build a list of relevant request parameters from this request
+ HashMap properties = new HashMap();
+
+ // Iterator of parameter names
+ Enumeration names = null;
+
+ // Map for multipart parameters
+ Map multipartParameters = null;
+
+ String contentType = request.getContentType();
+ String method = request.getMethod();
+ boolean isMultipart = false;
+
+ if (bean instanceof ActionForm) {
+ ((ActionForm) bean).setMultipartRequestHandler(null);
+ }
+
+ MultipartRequestHandler multipartHandler = null;
+ if ((contentType != null)
+ && (contentType.startsWith("multipart/form-data"))
+ && (method.equalsIgnoreCase("POST"))) {
+ // Get the ActionServletWrapper from the form bean
+ ActionServletWrapper servlet;
+
+ if (bean instanceof ActionForm) {
+ servlet = ((ActionForm) bean).getServletWrapper();
+ } else {
+ throw new ServletException("bean that's supposed to be "
+ + "populated from a multipart request is not of type "
+ + "\"org.apache.struts.action.ActionForm\", but type "
+ + "\"" + bean.getClass().getName() + "\"");
+ }
+
+ // Obtain a MultipartRequestHandler
+ multipartHandler = getMultipartHandler(request);
+
+ if (multipartHandler != null) {
+ isMultipart = true;
+
+ // Set servlet and mapping info
+ servlet.setServletFor(multipartHandler);
+ multipartHandler.setMapping((ActionMapping) request
+ .getAttribute(Globals.MAPPING_KEY));
+
+ // Initialize multipart request class handler
+ multipartHandler.handleRequest(request);
+
+ //stop here if the maximum length has been exceeded
+ Boolean maxLengthExceeded =
+ (Boolean) request.getAttribute(MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED);
+
+ if ((maxLengthExceeded != null)
+ && (maxLengthExceeded.booleanValue())) {
+ ((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
+ return;
+ }
+
+ //retrieve form values and put into properties
+ multipartParameters =
+ getAllParametersForMultipartRequest(request,
+ multipartHandler);
+ names = Collections.enumeration(multipartParameters.keySet());
+ }
+ }
+
+ if (!isMultipart) {
+ names = request.getParameterNames();
+ }
+
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ String stripped = name;
+
+ if (prefix != null) {
+ if (!stripped.startsWith(prefix)) {
+ continue;
+ }
+
+ stripped = stripped.substring(prefix.length());
+ }
+
+ if (suffix != null) {
+ if (!stripped.endsWith(suffix)) {
+ continue;
+ }
+
+ stripped =
+ stripped.substring(0, stripped.length() - suffix.length());
+ }
+
+ Object parameterValue = null;
+
+ if (isMultipart) {
+ parameterValue = multipartParameters.get(name);
+ parameterValue = rationalizeMultipleFileProperty(bean, name, parameterValue);
+ } else {
+ parameterValue = request.getParameterValues(name);
+ }
+
+ // Populate parameters, except "standard" struts attributes
+ // such as 'org.apache.struts.action.CANCEL'
+ if (!(stripped.startsWith("org.apache.struts."))) {
+ properties.put(stripped, parameterValue);
+ }
+ }
+
+ // Set the corresponding properties of our bean
+ try {
+ BeanUtils.populate(bean, properties);
+ } catch (Exception e) {
+ throw new ServletException("BeanUtils.populate", e);
+ } finally {
+ if (multipartHandler != null) {
+ // Set the multipart request handler for our ActionForm.
+ // If the bean isn't an ActionForm, an exception would have been
+ // thrown earlier, so it's safe to assume that our bean is
+ // in fact an ActionForm.
+ ((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
+ }
+ }
+ }
+
+ /**
+ * <p>Populates the parameters of the specified ActionRedirect from
+ * the specified HTTP request.</p>
+ *
+ * @param redirect The ActionRedirect whose parameters are to be set
+ * @param request The HTTP request whose parameters are to be used
+ * @since Struts 1.4
+ */
+ public static void populate(ActionRedirect redirect, HttpServletRequest request) {
+ assert (redirect != null) : "redirect is required";
+ assert (request != null) : "request is required";
+
+ Enumeration e = request.getParameterNames();
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+ String[] values = request.getParameterValues(name);
+ redirect.addParameter(name, values);
+ }
+ }
+
+ /**
+ * <p>If the given form bean can accept multiple FormFile objects but the user only uploaded a single, then
+ * the property will not match the form bean type. This method performs some simple checks to try to accommodate
+ * that situation.</p>
+ *
+ * @param bean
+ * @param name
+ * @param parameterValue
+ * @return
+ * @throws ServletException if the introspection has any errors.
+ */
+ private static Object rationalizeMultipleFileProperty(Object bean, String name, Object parameterValue) throws ServletException {
+ if (!(parameterValue instanceof FormFile)) {
+ return parameterValue;
+ }
+
+ FormFile formFileValue = (FormFile) parameterValue;
+ try {
+ Class propertyType = PropertyUtils.getPropertyType(bean, name);
+
+ if (propertyType == null) {
+ return parameterValue;
+ }
+
+ if (List.class.isAssignableFrom(propertyType)) {
+ ArrayList list = new ArrayList(1);
+ list.add(formFileValue);
+ return list;
+ }
+
+ if (propertyType.isArray() && propertyType.getComponentType().equals(FormFile.class)) {
+ return new FormFile[]{formFileValue};
+ }
+
+ } catch (IllegalAccessException e) {
+ throw new ServletException(e);
+ } catch (InvocationTargetException e) {
+ throw new ServletException(e);
+ } catch (NoSuchMethodException e) {
+ throw new ServletException(e);
+ }
+
+ // no changes
+ return parameterValue;
+
+ }
+
+ /**
+ * <p>Try to locate a multipart request handler for this request. First,
+ * look for a mapping-specific handler stored for us under an attribute.
+ * If one is not present, use the global multipart handler, if there is
+ * one.</p>
+ *
+ * @param request The HTTP request for which the multipart handler should
+ * be found.
+ * @return the multipart handler to use, or null if none is found.
+ * @throws ServletException if any exception is thrown while attempting to
+ * locate the multipart handler.
+ */
+ private static MultipartRequestHandler getMultipartHandler(
+ HttpServletRequest request)
+ throws ServletException {
+ MultipartRequestHandler multipartHandler = null;
+ String multipartClass =
+ (String) request.getAttribute(Globals.MULTIPART_KEY);
+
+ request.removeAttribute(Globals.MULTIPART_KEY);
+
+ // Try to initialize the mapping specific request handler
+ if (multipartClass != null) {
+ try {
+ multipartHandler =
+ (MultipartRequestHandler) applicationInstance(multipartClass);
+ } catch (ClassNotFoundException cnfe) {
+ log.error("MultipartRequestHandler class \"" + multipartClass
+ + "\" in mapping class not found, "
+ + "defaulting to global multipart class");
+ } catch (InstantiationException ie) {
+ log.error("InstantiationException when instantiating "
+ + "MultipartRequestHandler \"" + multipartClass + "\", "
+ + "defaulting to global multipart class, exception: "
+ + ie.getMessage());
+ } catch (IllegalAccessException iae) {
+ log.error("IllegalAccessException when instantiating "
+ + "MultipartRequestHandler \"" + multipartClass + "\", "
+ + "defaulting to global multipart class, exception: "
+ + iae.getMessage());
+ }
+
+ if (multipartHandler != null) {
+ return multipartHandler;
+ }
+ }
+
+ ModuleConfig moduleConfig =
+ ModuleUtils.getInstance().getModuleConfig(request);
+
+ multipartClass = moduleConfig.getControllerConfig().getMultipartClass();
+
+ // Try to initialize the global request handler
+ if (multipartClass != null) {
+ try {
+ multipartHandler =
+ (MultipartRequestHandler) applicationInstance(multipartClass);
+ } catch (ClassNotFoundException cnfe) {
+ throw new ServletException("Cannot find multipart class \""
+ + multipartClass + "\"", cnfe);
+ } catch (InstantiationException ie) {
+ throw new ServletException(
+ "InstantiationException when instantiating "
+ + "multipart class \"" + multipartClass + "\"", ie);
+ } catch (IllegalAccessException iae) {
+ throw new ServletException(
+ "IllegalAccessException when instantiating "
+ + "multipart class \"" + multipartClass + "\"", iae);
+ }
+
+ if (multipartHandler != null) {
+ return multipartHandler;
+ }
+ }
+
+ return multipartHandler;
+ }
+
+ /**
+ * <p>Create a <code>Map</code> containing all of the parameters supplied
+ * for a multipart request, keyed by parameter name. In addition to text
+ * and file elements from the multipart body, query string parameters are
+ * included as well.</p>
+ *
+ * @param request The (wrapped) HTTP request whose parameters are
+ * to be added to the map.
+ * @param multipartHandler The multipart handler used to parse the
+ * request.
+ * @return the map containing all parameters for this multipart request.
+ */
+ private static Map getAllParametersForMultipartRequest(
+ HttpServletRequest request, MultipartRequestHandler multipartHandler) {
+ Map parameters = new HashMap();
+ Hashtable elements = multipartHandler.getAllElements();
+ Enumeration e = elements.keys();
+
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+
+ parameters.put(key, elements.get(key));
+ }
+
+ if (request instanceof MultipartRequestWrapper) {
+ request =
+ (HttpServletRequest) ((MultipartRequestWrapper) request)
+ .getRequest();
+ e = request.getParameterNames();
+
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+
+ parameters.put(key, request.getParameterValues(key));
+ }
+ } else {
+ log.debug("Gathering multipart parameters for unwrapped request");
+ }
+
+ return parameters;
+ }
+
+ /**
+ * <p>Compute the printable representation of a URL, leaving off the
+ * scheme/host/port part if no host is specified. This will typically be
+ * the case for URLs that were originally created from relative or
+ * context-relative URIs.</p>
+ *
+ * @param url URL to render in a printable representation
+ * @return printable representation of a URL
+ */
+ public static String printableURL(URL url) {
+ if (url.getHost() != null) {
+ return (url.toString());
+ }
+
+ String file = url.getFile();
+ String ref = url.getRef();
+
+ if (ref == null) {
+ return (file);
+ } else {
+ StringBuffer sb = new StringBuffer(file);
+
+ sb.append('#');
+ sb.append(ref);
+
+ return (sb.toString());
+ }
+ }
+
+ /**
+ * <p>Return the context-relative URL that corresponds to the specified
+ * {@link ActionConfig}, relative to the module associated with the
+ * current modules's {@link ModuleConfig}.</p>
+ *
+ * @param request The servlet request we are processing
+ * @param action ActionConfig to be evaluated
+ * @param pattern URL pattern used to map the controller servlet
+ * @return context-relative URL relative to the module
+ * @since Struts 1.1
+ */
+ public static String actionURL(HttpServletRequest request,
+ ActionConfig action, String pattern) {
+ StringBuffer sb = new StringBuffer();
+
+ if (pattern.endsWith("/*")) {
+ sb.append(pattern.substring(0, pattern.length() - 2));
+ sb.append(action.getPath());
+ } else if (pattern.startsWith("*.")) {
+ ModuleConfig appConfig =
+ ModuleUtils.getInstance().getModuleConfig(request);
+
+ sb.append(appConfig.getPrefix());
+ sb.append(action.getPath());
+ sb.append(pattern.substring(1));
+ } else {
+ throw new IllegalArgumentException(pattern);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * <p>Return the context-relative URL that corresponds to the specified
+ * <code>ForwardConfig</code>. The URL is calculated based on the
+ * properties of the {@link ForwardConfig} instance as follows:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <p/>
+ * <li>If the <code>contextRelative</code> property is set, it is assumed
+ * that the <code>path</code> property contains a path that is already
+ * context-relative:
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>If the <code>path</code> property value starts with a slash, it is
+ * returned unmodified.</li> <li>If the <code>path</code> property value
+ * does not start with a slash, a slash is prepended.</li>
+ * <p/>
+ * </ul></li>
+ * <p/>
+ * <li>Acquire the <code>forwardPattern</code> property from the
+ * <code>ControllerConfig</code> for the application module used to
+ * process this request. If no pattern was configured, default to a
+ * pattern of <code>$M$P</code>, which is compatible with the hard-coded
+ * mapping behavior in Struts 1.0.</li>
+ * <p/>
+ * <li>Process the acquired <code>forwardPattern</code>, performing the
+ * following substitutions:
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li><strong>$M</strong> - Replaced by the module prefix for the
+ * application module processing this request.</li>
+ * <p/>
+ * <li><strong>$P</strong> - Replaced by the <code>path</code> property of
+ * the specified {@link ForwardConfig}, prepended with a slash if it does
+ * not start with one.</li>
+ * <p/>
+ * <li><strong>$$</strong> - Replaced by a single dollar sign
+ * character.</li>
+ * <p/>
+ * <li><strong>$x</strong> (where "x" is any charater not listed above) -
+ * Silently omit these two characters from the result value. (This has
+ * the side effect of causing all other $+letter combinations to be
+ * reserved.)</li>
+ * <p/>
+ * </ul></li>
+ * <p/>
+ * </ul>
+ *
+ * @param request The servlet request we are processing
+ * @param forward ForwardConfig to be evaluated
+ * @return context-relative URL
+ * @since Struts 1.1
+ */
+ public static String forwardURL(HttpServletRequest request,
+ ForwardConfig forward) {
+ return forwardURL(request, forward, null);
+ }
+
+ /**
+ * <p>Return the context-relative URL that corresponds to the specified
+ * <code>ForwardConfig</code>. The URL is calculated based on the
+ * properties of the {@link ForwardConfig} instance as follows:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>If the <code>contextRelative</code> property is set, it is assumed
+ * that the <code>path</code> property contains a path that is already
+ * context-relative: <ul>
+ * <p/>
+ * <li>If the <code>path</code> property value starts with a slash, it is
+ * returned unmodified.</li> <li>If the <code>path</code> property value
+ * does not start with a slash, a slash is prepended.</li>
+ * <p/>
+ * </ul></li>
+ * <p/>
+ * <li>Acquire the <code>forwardPattern</code> property from the
+ * <code>ControllerConfig</code> for the application module used to
+ * process this request. If no pattern was configured, default to a
+ * pattern of <code>$M$P</code>, which is compatible with the hard-coded
+ * mapping behavior in Struts 1.0.</li>
+ * <p/>
+ * <li>Process the acquired <code>forwardPattern</code>, performing the
+ * following substitutions: <ul> <li><strong>$M</strong> - Replaced by the
+ * module prefix for the application module processing this request.</li>
+ * <p/>
+ * <li><strong>$P</strong> - Replaced by the <code>path</code> property of
+ * the specified {@link ForwardConfig}, prepended with a slash if it does
+ * not start with one.</li>
+ * <p/>
+ * <li><strong>$$</strong> - Replaced by a single dollar sign
+ * character.</li>
+ * <p/>
+ * <li><strong>$x</strong> (where "x" is any charater not listed above) -
+ * Silently omit these two characters from the result value. (This has
+ * the side effect of causing all other $+letter combinations to be
+ * reserved.)</li>
+ * <p/>
+ * </ul></li></ul>
+ *
+ * @param request The servlet request we are processing
+ * @param forward ForwardConfig to be evaluated
+ * @param moduleConfig Base forward on this module config.
+ * @return context-relative URL
+ * @since Struts 1.2
+ */
+ public static String forwardURL(HttpServletRequest request,
+ ForwardConfig forward, ModuleConfig moduleConfig) {
+ //load the current moduleConfig, if null
+ if (moduleConfig == null) {
+ moduleConfig = ModuleUtils.getInstance().getModuleConfig(request);
+ }
+
+ String path = forward.getPath();
+
+ //load default prefix
+ String prefix = moduleConfig.getPrefix();
+
+ //override prefix if supplied by forward
+ if (forward.getModule() != null) {
+ prefix = forward.getModule();
+
+ if ("/".equals(prefix)) {
+ prefix = "";
+ }
+ }
+
+ StringBuffer sb = new StringBuffer();
+
+ // Calculate a context relative path for this ForwardConfig
+ String forwardPattern =
+ moduleConfig.getControllerConfig().getForwardPattern();
+
+ if (forwardPattern == null) {
+ // Performance optimization for previous default behavior
+ sb.append(prefix);
+
+ // smoothly insert a '/' if needed
+ if (!path.startsWith("/")) {
+ sb.append("/");
+ }
+
+ sb.append(path);
+ } else {
+ boolean dollar = false;
+
+ for (int i = 0; i < forwardPattern.length(); i++) {
+ char ch = forwardPattern.charAt(i);
+
+ if (dollar) {
+ switch (ch) {
+ case 'M':
+ sb.append(prefix);
+
+ break;
+
+ case 'P':
+
+ // add '/' if needed
+ if (!path.startsWith("/")) {
+ sb.append("/");
+ }
+
+ sb.append(path);
+
+ break;
+
+ case '$':
+ sb.append('$');
+
+ break;
+
+ default:
+ ; // Silently swallow
+ }
+
+ dollar = false;
+
+ continue;
+ } else if (ch == '$') {
+ dollar = true;
+ } else {
+ sb.append(ch);
+ }
+ }
+ }
+
+ return (sb.toString());
+ }
+
+ /**
+ * <p>Return the URL representing the current request. This is equivalent
+ * to <code>HttpServletRequest.getRequestURL</code> in Servlet 2.3.</p>
+ *
+ * @param request The servlet request we are processing
+ * @return URL representing the current request
+ * @throws MalformedURLException if a URL cannot be created
+ */
+ public static URL requestURL(HttpServletRequest request)
+ throws MalformedURLException {
+ StringBuffer url = requestToServerUriStringBuffer(request);
+
+ return (new URL(url.toString()));
+ }
+
+ /**
+ * <p>Return the URL representing the scheme, server, and port number of
+ * the current request. Server-relative URLs can be created by simply
+ * appending the server-relative path (starting with '/') to this.</p>
+ *
+ * @param request The servlet request we are processing
+ * @return URL representing the scheme, server, and port number of the
+ * current request
+ * @throws MalformedURLException if a URL cannot be created
+ */
+ public static URL serverURL(HttpServletRequest request)
+ throws MalformedURLException {
+ StringBuffer url = requestToServerStringBuffer(request);
+
+ return (new URL(url.toString()));
+ }
+
+ /**
+ * <p>Return the string representing the scheme, server, and port number
+ * of the current request. Server-relative URLs can be created by simply
+ * appending the server-relative path (starting with '/') to this.</p>
+ *
+ * @param request The servlet request we are processing
+ * @return URL representing the scheme, server, and port number of the
+ * current request
+ * @since Struts 1.2.0
+ */
+ public static StringBuffer requestToServerUriStringBuffer(
+ HttpServletRequest request) {
+ StringBuffer serverUri =
+ createServerUriStringBuffer(request.getScheme(),
+ request.getServerName(), request.getServerPort(),
+ request.getRequestURI());
+
+ return serverUri;
+ }
+
+ /**
+ * <p>Return <code>StringBuffer</code> representing the scheme, server,
+ * and port number of the current request. Server-relative URLs can be
+ * created by simply appending the server-relative path (starting with
+ * '/') to this.</p>
+ *
+ * @param request The servlet request we are processing
+ * @return URL representing the scheme, server, and port number of the
+ * current request
+ * @since Struts 1.2.0
+ */
+ public static StringBuffer requestToServerStringBuffer(
+ HttpServletRequest request) {
+ return createServerStringBuffer(request.getScheme(),
+ request.getServerName(), request.getServerPort());
+ }
+
+ /**
+ * <p>Return <code>StringBuffer</code> representing the scheme, server,
+ * and port number of the current request.</p>
+ *
+ * @param scheme The scheme name to use
+ * @param server The server name to use
+ * @param port The port value to use
+ * @return StringBuffer in the form scheme: server: port
+ * @since Struts 1.2.0
+ */
+ public static StringBuffer createServerStringBuffer(String scheme,
+ String server, int port) {
+ StringBuffer url = new StringBuffer();
+
+ if (port < 0) {
+ port = 80; // Work around java.net.URL bug
+ }
+
+ url.append(scheme);
+ url.append("://");
+ url.append(server);
+
+ if ((scheme.equals("http") && (port != 80))
+ || (scheme.equals("https") && (port != 443))) {
+ url.append(':');
+ url.append(port);
+ }
+
+ return url;
+ }
+
+ /**
+ * <p>Return <code>StringBuffer</code> representing the scheme, server,
+ * and port number of the current request.</p>
+ *
+ * @param scheme The scheme name to use
+ * @param server The server name to use
+ * @param port The port value to use
+ * @param uri The uri value to use
+ * @return StringBuffer in the form scheme: server: port
+ * @since Struts 1.2.0
+ */
+ public static StringBuffer createServerUriStringBuffer(String scheme,
+ String server, int port, String uri) {
+ StringBuffer serverUri = createServerStringBuffer(scheme, server, port);
+
+ serverUri.append(uri);
+
+ return serverUri;
+ }
+
+ /**
+ * <p>Returns the true path of the destination action if the specified forward
+ * is an action-aliased URL. This method version forms the URL based on
+ * the current request; selecting the current module if the forward does not
+ * explicitly contain a module path.</p>
+ *
+ * @param forward the forward config
+ * @param request the current request
+ * @param servlet the servlet handling the current request
+ * @return the context-relative URL of the action if the forward has an action identifier; otherwise <code>null</code>.
+ * @since Struts 1.3.6
+ */
+ public static String actionIdURL(ForwardConfig forward, HttpServletRequest request, ActionServlet servlet) {
+ ModuleConfig moduleConfig = null;
+ if (forward.getModule() != null) {
+ String prefix = forward.getModule();
+ moduleConfig = ModuleUtils.getInstance().getModuleConfig(prefix, servlet.getServletContext());
+ } else {
+ moduleConfig = ModuleUtils.getInstance().getModuleConfig(request);
+ }
+ return actionIdURL(forward.getPath(), moduleConfig, servlet);
+ }
+
+ /**
+ * <p>Returns the true path of the destination action if the specified forward
+ * is an action-aliased URL. This method version forms the URL based on
+ * the specified module.
+ *
+ * @param originalPath the action-aliased path
+ * @param moduleConfig the module config for this request
+ * @param servlet the servlet handling the current request
+ * @return the context-relative URL of the action if the path has an action identifier; otherwise <code>null</code>.
+ * @since Struts 1.3.6
+ */
+ public static String actionIdURL(String originalPath, ModuleConfig moduleConfig, ActionServlet servlet) {
+ if (originalPath.startsWith("http") || originalPath.startsWith("/")) {
+ return null;
+ }
+
+ // Split the forward path into the resource and query string;
+ // it is possible a forward (or redirect) has added parameters.
+ String actionId = null;
+ String qs = null;
+ int qpos = originalPath.indexOf("?");
+ if (qpos == -1) {
+ actionId = originalPath;
+ } else {
+ actionId = originalPath.substring(0, qpos);
+ qs = originalPath.substring(qpos);
+ }
+
+ // Find the action of the given actionId
+ ActionConfig actionConfig = moduleConfig.findActionConfigId(actionId);
+ if (actionConfig == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("No actionId found for " + actionId);
+ }
+ return null;
+ }
+
+ String path = actionConfig.getPath();
+ String mapping = RequestUtils.getServletMapping(servlet);
+ StringBuffer actionIdPath = new StringBuffer();
+
+ // Form the path based on the servlet mapping pattern
+ if (mapping.startsWith("*")) {
+ actionIdPath.append(path);
+ actionIdPath.append(mapping.substring(1));
+ } else if (mapping.startsWith("/")) { // implied ends with a *
+ mapping = mapping.substring(0, mapping.length() - 1);
+ if (mapping.endsWith("/") && path.startsWith("/")) {
+ actionIdPath.append(mapping);
+ actionIdPath.append(path.substring(1));
+ } else {
+ actionIdPath.append(mapping);
+ actionIdPath.append(path);
+ }
+ } else {
+ log.warn("Unknown servlet mapping pattern");
+ actionIdPath.append(path);
+ }
+
+ // Lastly add any query parameters (the ? is part of the query string)
+ if (qs != null) {
+ actionIdPath.append(qs);
+ }
+
+ // Return the path
+ if (log.isDebugEnabled()) {
+ log.debug(originalPath + " unaliased to " + actionIdPath.toString());
+ }
+ return actionIdPath.toString();
+ }
+
+ /**
+ * Determines whether the current request is forwarded.
+ *
+ * @param request current HTTP request
+ * @return true if the request is forwarded; otherwise false
+ * @since Struts 1.4
+ */
+ public static boolean isRequestForwarded(HttpServletRequest request) {
+ return (request.getAttribute("javax.servlet.forward.request_uri") != null);
+ }
+
+ /**
+ * Determines whether the current request is included.
+ *
+ * @param request current HTTP request
+ * @return true if the request is included; otherwise false
+ * @since Struts 1.4
+ */
+ public static boolean isRequestIncluded(HttpServletRequest request) {
+ return (request.getAttribute("javax.servlet.include.request_uri") != null);
+ }
+
+ /**
+ * Verifies whether current request is forwarded from one action to
+ * another or not.
+ *
+ * @param request current HTTP request
+ * @return true if the request is chained; otherwise false
+ * @since Struts 1.4
+ */
+ public static boolean isRequestChained(HttpServletRequest request) {
+ return (request.getAttribute(Globals.CHAIN_KEY) != null);
+ }
+}