A utility class the actual dispatcher delegates most of its tasks to. Each instance
of the primary dispatcher holds an instance of this dispatcher to be shared for
all requests.
| Method from org.apache.struts2.dispatcher.Dispatcher Detail: |
public static void addDispatcherListener(DispatcherListener listener) {
dispatcherListeners.add(listener);
}
Add a dispatcher lifecycle listener. |
public void cleanup() {
// clean up ObjectFactory
ObjectFactory objectFactory = getContainer().getInstance(ObjectFactory.class);
if (objectFactory == null) {
LOG.warn("Object Factory is null, something is seriously wrong, no clean up will be performed");
}
if (objectFactory instanceof ObjectFactoryDestroyable) {
try {
((ObjectFactoryDestroyable)objectFactory).destroy();
}
catch(Exception e) {
// catch any exception that may occured during destroy() and log it
LOG.error("exception occurred while destroying ObjectFactory ["+objectFactory+"]", e);
}
}
// clean up Dispatcher itself for this thread
instance.set(null);
// clean up DispatcherListeners
if (!dispatcherListeners.isEmpty()) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherDestroyed(this);
}
}
// clean up all interceptors by calling their destroy() method
Set< Interceptor > interceptors = new HashSet< Interceptor >();
Collection< PackageConfig > packageConfigs = configurationManager.getConfiguration().getPackageConfigs().values();
for (PackageConfig packageConfig : packageConfigs) {
for (Object config : packageConfig.getAllInterceptorConfigs().values()) {
if (config instanceof InterceptorStackConfig) {
for (InterceptorMapping interceptorMapping : ((InterceptorStackConfig) config).getInterceptors()) {
interceptors.add(interceptorMapping.getInterceptor());
}
}
}
}
for (Interceptor interceptor : interceptors) {
interceptor.destroy();
}
//cleanup action context
ActionContext.setContext(null);
// clean up configuration
configurationManager.destroyConfiguration();
configurationManager = null;
}
Releases all instances bound to this dispatcher instance. |
public Map<String, Object> createContextMap(HttpServletRequest request,
HttpServletResponse response,
ActionMapping mapping,
ServletContext context) {
// request map wrapping the http request objects
Map requestMap = new RequestMap(request);
// parameters map wrapping the http parameters. ActionMapping parameters are now handled and applied separately
Map params = new HashMap(request.getParameterMap());
// session map wrapping the http session
Map session = new SessionMap(request);
// application map wrapping the ServletContext
Map application = new ApplicationMap(context);
Map< String,Object > extraContext = createContextMap(requestMap, params, session, application, request, response, context);
if (mapping != null) {
extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
}
return extraContext;
}
Create a context map containing all the wrapped request objects |
public HashMap<String, Object> createContextMap(Map requestMap,
Map parameterMap,
Map sessionMap,
Map applicationMap,
HttpServletRequest request,
HttpServletResponse response,
ServletContext servletContext) {
HashMap< String,Object > extraContext = new HashMap< String,Object >();
extraContext.put(ActionContext.PARAMETERS, new HashMap(parameterMap));
extraContext.put(ActionContext.SESSION, sessionMap);
extraContext.put(ActionContext.APPLICATION, applicationMap);
Locale locale;
if (defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
} else {
locale = request.getLocale();
}
extraContext.put(ActionContext.LOCALE, locale);
//extraContext.put(ActionContext.DEV_MODE, Boolean.valueOf(devMode));
extraContext.put(StrutsStatics.HTTP_REQUEST, request);
extraContext.put(StrutsStatics.HTTP_RESPONSE, response);
extraContext.put(StrutsStatics.SERVLET_CONTEXT, servletContext);
// helpers to get access to request/session/application scope
extraContext.put("request", requestMap);
extraContext.put("session", sessionMap);
extraContext.put("application", applicationMap);
extraContext.put("parameters", parameterMap);
AttributeMap attrMap = new AttributeMap(extraContext);
extraContext.put("attr", attrMap);
return extraContext;
}
Merge all application and servlet attributes into a single HashMap to represent the entire
Action context. |
public ConfigurationManager getConfigurationManager() {
return configurationManager;
}
Expose the ConfigurationManager instance. |
public Container getContainer() {
ConfigurationManager mgr = getConfigurationManager();
if (mgr == null) {
throw new IllegalStateException("The configuration manager shouldn't be null");
} else {
Configuration config = mgr.getConfiguration();
if (config == null) {
throw new IllegalStateException("Unable to load configuration");
} else {
return config.getContainer();
}
}
}
Expose the dependency injection container. |
public static Dispatcher getInstance() {
return instance.get();
}
Provide the dispatcher instance for the current thread. |
public void init() {
if (configurationManager == null) {
configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
try {
init_DefaultProperties(); // [1]
init_TraditionalXmlConfigurations(); // [2]
init_LegacyStrutsProperties(); // [3]
init_CustomConfigurationProviders(); // [5]
init_FilterInitParameters() ; // [6]
init_AliasStandardObjects() ; // [7]
Container container = init_PreloadConfiguration();
container.inject(this);
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if (!dispatcherListeners.isEmpty()) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherInitialized(this);
}
}
} catch (Exception ex) {
if (LOG.isErrorEnabled())
LOG.error("Dispatcher initialization failed", ex);
throw new StrutsException(ex);
}
}
Load configurations, including both XML and zero-configuration strategies,
and update optional settings, including whether to reload configurations and resource files. |
public void prepare(HttpServletRequest request,
HttpServletResponse response) {
String encoding = null;
if (defaultEncoding != null) {
encoding = defaultEncoding;
}
Locale locale = null;
if (defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
}
if (encoding != null) {
try {
request.setCharacterEncoding(encoding);
} catch (Exception e) {
LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
}
}
if (locale != null) {
response.setLocale(locale);
}
if (paramsWorkaroundEnabled) {
request.getParameter("foo"); // simply read any parameter (existing or not) to "prime" the request
}
}
Prepare a request, including setting the encoding and locale. |
public static void removeDispatcherListener(DispatcherListener listener) {
dispatcherListeners.remove(listener);
}
Remove a specific dispatcher lifecycle listener. |
public void sendError(HttpServletRequest request,
HttpServletResponse response,
ServletContext ctx,
int code,
Exception e) {
if (devMode) {
response.setContentType("text/html");
try {
FreemarkerManager mgr = getContainer().getInstance(FreemarkerManager.class);
freemarker.template.Configuration config = mgr.getConfiguration(ctx);
Template template = config.getTemplate("/org/apache/struts2/dispatcher/error.ftl");
List< Throwable > chain = new ArrayList< Throwable >();
Throwable cur = e;
chain.add(cur);
while ((cur = cur.getCause()) != null) {
chain.add(cur);
}
HashMap< String,Object > data = new HashMap< String,Object >();
data.put("exception", e);
data.put("unknown", Location.UNKNOWN);
data.put("chain", chain);
data.put("locator", new Locator());
template.process(data, response.getWriter());
response.getWriter().close();
} catch (Exception exp) {
try {
response.sendError(code, "Unable to show problem report: " + exp);
} catch (IOException ex) {
// we're already sending an error, not much else we can do if more stuff breaks
}
}
} else {
try {
// WW-1977: Only put errors in the request when code is a 500 error
if (code == HttpServletResponse.SC_INTERNAL_SERVER_ERROR) {
// send a http error response to use the servlet defined error handler
// make the exception availible to the web.xml defined error page
request.setAttribute("javax.servlet.error.exception", e);
// for compatibility
request.setAttribute("javax.servlet.jsp.jspException", e);
}
// send the error response
response.sendError(code, e.getMessage());
} catch (IOException e1) {
// we're already sending an error, not much else we can do if more stuff breaks
}
}
}
Send an HTTP error response code. |
public void serviceAction(HttpServletRequest request,
HttpServletResponse response,
ServletContext context,
ActionMapping mapping) throws ServletException {
Map< String, Object > extraContext = createContextMap(request, response, mapping, context);
// If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
boolean nullStack = stack == null;
if (nullStack) {
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
stack = ctx.getValueStack();
}
}
if (stack != null) {
extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
}
String timerKey = "Handling request from Dispatcher";
try {
UtilTimerStack.push(timerKey);
String namespace = mapping.getNamespace();
String name = mapping.getName();
String method = mapping.getMethod();
Configuration config = configurationManager.getConfiguration();
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
// if the ActionMapping says to go straight to a result, do it!
if (mapping.getResult() != null) {
Result result = mapping.getResult();
result.execute(proxy.getInvocation());
} else {
proxy.execute();
}
// If there was a previous value stack then set it back onto the request
if (!nullStack) {
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
}
} catch (ConfigurationException e) {
// WW-2874 Only log error if in devMode
if(devMode) {
LOG.error("Could not find action or result", e);
}
else {
LOG.warn("Could not find action or result", e);
}
sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
} catch (Exception e) {
sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
} finally {
UtilTimerStack.pop(timerKey);
}
}
Load Action class for mapping and invoke the appropriate Action method, or go directly to the Result.
This method first creates the action context from the given parameters,
and then loads an ActionProxy from the given action name and namespace.
After that, the Action method is executed and output channels through the response object.
Actions not found are sent back to the user via the Dispatcher#sendError method,
using the 404 return code.
All other errors are reported by throwing a ServletException. |
public void setConfigurationManager(ConfigurationManager mgr) {
this.configurationManager = mgr;
}
Modify the ConfigurationManager instance |
public void setDefaultEncoding(String val) {
defaultEncoding = val;
}
Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting. |
public void setDefaultLocale(String val) {
defaultLocale = val;
}
Modify state of StrutsConstants.STRUTS_LOCALE setting. |
public void setDevMode(String mode) {
devMode = "true".equals(mode);
}
Modify state of StrutsConstants.STRUTS_DEVMODE setting. |
public static void setInstance(Dispatcher instance) {
Dispatcher.instance.set(instance);
}
Store the dispatcher instance for this thread. |
public void setMultipartHandler(String val) {
multipartHandlerName = val;
}
|
public void setMultipartSaveDir(String val) {
multipartSaveDir = val;
}
Modify state of StrutsConstants.STRUTS_MULTIPART_SAVEDIR setting. |
public void setValueStackFactory(ValueStackFactory valueStackFactory) {
this.valueStackFactory = valueStackFactory;
}
|
public HttpServletRequest wrapRequest(HttpServletRequest request,
ServletContext servletContext) throws IOException {
// don't wrap more than once
if (request instanceof StrutsRequestWrapper) {
return request;
}
String content_type = request.getContentType();
if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
MultiPartRequest mpr = null;
//check for alternate implementations of MultiPartRequest
Set< String > multiNames = getContainer().getInstanceNames(MultiPartRequest.class);
if (multiNames != null) {
for (String multiName : multiNames) {
if (multiName.equals(multipartHandlerName)) {
mpr = getContainer().getInstance(MultiPartRequest.class, multiName);
}
}
}
if (mpr == null ) {
mpr = getContainer().getInstance(MultiPartRequest.class);
}
request = new MultiPartRequestWrapper(mpr, request, getSaveDir(servletContext));
} else {
request = new StrutsRequestWrapper(request);
}
return request;
}
Wrap and return the given request or return the original request object.
This method transparently handles multipart data as a wrapped class around the given request.
Override this method to handle multipart requests in a special way or to handle other types of requests.
Note, org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper is
flexible - look first to that object before overriding this method to handle multipart data. |