diff options
Diffstat (limited to 'sonar-duplications/src/test/files')
-rw-r--r-- | sonar-duplications/src/test/files/java/MessageResources.java | 508 | ||||
-rw-r--r-- | sonar-duplications/src/test/files/java/RequestUtils.java | 1161 |
2 files changed, 1669 insertions, 0 deletions
diff --git a/sonar-duplications/src/test/files/java/MessageResources.java b/sonar-duplications/src/test/files/java/MessageResources.java new file mode 100644 index 00000000000..fbed9f7e738 --- /dev/null +++ b/sonar-duplications/src/test/files/java/MessageResources.java @@ -0,0 +1,508 @@ +/* + * $Id: MessageResources.java 471754 2006-11-06 14:55:09Z husted $ + * + * 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.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Locale; + +/** + * General purpose abstract class that describes an API for retrieving + * Locale-sensitive messages from underlying resource locations of an + * unspecified design, and optionally utilizing the <code>MessageFormat</code> + * class to produce internationalized messages with parametric replacement. + * <p> Calls to <code>getMessage()</code> variants without a + * <code>Locale</code> argument are presumed to be requesting a message string + * in the default <code>Locale</code> for this JVM. <p> Calls to + * <code>getMessage()</code> with an unknown key, or an unknown + * <code>Locale</code> will return <code>null</code> if the + * <code>returnNull</code> property is set to <code>true</code>. Otherwise, a + * suitable error message will be returned instead. <p> <strong>IMPLEMENTATION + * NOTE</strong> - Classes that extend this class must be Serializable so that + * instances may be used in distributable application server environments. + * + * @version $Rev: 471754 $ $Date: 2005-08-29 23:57:50 -0400 (Mon, 29 Aug 2005) + * $ + */ +public abstract class MessageResources implements Serializable { + // ------------------------------------------------------------- Properties + + /** + * Commons Logging instance. + */ + protected static Log log = LogFactory.getLog(MessageResources.class); + + // --------------------------------------------------------- Static Methods + + /** + * The default MessageResourcesFactory used to create MessageResources + * instances. + */ + protected static MessageResourcesFactory defaultFactory = null; + + /** + * The configuration parameter used to initialize this MessageResources. + */ + protected String config = null; + + /** + * The default Locale for our environment. + */ + protected Locale defaultLocale = Locale.getDefault(); + + /** + * The <code>MessageResourcesFactory</code> that created this instance. + */ + protected MessageResourcesFactory factory = null; + + /** + * The set of previously created MessageFormat objects, keyed by the key + * computed in <code>messageKey()</code>. + */ + protected HashMap formats = new HashMap(); + + /** + * Indicate is a <code>null</code> is returned instead of an error message + * string when an unknown Locale or key is requested. + */ + protected boolean returnNull = false; + + /** + * Indicates whether 'escape processing' should be performed on the error + * message string. + */ + private boolean escape = true; + + // ----------------------------------------------------------- Constructors + + /** + * Construct a new MessageResources according to the specified + * parameters. + * + * @param factory The MessageResourcesFactory that created us + * @param config The configuration parameter for this MessageResources + */ + public MessageResources(MessageResourcesFactory factory, String config) { + this(factory, config, false); + } + + /** + * Construct a new MessageResources according to the specified + * parameters. + * + * @param factory The MessageResourcesFactory that created us + * @param config The configuration parameter for this + * MessageResources + * @param returnNull The returnNull property we should initialize with + */ + public MessageResources(MessageResourcesFactory factory, String config, + boolean returnNull) { + super(); + this.factory = factory; + this.config = config; + this.returnNull = returnNull; + } + + /** + * The configuration parameter used to initialize this MessageResources. + * + * @return parameter used to initialize this MessageResources + */ + public String getConfig() { + return (this.config); + } + + /** + * The <code>MessageResourcesFactory</code> that created this instance. + * + * @return <code>MessageResourcesFactory</code> that created instance + */ + public MessageResourcesFactory getFactory() { + return (this.factory); + } + + /** + * Indicates that a <code>null</code> is returned instead of an error + * message string if an unknown Locale or key is requested. + * + * @return true if null is returned if unknown key or locale is requested + */ + public boolean getReturnNull() { + return (this.returnNull); + } + + /** + * Indicates that a <code>null</code> is returned instead of an error + * message string if an unknown Locale or key is requested. + * + * @param returnNull true Indicates that a <code>null</code> is returned + * if an unknown Locale or key is requested. + */ + public void setReturnNull(boolean returnNull) { + this.returnNull = returnNull; + } + + /** + * Indicates whether 'escape processing' should be performed on the error + * message string. + * + * @since Struts 1.2.8 + */ + public boolean isEscape() { + return escape; + } + + /** + * Set whether 'escape processing' should be performed on the error + * message string. + * + * @since Struts 1.2.8 + */ + public void setEscape(boolean escape) { + this.escape = escape; + } + + // --------------------------------------------------------- Public Methods + + /** + * Returns a text message for the specified key, for the default Locale. + * + * @param key The message key to look up + */ + public String getMessage(String key) { + return this.getMessage((Locale) null, key, null); + } + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. + * + * @param key The message key to look up + * @param args An array of replacement parameters for placeholders + */ + public String getMessage(String key, Object[] args) { + return this.getMessage((Locale) null, key, args); + } + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. + * + * @param key The message key to look up + * @param arg0 The replacement for placeholder {0} in the message + */ + public String getMessage(String key, Object arg0) { + return this.getMessage((Locale) null, key, arg0); + } + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. + * + * @param key The message key to look up + * @param arg0 The replacement for placeholder {0} in the message + * @param arg1 The replacement for placeholder {1} in the message + */ + public String getMessage(String key, Object arg0, Object arg1) { + return this.getMessage((Locale) null, key, arg0, arg1); + } + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. + * + * @param key The message key to look up + * @param arg0 The replacement for placeholder {0} in the message + * @param arg1 The replacement for placeholder {1} in the message + * @param arg2 The replacement for placeholder {2} in the message + */ + public String getMessage(String key, Object arg0, Object arg1, Object arg2) { + return this.getMessage((Locale) null, key, arg0, arg1, arg2); + } + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. + * + * @param key The message key to look up + * @param arg0 The replacement for placeholder {0} in the message + * @param arg1 The replacement for placeholder {1} in the message + * @param arg2 The replacement for placeholder {2} in the message + * @param arg3 The replacement for placeholder {3} in the message + */ + public String getMessage(String key, Object arg0, Object arg1, Object arg2, + Object arg3) { + return this.getMessage((Locale) null, key, arg0, arg1, arg2, arg3); + } + + /** + * Returns a text message for the specified key, for the default Locale. A + * null string result will be returned by this method if no relevant + * message resource is found for this key or Locale, if the + * <code>returnNull</code> property is set. Otherwise, an appropriate + * error message will be returned. <p> This method must be implemented by + * a concrete subclass. + * + * @param locale The requested message Locale, or <code>null</code> for + * the system default Locale + * @param key The message key to look up + */ + public abstract String getMessage(Locale locale, String key); + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. A null string result will be returned by this + * method if no resource bundle has been configured. + * + * @param locale The requested message Locale, or <code>null</code> for + * the system default Locale + * @param key The message key to look up + * @param args An array of replacement parameters for placeholders + */ + public String getMessage(Locale locale, String key, Object[] args) { + // Cache MessageFormat instances as they are accessed + if (locale == null) { + locale = defaultLocale; + } + + MessageFormat format = null; + String formatKey = messageKey(locale, key); + + synchronized (formats) { + format = (MessageFormat) formats.get(formatKey); + + if (format == null) { + String formatString = getMessage(locale, key); + + if (formatString == null) { + return returnNull ? null : ("???" + formatKey + "???"); + } + + format = new MessageFormat(escape(formatString)); + format.setLocale(locale); + formats.put(formatKey, format); + } + } + + return format.format(args); + } + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. A null string result will never be returned by + * this method. + * + * @param locale The requested message Locale, or <code>null</code> for + * the system default Locale + * @param key The message key to look up + * @param arg0 The replacement for placeholder {0} in the message + */ + public String getMessage(Locale locale, String key, Object arg0) { + return this.getMessage(locale, key, new Object[]{arg0}); + } + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. A null string result will never be returned by + * this method. + * + * @param locale The requested message Locale, or <code>null</code> for + * the system default Locale + * @param key The message key to look up + * @param arg0 The replacement for placeholder {0} in the message + * @param arg1 The replacement for placeholder {1} in the message + */ + public String getMessage(Locale locale, String key, Object arg0, Object arg1) { + return this.getMessage(locale, key, new Object[]{arg0, arg1}); + } + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. A null string result will never be returned by + * this method. + * + * @param locale The requested message Locale, or <code>null</code> for + * the system default Locale + * @param key The message key to look up + * @param arg0 The replacement for placeholder {0} in the message + * @param arg1 The replacement for placeholder {1} in the message + * @param arg2 The replacement for placeholder {2} in the message + */ + public String getMessage(Locale locale, String key, Object arg0, + Object arg1, Object arg2) { + return this.getMessage(locale, key, new Object[]{arg0, arg1, arg2}); + } + + /** + * Returns a text message after parametric replacement of the specified + * parameter placeholders. A null string result will never be returned by + * this method. + * + * @param locale The requested message Locale, or <code>null</code> for + * the system default Locale + * @param key The message key to look up + * @param arg0 The replacement for placeholder {0} in the message + * @param arg1 The replacement for placeholder {1} in the message + * @param arg2 The replacement for placeholder {2} in the message + * @param arg3 The replacement for placeholder {3} in the message + */ + public String getMessage(Locale locale, String key, Object arg0, + Object arg1, Object arg2, Object arg3) { + return this.getMessage(locale, key, + new Object[]{arg0, arg1, arg2, arg3}); + } + + /** + * Return <code>true</code> if there is a defined message for the + * specified key in the system default locale. + * + * @param key The message key to look up + */ + public boolean isPresent(String key) { + return this.isPresent(null, key); + } + + /** + * Return <code>true</code> if there is a defined message for the + * specified key in the specified Locale. + * + * @param locale The requested message Locale, or <code>null</code> for + * the system default Locale + * @param key The message key to look up + */ + public boolean isPresent(Locale locale, String key) { + String message = getMessage(locale, key); + + if (message == null) { + return false; + } else if (message.startsWith("???") && message.endsWith("???")) { + return false; // FIXME - Only valid for default implementation + } else { + return true; + } + } + + // ------------------------------------------------------ Protected Methods + + /** + * Escape any single quote characters that are included in the specified + * message string. + * + * @param string The string to be escaped + */ + protected String escape(String string) { + if (!isEscape()) { + return string; + } + + if ((string == null) || (string.indexOf('\'') < 0)) { + return string; + } + + int n = string.length(); + StringBuffer sb = new StringBuffer(n); + + for (int i = 0; i < n; i++) { + char ch = string.charAt(i); + + if (ch == '\'') { + sb.append('\''); + } + + sb.append(ch); + } + + return sb.toString(); + } + + /** + * Compute and return a key to be used in caching information by a Locale. + * <strong>NOTE</strong> - The locale key for the default Locale in our + * environment is a zero length String. + * + * @param locale The locale for which a key is desired + */ + protected String localeKey(Locale locale) { + return (locale == null) ? "" : locale.toString(); + } + + /** + * Compute and return a key to be used in caching information by Locale + * and message key. + * + * @param locale The Locale for which this format key is calculated + * @param key The message key for which this format key is calculated + */ + protected String messageKey(Locale locale, String key) { + return (localeKey(locale) + "." + key); + } + + /** + * Compute and return a key to be used in caching information by locale + * key and message key. + * + * @param localeKey The locale key for which this cache key is calculated + * @param key The message key for which this cache key is + * calculated + */ + protected String messageKey(String localeKey, String key) { + return (localeKey + "." + key); + } + + /** + * Create and return an instance of <code>MessageResources</code> for the + * created by the default <code>MessageResourcesFactory</code>. + * + * @param config Configuration parameter for this message bundle. + */ + public synchronized static MessageResources getMessageResources( + String config) { + if (defaultFactory == null) { + defaultFactory = MessageResourcesFactory.createFactory(); + } + + return defaultFactory.createResources(config); + } + + /** + * Log a message to the Writer that has been configured for our use. + * + * @param message The message to be logged + */ + public void log(String message) { + log.debug(message); + } + + /** + * Log a message and exception to the Writer that has been configured for + * our use. + * + * @param message The message to be logged + * @param throwable The exception to be logged + */ + public void log(String message, Throwable throwable) { + log.debug(message, throwable); + } +} 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); + } +} |