Save This Page
Home » struts-2.1.8.1-src » org.apache » struts2 » dispatcher » [javadoc | source]
    1   /*
    2    * $Id: Dispatcher.java 783012 2009-06-09 14:15:54Z wesw $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
   10    * with the License.  You may obtain a copy of the License at
   11    *
   12    *  http://www.apache.org/licenses/LICENSE-2.0
   13    *
   14    * Unless required by applicable law or agreed to in writing,
   15    * software distributed under the License is distributed on an
   16    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   17    * KIND, either express or implied.  See the License for the
   18    * specific language governing permissions and limitations
   19    * under the License.
   20    */
   21   
   22   package org.apache.struts2.dispatcher;
   23   
   24   import java.io.File;
   25   import java.io.IOException;
   26   import java.util.ArrayList;
   27   import java.util.Collection;
   28   import java.util.HashMap;
   29   import java.util.HashSet;
   30   import java.util.List;
   31   import java.util.Locale;
   32   import java.util.Map;
   33   import java.util.Set;
   34   import java.util.concurrent.CopyOnWriteArrayList;
   35   
   36   import javax.servlet.ServletContext;
   37   import javax.servlet.ServletException;
   38   import javax.servlet.http.HttpServletRequest;
   39   import javax.servlet.http.HttpServletResponse;
   40   
   41   import org.apache.struts2.ServletActionContext;
   42   import org.apache.struts2.StrutsConstants;
   43   import org.apache.struts2.StrutsStatics;
   44   import org.apache.struts2.StrutsException;
   45   import org.apache.struts2.config.BeanSelectionProvider;
   46   import org.apache.struts2.config.DefaultPropertiesProvider;
   47   import org.apache.struts2.config.LegacyPropertiesConfigurationProvider;
   48   import org.apache.struts2.config.StrutsXmlConfigurationProvider;
   49   import org.apache.struts2.dispatcher.mapper.ActionMapping;
   50   import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
   51   import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
   52   import org.apache.struts2.util.AttributeMap;
   53   import org.apache.struts2.util.ClassLoaderUtils;
   54   import org.apache.struts2.util.ObjectFactoryDestroyable;
   55   import org.apache.struts2.views.freemarker.FreemarkerManager;
   56   
   57   import com.opensymphony.xwork2.ActionContext;
   58   import com.opensymphony.xwork2.ActionProxy;
   59   import com.opensymphony.xwork2.ActionProxyFactory;
   60   import com.opensymphony.xwork2.ObjectFactory;
   61   import com.opensymphony.xwork2.Result;
   62   import com.opensymphony.xwork2.config.Configuration;
   63   import com.opensymphony.xwork2.config.ConfigurationException;
   64   import com.opensymphony.xwork2.config.ConfigurationManager;
   65   import com.opensymphony.xwork2.config.ConfigurationProvider;
   66   import com.opensymphony.xwork2.config.entities.InterceptorMapping;
   67   import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
   68   import com.opensymphony.xwork2.config.entities.PackageConfig;
   69   import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
   70   import com.opensymphony.xwork2.inject.Container;
   71   import com.opensymphony.xwork2.inject.ContainerBuilder;
   72   import com.opensymphony.xwork2.inject.Inject;
   73   import com.opensymphony.xwork2.interceptor.Interceptor;
   74   import com.opensymphony.xwork2.util.FileManager;
   75   import com.opensymphony.xwork2.util.LocalizedTextUtil;
   76   import com.opensymphony.xwork2.util.ValueStack;
   77   import com.opensymphony.xwork2.util.ValueStackFactory;
   78   import com.opensymphony.xwork2.util.location.LocatableProperties;
   79   import com.opensymphony.xwork2.util.location.Location;
   80   import com.opensymphony.xwork2.util.location.LocationUtils;
   81   import com.opensymphony.xwork2.util.logging.Logger;
   82   import com.opensymphony.xwork2.util.logging.LoggerFactory;
   83   import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
   84   
   85   import freemarker.template.Template;
   86   
   87   /**
   88    * A utility class the actual dispatcher delegates most of its tasks to. Each instance
   89    * of the primary dispatcher holds an instance of this dispatcher to be shared for
   90    * all requests.
   91    *
   92    * @see org.apache.struts2.dispatcher.FilterDispatcher
   93    */
   94   public class Dispatcher {
   95   
   96       /**
   97        * Provide a logging instance.
   98        */
   99       private static final Logger LOG = LoggerFactory.getLogger(Dispatcher.class);
  100   
  101       /**
  102        * Provide a thread local instance.
  103        */
  104       private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>();
  105   
  106       /**
  107        * Store list of DispatcherListeners.
  108        */
  109       private static List<DispatcherListener> dispatcherListeners =
  110           new CopyOnWriteArrayList<DispatcherListener>();
  111   
  112       /**
  113        * Store ConfigurationManager instance, set on init.
  114        */
  115       private ConfigurationManager configurationManager;
  116   
  117       /**
  118        * Store state of  StrutsConstants.STRUTS_DEVMODE setting.
  119        */
  120       private boolean devMode;
  121   
  122       /**
  123        * Store state of StrutsConstants.STRUTS_I18N_ENCODING setting.
  124        */
  125       private String defaultEncoding;
  126   
  127       /**
  128        * Store state of StrutsConstants.STRUTS_LOCALE setting.
  129        */
  130       private String defaultLocale;
  131   
  132       /**
  133        * Store state of StrutsConstants.STRUTS_MULTIPART_SAVEDIR setting.
  134        */
  135       private String multipartSaveDir;
  136   
  137       /**
  138        * Stores the value of StrutsConstants.STRUTS_MULTIPART_HANDLER setting
  139        */
  140       private String multipartHandlerName;
  141   
  142       /**
  143        * Provide list of default configuration files.
  144        */
  145       private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";
  146   
  147       /**
  148        * Store state of STRUTS_DISPATCHER_PARAMETERSWORKAROUND.
  149        * <p/>
  150        * The workaround is for WebLogic.
  151        * We try to autodect WebLogic on Dispatcher init.
  152        * The workaround can also be enabled manually.
  153        */
  154       private boolean paramsWorkaroundEnabled = false;
  155   
  156       /**
  157        * Provide the dispatcher instance for the current thread.
  158        *
  159        * @return The dispatcher instance
  160        */
  161       public static Dispatcher getInstance() {
  162           return instance.get();
  163       }
  164   
  165       /**
  166        * Store the dispatcher instance for this thread.
  167        *
  168        * @param instance The instance
  169        */
  170       public static void setInstance(Dispatcher instance) {
  171           Dispatcher.instance.set(instance);
  172       }
  173   
  174       /**
  175        * Add a dispatcher lifecycle listener.
  176        *
  177        * @param listener The listener to add
  178        */
  179       public static void addDispatcherListener(DispatcherListener listener) {
  180           dispatcherListeners.add(listener);
  181       }
  182   
  183       /**
  184        * Remove a specific dispatcher lifecycle listener.
  185        *
  186        * @param listener The listener
  187        */
  188       public static void removeDispatcherListener(DispatcherListener listener) {
  189           dispatcherListeners.remove(listener);
  190       }
  191   
  192       private ServletContext servletContext;
  193       private Map<String, String> initParams;
  194   
  195       private ValueStackFactory valueStackFactory;
  196   
  197   
  198       /**
  199        * Create the Dispatcher instance for a given ServletContext and set of initialization parameters.
  200        *
  201        * @param servletContext Our servlet context
  202        * @param initParams The set of initialization parameters
  203        */
  204       public Dispatcher(ServletContext servletContext, Map<String, String> initParams) {
  205           this.servletContext = servletContext;
  206           this.initParams = initParams;
  207       }
  208   
  209       /**
  210        * Modify state of StrutsConstants.STRUTS_DEVMODE setting.
  211        * @param mode New setting
  212        */
  213       @Inject(StrutsConstants.STRUTS_DEVMODE)
  214       public void setDevMode(String mode) {
  215           devMode = "true".equals(mode);
  216       }
  217   
  218       /**
  219        * Modify state of StrutsConstants.STRUTS_LOCALE setting.
  220        * @param val New setting
  221        */
  222       @Inject(value=StrutsConstants.STRUTS_LOCALE, required=false)
  223       public void setDefaultLocale(String val) {
  224           defaultLocale = val;
  225       }
  226   
  227       /**
  228        * Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
  229        * @param val New setting
  230        */
  231       @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
  232       public void setDefaultEncoding(String val) {
  233           defaultEncoding = val;
  234       }
  235   
  236       /**
  237        * Modify state of StrutsConstants.STRUTS_MULTIPART_SAVEDIR setting.
  238        * @param val New setting
  239        */
  240       @Inject(StrutsConstants.STRUTS_MULTIPART_SAVEDIR)
  241       public void setMultipartSaveDir(String val) {
  242           multipartSaveDir = val;
  243       }
  244   
  245       @Inject(StrutsConstants.STRUTS_MULTIPART_HANDLER)
  246       public void setMultipartHandler(String val) {
  247           multipartHandlerName = val;
  248       }
  249   
  250       @Inject
  251       public void setValueStackFactory(ValueStackFactory valueStackFactory) {
  252           this.valueStackFactory = valueStackFactory;
  253       }
  254   
  255       /**
  256        * Releases all instances bound to this dispatcher instance.
  257        */
  258       public void cleanup() {
  259   
  260       	// clean up ObjectFactory
  261           ObjectFactory objectFactory = getContainer().getInstance(ObjectFactory.class);
  262           if (objectFactory == null) {
  263               LOG.warn("Object Factory is null, something is seriously wrong, no clean up will be performed");
  264           }
  265           if (objectFactory instanceof ObjectFactoryDestroyable) {
  266               try {
  267                   ((ObjectFactoryDestroyable)objectFactory).destroy();
  268               }
  269               catch(Exception e) {
  270                   // catch any exception that may occured during destroy() and log it
  271                   LOG.error("exception occurred while destroying ObjectFactory ["+objectFactory+"]", e);
  272               }
  273           }
  274   
  275           // clean up Dispatcher itself for this thread
  276           instance.set(null);
  277   
  278           // clean up DispatcherListeners
  279           if (!dispatcherListeners.isEmpty()) {
  280               for (DispatcherListener l : dispatcherListeners) {
  281                   l.dispatcherDestroyed(this);
  282               }
  283           }
  284   
  285           // clean up all interceptors by calling their destroy() method
  286           Set<Interceptor> interceptors = new HashSet<Interceptor>();
  287           Collection<PackageConfig> packageConfigs = configurationManager.getConfiguration().getPackageConfigs().values();
  288           for (PackageConfig packageConfig : packageConfigs) {
  289               for (Object config : packageConfig.getAllInterceptorConfigs().values()) {
  290                   if (config instanceof InterceptorStackConfig) {
  291                       for (InterceptorMapping interceptorMapping : ((InterceptorStackConfig) config).getInterceptors()) {
  292                   	    interceptors.add(interceptorMapping.getInterceptor());
  293                       }
  294                   }
  295               }
  296           }
  297           for (Interceptor interceptor : interceptors) {
  298           	interceptor.destroy();
  299           }
  300   
  301           //cleanup action context
  302           ActionContext.setContext(null);
  303   
  304           // clean up configuration
  305       	configurationManager.destroyConfiguration();
  306       	configurationManager = null;
  307       }
  308   
  309       private void init_DefaultProperties() {
  310           configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
  311       }
  312       
  313       private void init_LegacyStrutsProperties() {
  314           configurationManager.addConfigurationProvider(new LegacyPropertiesConfigurationProvider());
  315       }
  316   
  317       private void init_TraditionalXmlConfigurations() {
  318           String configPaths = initParams.get("config");
  319           if (configPaths == null) {
  320               configPaths = DEFAULT_CONFIGURATION_PATHS;
  321           }
  322           String[] files = configPaths.split("\\s*[,]\\s*");
  323           for (String file : files) {
  324               if (file.endsWith(".xml")) {
  325                   if ("xwork.xml".equals(file)) {
  326                       configurationManager.addConfigurationProvider(new XmlConfigurationProvider(file, false));
  327                   } else {
  328                       configurationManager.addConfigurationProvider(new StrutsXmlConfigurationProvider(file, false, servletContext));
  329                   }
  330               } else {
  331                   throw new IllegalArgumentException("Invalid configuration file name");
  332               }
  333           }
  334       }
  335   
  336       private void init_CustomConfigurationProviders() {
  337           String configProvs = initParams.get("configProviders");
  338           if (configProvs != null) {
  339               String[] classes = configProvs.split("\\s*[,]\\s*");
  340               for (String cname : classes) {
  341                   try {
  342                       Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());
  343                       ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance();
  344                       configurationManager.addConfigurationProvider(prov);
  345                   } catch (InstantiationException e) {
  346                       throw new ConfigurationException("Unable to instantiate provider: "+cname, e);
  347                   } catch (IllegalAccessException e) {
  348                       throw new ConfigurationException("Unable to access provider: "+cname, e);
  349                   } catch (ClassNotFoundException e) {
  350                       throw new ConfigurationException("Unable to locate provider class: "+cname, e);
  351                   }
  352               }
  353           }
  354       }
  355   
  356       private void init_FilterInitParameters() {
  357           configurationManager.addConfigurationProvider(new ConfigurationProvider() {
  358               public void destroy() {}
  359               public void init(Configuration configuration) throws ConfigurationException {}
  360               public void loadPackages() throws ConfigurationException {}
  361               public boolean needsReload() { return false; }
  362   
  363               public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
  364                   props.putAll(initParams);
  365               }
  366           });
  367       }
  368   
  369       private void init_AliasStandardObjects() {
  370           configurationManager.addConfigurationProvider(new BeanSelectionProvider());
  371       }
  372   
  373       private Container init_PreloadConfiguration() {
  374           Configuration config = configurationManager.getConfiguration();
  375           Container container = config.getContainer();
  376   
  377           boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
  378           LocalizedTextUtil.setReloadBundles(reloadi18n);
  379   
  380           return container;
  381       }
  382   
  383       private void init_CheckConfigurationReloading(Container container) {
  384           FileManager.setReloadingConfigs("true".equals(container.getInstance(String.class,
  385                   StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD)));
  386       }
  387   
  388       private void init_CheckWebLogicWorkaround(Container container) {
  389           // test whether param-access workaround needs to be enabled
  390           if (servletContext != null && servletContext.getServerInfo() != null
  391                   && servletContext.getServerInfo().indexOf("WebLogic") >= 0) {
  392               LOG.info("WebLogic server detected. Enabling Struts parameter access work-around.");
  393               paramsWorkaroundEnabled = true;
  394           } else {
  395               paramsWorkaroundEnabled = "true".equals(container.getInstance(String.class,
  396                       StrutsConstants.STRUTS_DISPATCHER_PARAMETERSWORKAROUND));
  397           }
  398       }
  399   
  400       /**
  401        * Load configurations, including both XML and zero-configuration strategies,
  402        * and update optional settings, including whether to reload configurations and resource files.
  403        */
  404       public void init() {
  405   
  406       	if (configurationManager == null) {
  407       		configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
  408       	}
  409   
  410           try {
  411               init_DefaultProperties(); // [1]
  412               init_TraditionalXmlConfigurations(); // [2]
  413               init_LegacyStrutsProperties(); // [3]
  414               init_CustomConfigurationProviders(); // [5]
  415               init_FilterInitParameters() ; // [6]
  416               init_AliasStandardObjects() ; // [7]
  417   
  418               Container container = init_PreloadConfiguration();
  419               container.inject(this);
  420               init_CheckConfigurationReloading(container);
  421               init_CheckWebLogicWorkaround(container);
  422   
  423               if (!dispatcherListeners.isEmpty()) {
  424                   for (DispatcherListener l : dispatcherListeners) {
  425                       l.dispatcherInitialized(this);
  426                   }
  427               }
  428           } catch (Exception ex) {
  429               if (LOG.isErrorEnabled())
  430                   LOG.error("Dispatcher initialization failed", ex);
  431               throw new StrutsException(ex);
  432           }
  433       }
  434   
  435       /**
  436        * Load Action class for mapping and invoke the appropriate Action method, or go directly to the Result.
  437        * <p/>
  438        * This method first creates the action context from the given parameters,
  439        * and then loads an <tt>ActionProxy</tt> from the given action name and namespace.
  440        * After that, the Action method is executed and output channels through the response object.
  441        * Actions not found are sent back to the user via the {@link Dispatcher#sendError} method,
  442        * using the 404 return code.
  443        * All other errors are reported by throwing a ServletException.
  444        *
  445        * @param request  the HttpServletRequest object
  446        * @param response the HttpServletResponse object
  447        * @param mapping  the action mapping object
  448        * @throws ServletException when an unknown error occurs (not a 404, but typically something that
  449        *                          would end up as a 5xx by the servlet container)
  450        * @param context Our ServletContext object
  451        */
  452       public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
  453                                 ActionMapping mapping) throws ServletException {
  454   
  455           Map<String, Object> extraContext = createContextMap(request, response, mapping, context);
  456   
  457           // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
  458           ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
  459           boolean nullStack = stack == null;
  460           if (nullStack) {
  461               ActionContext ctx = ActionContext.getContext();
  462               if (ctx != null) {
  463                   stack = ctx.getValueStack();
  464               }
  465           }
  466           if (stack != null) {
  467               extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
  468           }
  469   
  470           String timerKey = "Handling request from Dispatcher";
  471           try {
  472               UtilTimerStack.push(timerKey);
  473               String namespace = mapping.getNamespace();
  474               String name = mapping.getName();
  475               String method = mapping.getMethod();
  476   
  477               Configuration config = configurationManager.getConfiguration();
  478               ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
  479                       namespace, name, method, extraContext, true, false);
  480   
  481               request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
  482   
  483               // if the ActionMapping says to go straight to a result, do it!
  484               if (mapping.getResult() != null) {
  485                   Result result = mapping.getResult();
  486                   result.execute(proxy.getInvocation());
  487               } else {
  488                   proxy.execute();
  489               }
  490   
  491               // If there was a previous value stack then set it back onto the request
  492               if (!nullStack) {
  493                   request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
  494               }
  495           } catch (ConfigurationException e) {
  496           	// WW-2874 Only log error if in devMode
  497           	if(devMode) {
  498           		LOG.error("Could not find action or result", e);
  499           	}
  500           	else {
  501           		LOG.warn("Could not find action or result", e);
  502           	}
  503               sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
  504           } catch (Exception e) {
  505               sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
  506           } finally {
  507               UtilTimerStack.pop(timerKey);
  508           }
  509       }
  510   
  511       /**
  512        * Create a context map containing all the wrapped request objects
  513        *
  514        * @param request The servlet request
  515        * @param response The servlet response
  516        * @param mapping The action mapping
  517        * @param context The servlet context
  518        * @return A map of context objects
  519        */
  520       public Map<String,Object> createContextMap(HttpServletRequest request, HttpServletResponse response,
  521               ActionMapping mapping, ServletContext context) {
  522   
  523           // request map wrapping the http request objects
  524           Map requestMap = new RequestMap(request);
  525   
  526           // parameters map wrapping the http parameters.  ActionMapping parameters are now handled and applied separately
  527           Map params = new HashMap(request.getParameterMap());
  528   
  529           // session map wrapping the http session
  530           Map session = new SessionMap(request);
  531   
  532           // application map wrapping the ServletContext
  533           Map application = new ApplicationMap(context);
  534   
  535           Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context);
  536   
  537           if (mapping != null) {
  538               extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
  539           }
  540           return extraContext;
  541       }
  542   
  543       /**
  544        * Merge all application and servlet attributes into a single <tt>HashMap</tt> to represent the entire
  545        * <tt>Action</tt> context.
  546        *
  547        * @param requestMap     a Map of all request attributes.
  548        * @param parameterMap   a Map of all request parameters.
  549        * @param sessionMap     a Map of all session attributes.
  550        * @param applicationMap a Map of all servlet context attributes.
  551        * @param request        the HttpServletRequest object.
  552        * @param response       the HttpServletResponse object.
  553        * @param servletContext the ServletContextmapping object.
  554        * @return a HashMap representing the <tt>Action</tt> context.
  555        */
  556       public HashMap<String,Object> createContextMap(Map requestMap,
  557                                       Map parameterMap,
  558                                       Map sessionMap,
  559                                       Map applicationMap,
  560                                       HttpServletRequest request,
  561                                       HttpServletResponse response,
  562                                       ServletContext servletContext) {
  563           HashMap<String,Object> extraContext = new HashMap<String,Object>();
  564           extraContext.put(ActionContext.PARAMETERS, new HashMap(parameterMap));
  565           extraContext.put(ActionContext.SESSION, sessionMap);
  566           extraContext.put(ActionContext.APPLICATION, applicationMap);
  567   
  568           Locale locale;
  569           if (defaultLocale != null) {
  570               locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
  571           } else {
  572               locale = request.getLocale();
  573           }
  574   
  575           extraContext.put(ActionContext.LOCALE, locale);
  576           //extraContext.put(ActionContext.DEV_MODE, Boolean.valueOf(devMode));
  577   
  578           extraContext.put(StrutsStatics.HTTP_REQUEST, request);
  579           extraContext.put(StrutsStatics.HTTP_RESPONSE, response);
  580           extraContext.put(StrutsStatics.SERVLET_CONTEXT, servletContext);
  581   
  582           // helpers to get access to request/session/application scope
  583           extraContext.put("request", requestMap);
  584           extraContext.put("session", sessionMap);
  585           extraContext.put("application", applicationMap);
  586           extraContext.put("parameters", parameterMap);
  587   
  588           AttributeMap attrMap = new AttributeMap(extraContext);
  589           extraContext.put("attr", attrMap);
  590   
  591           return extraContext;
  592       }
  593   
  594       /**
  595        * Return the path to save uploaded files to (this is configurable).
  596        *
  597        * @return the path to save uploaded files to
  598        * @param servletContext Our ServletContext
  599        */
  600       private String getSaveDir(ServletContext servletContext) {
  601           String saveDir = multipartSaveDir.trim();
  602   
  603           if (saveDir.equals("")) {
  604               File tempdir = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
  605               LOG.info("Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir");
  606   
  607               if (tempdir != null) {
  608                   saveDir = tempdir.toString();
  609                   setMultipartSaveDir(saveDir);
  610               }
  611           } else {
  612               File multipartSaveDir = new File(saveDir);
  613   
  614               if (!multipartSaveDir.exists()) {
  615                   if (multipartSaveDir.mkdir() == false) {
  616                       String logMessage;
  617           	    try {
  618                           logMessage = "Could not find create multipart save directory '"+multipartSaveDir.getCanonicalPath()+"'.";
  619           	    } catch (IOException e) {
  620                           logMessage = "Could not find create multipart save directory '"+multipartSaveDir.toString()+"'.";
  621           	    }
  622           	    if(devMode) {
  623                           LOG.error(logMessage);
  624           	    }
  625           	    else {
  626                           LOG.warn(logMessage);
  627           	    }
  628                   }
  629               }
  630           }
  631   
  632           if (LOG.isDebugEnabled()) {
  633               LOG.debug("saveDir=" + saveDir);
  634           }
  635   
  636           return saveDir;
  637       }
  638   
  639       /**
  640        * Prepare a request, including setting the encoding and locale.
  641        *
  642        * @param request The request
  643        * @param response The response
  644        */
  645       public void prepare(HttpServletRequest request, HttpServletResponse response) {
  646           String encoding = null;
  647           if (defaultEncoding != null) {
  648               encoding = defaultEncoding;
  649           }
  650   
  651           Locale locale = null;
  652           if (defaultLocale != null) {
  653               locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
  654           }
  655   
  656           if (encoding != null) {
  657               try {
  658                   request.setCharacterEncoding(encoding);
  659               } catch (Exception e) {
  660                   LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
  661               }
  662           }
  663   
  664           if (locale != null) {
  665               response.setLocale(locale);
  666           }
  667   
  668           if (paramsWorkaroundEnabled) {
  669               request.getParameter("foo"); // simply read any parameter (existing or not) to "prime" the request
  670           }
  671       }
  672   
  673       /**
  674        * Wrap and return the given request or return the original request object.
  675        * </p>
  676        * This method transparently handles multipart data as a wrapped class around the given request.
  677        * Override this method to handle multipart requests in a special way or to handle other types of requests.
  678        * Note, {@link org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper} is
  679        * flexible - look first to that object before overriding this method to handle multipart data.
  680        *
  681        * @param request the HttpServletRequest object.
  682        * @param servletContext Our ServletContext object
  683        * @return a wrapped request or original request.
  684        * @see org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper
  685        * @throws java.io.IOException on any error.
  686        */
  687       public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext) throws IOException {
  688           // don't wrap more than once
  689           if (request instanceof StrutsRequestWrapper) {
  690               return request;
  691           }
  692   
  693           String content_type = request.getContentType();
  694           if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
  695               MultiPartRequest mpr = null;
  696               //check for alternate implementations of MultiPartRequest
  697               Set<String> multiNames = getContainer().getInstanceNames(MultiPartRequest.class);
  698               if (multiNames != null) {
  699                   for (String multiName : multiNames) {
  700                       if (multiName.equals(multipartHandlerName)) {
  701                           mpr = getContainer().getInstance(MultiPartRequest.class, multiName);
  702                       }
  703                   }
  704               }
  705               if (mpr == null ) {
  706                   mpr = getContainer().getInstance(MultiPartRequest.class);
  707               }
  708               request = new MultiPartRequestWrapper(mpr, request, getSaveDir(servletContext));
  709           } else {
  710               request = new StrutsRequestWrapper(request);
  711           }
  712   
  713           return request;
  714       }
  715   
  716       /**
  717        * Send an HTTP error response code.
  718        *
  719        * @param request  the HttpServletRequest object.
  720        * @param response the HttpServletResponse object.
  721        * @param code     the HttpServletResponse error code (see {@link javax.servlet.http.HttpServletResponse} for possible error codes).
  722        * @param e        the Exception that is reported.
  723        * @param ctx      the ServletContext object.
  724        */
  725       public void sendError(HttpServletRequest request, HttpServletResponse response,
  726               ServletContext ctx, int code, Exception e) {
  727           if (devMode) {
  728               response.setContentType("text/html");
  729   
  730               try {
  731                   FreemarkerManager mgr = getContainer().getInstance(FreemarkerManager.class);
  732   
  733                   freemarker.template.Configuration config = mgr.getConfiguration(ctx);
  734                   Template template = config.getTemplate("/org/apache/struts2/dispatcher/error.ftl");
  735   
  736                   List<Throwable> chain = new ArrayList<Throwable>();
  737                   Throwable cur = e;
  738                   chain.add(cur);
  739                   while ((cur = cur.getCause()) != null) {
  740                       chain.add(cur);
  741                   }
  742   
  743                   HashMap<String,Object> data = new HashMap<String,Object>();
  744                   data.put("exception", e);
  745                   data.put("unknown", Location.UNKNOWN);
  746                   data.put("chain", chain);
  747                   data.put("locator", new Locator());
  748                   template.process(data, response.getWriter());
  749                   response.getWriter().close();
  750               } catch (Exception exp) {
  751                   try {
  752                       response.sendError(code, "Unable to show problem report: " + exp);
  753                   } catch (IOException ex) {
  754                       // we're already sending an error, not much else we can do if more stuff breaks
  755                   }
  756               }
  757           } else {
  758               try {
  759                   // WW-1977: Only put errors in the request when code is a 500 error
  760                   if (code == HttpServletResponse.SC_INTERNAL_SERVER_ERROR) {
  761                       // send a http error response to use the servlet defined error handler
  762                       // make the exception availible to the web.xml defined error page
  763                       request.setAttribute("javax.servlet.error.exception", e);
  764   
  765                       // for compatibility
  766                       request.setAttribute("javax.servlet.jsp.jspException", e);
  767                   }
  768   
  769                   // send the error response
  770                   response.sendError(code, e.getMessage());
  771               } catch (IOException e1) {
  772                   // we're already sending an error, not much else we can do if more stuff breaks
  773               }
  774           }
  775       }
  776   
  777       
  778   
  779       /**
  780        * Provide an accessor class for static XWork utility.
  781        */
  782       public static class Locator {
  783           public Location getLocation(Object obj) {
  784               Location loc = LocationUtils.getLocation(obj);
  785               if (loc == null) {
  786                   return Location.UNKNOWN;
  787               }
  788               return loc;
  789           }
  790       }
  791   
  792       /**
  793        * Expose the ConfigurationManager instance.
  794        *
  795        * @return The instance
  796        */
  797       public ConfigurationManager getConfigurationManager() {
  798           return configurationManager;
  799       }
  800   
  801       /**
  802        * Modify the ConfigurationManager instance
  803        *
  804        * @param mgr The configuration manager
  805        */
  806       public void setConfigurationManager(ConfigurationManager mgr) {
  807           this.configurationManager = mgr;
  808       }
  809   
  810       /**
  811        * Expose the dependency injection container.
  812        * @return Our dependency injection container
  813        */
  814       public Container getContainer() {
  815           ConfigurationManager mgr = getConfigurationManager();
  816           if (mgr == null) {
  817               throw new IllegalStateException("The configuration manager shouldn't be null");
  818           } else {
  819               Configuration config = mgr.getConfiguration();
  820               if (config == null) {
  821                   throw new IllegalStateException("Unable to load configuration");
  822               } else {
  823                   return config.getContainer();
  824               }
  825           }
  826       }
  827   }

Save This Page
Home » struts-2.1.8.1-src » org.apache » struts2 » dispatcher » [javadoc | source]