com.opensymphony.webwork.dispatcher
public class: FilterDispatcher [javadoc |
source]
java.lang.Object
com.opensymphony.webwork.dispatcher.FilterDispatcher
All Implemented Interfaces:
Filter, WebWorkStatics
Direct Known Subclasses:
FilterDispatcherCompatWeblogic61, PicoFilterDispatcher
Master filter for WebWork that handles four distinct responsibilities:
- Executing actions
- Cleaning up the ActionContext (see note)
- Serving static content
- Kicking off XWork's IoC for the request lifecycle
IMPORTANT: this filter must be mapped to all requests. Unless you know exactly what you are doing, always
map to this URL pattern: /*
Executing actions
This filter executes actions by consulting the
ActionMapper and determining if the requested URL should
invoke an action. If the mapper indicates it should,
the rest of the filter chain is stopped and the action is
invoked. This is important, as it means that filters like the SiteMesh filter must be placed
before this
filter or they will not be able to decorate the output of actions.
Cleaning up the ActionContext
This filter will also automatically clean up the
ActionContext for you, ensuring that no memory leaks
take place. However, this can sometimes cause problems integrating with other products like SiteMesh. See
ActionContextCleanUp for more information on how to deal with this.
Serving static content
This filter also serves common static content needed when using various parts of WebWork, such as JavaScript
files, CSS files, etc. It works by looking for requests to /webwork/*, and then mapping the value after "/webwork/"
to common packages in WebWork and, optionally, in your class path. By default, the following packages are
automatically searched:
- com.opensymphony.webwork.static
- template
This means that you can simply request /webwork/xhtml/styles.css and the XHTML UI theme's default stylesheet
will be returned. Likewise, many of the AJAX UI components require various JavaScript files, which are found in the
com.opensymphony.webwork.static package. If you wish to add additional packages to be searched, you can add a comma
separated (space, tab and new line will do as well) list in the filter init parameter named "packages".
Be
careful, however, to expose any packages that may have sensitive information, such as properties file with
database access credentials.
Kicking off XWork's IoC for the request lifecycle
This filter also kicks off the XWork IoC request scope, provided that you are using XWork's IoC. All you have to
do to get started with XWork's IoC is add a components.xml file to WEB-INF/classes and properly set up the
com.opensymphony.webwork.lifecycle.LifecycleListener in web.xml. See the IoC docs for more information.
| Field Summary |
|---|
| protected FilterConfig | filterConfig | |
| protected String[] | pathPrefixes | |
| Method from com.opensymphony.webwork.dispatcher.FilterDispatcher Summary: |
|---|
|
afterActionInvocation, beforeActionInvocation, checkUrl, copy, createComponentManager, destroy, doFilter, findInputStream, findStaticResource, getFilterConfig, getServletContext, init, parse, setupContainer |
| Method from com.opensymphony.webwork.dispatcher.FilterDispatcher Detail: |
protected void afterActionInvocation(HttpServletRequest request,
Object o,
Object o1) {
// nothing by default, but a good hook for scoped ioc integration
}
|
protected Object beforeActionInvocation(HttpServletRequest request,
ServletContext servletContext) {
// nothing by default, but a good hook for scoped ioc integration
return null;
}
|
protected boolean checkUrl(URL url,
String rawResourcePath) {
// ignore folder resources - they provide streams too ! dunno why :)
if (url.getPath().endsWith("/")) {
return false;
}
// check for parent path access
// NOTE : most servlet containers shoudl resolve .. chars in the request url anyway
if (url.toExternalForm().indexOf(rawResourcePath) == -1) {
return false;
}
return true;
}
handle .. chars here and other URL hacks |
protected void copy(InputStream input,
OutputStream output) throws IOException {
final byte[] buffer = new byte[4096];
int n;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
// some app server eg WebSphere6 doesn't like it if didn't flush (WW-1384)
output.flush();
}
|
protected DefaultComponentManager createComponentManager() {
return new DefaultComponentManager();
}
Returns a new DefaultComponentManager instance. This method is useful for developers wishing to subclass
this class and provide a different implementation of DefaultComponentManager. |
public void destroy() {
DispatcherUtils du = DispatcherUtils.getInstance(); // should not be null as it is initialized in init(FilterConfig)
if (du == null) {
LOG.warn("something is seriously wrong, DispatcherUtil is not initialized (null) ");
}
du.cleanup();
}
|
public void doFilter(ServletRequest req,
ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
ServletContext servletContext = filterConfig.getServletContext();
// prepare the request no matter what - this ensures that the proper character encoding
// is used before invoking the mapper (see WW-9127)
DispatcherUtils du = DispatcherUtils.getInstance();
du.prepare(request, response);
try {
// Wrap request first, just in case it is multipart/form-data
// parameters might not be accessible through before encoding (ww-1278)
request = du.wrapRequest(request, servletContext);
} catch (IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
LOG.error(message, e);
throw new ServletException(message, e);
}
ActionMapper mapper = ActionMapperFactory.getMapper();
ActionMapping mapping = mapper.getMapping(request);
if (mapping == null) {
// there is no action in this request, should we look for a static resource?
String resourcePath = RequestUtils.getServletPath(request);
if ("".equals(resourcePath) && null != request.getPathInfo()) {
resourcePath = request.getPathInfo();
}
if ("true".equals(Configuration.get(WebWorkConstants.WEBWORK_SERVE_STATIC_CONTENT))
&& resourcePath.startsWith("/webwork")) {
String name = resourcePath.substring("/webwork".length());
findStaticResource(name, response);
} else {
// this is a normal request, let it pass through
chain.doFilter(request, response);
}
// WW did its job here
return;
}
Object o = null;
try {
setupContainer(request);
o = beforeActionInvocation(request, servletContext);
du.serviceAction(request, response, servletContext, mapping);
} finally {
afterActionInvocation(request, servletContext, o);
ActionContextCleanUp.cleanUp(req);
}
}
|
protected InputStream findInputStream(String name,
String packagePrefix) throws IOException {
String resourcePath;
if (packagePrefix.endsWith("/") && name.startsWith("/")) {
resourcePath = packagePrefix + name.substring(1);
} else {
resourcePath = packagePrefix + name;
}
String enc = (String) Configuration.get(WebWorkConstants.WEBWORK_I18N_ENCODING);
resourcePath = URLDecoder.decode(resourcePath, enc);
return ClassLoaderUtil.getResourceAsStream(resourcePath, getClass());
}
|
protected void findStaticResource(String name,
HttpServletResponse response) throws IOException {
if (!name.endsWith(".class")) {
for (int i = 0; i < pathPrefixes.length; i++) {
InputStream is = findInputStream(name, pathPrefixes[i]);
if (is != null) {
// set the content-type header
String contentType = getContentType(name);
if (contentType != null) {
response.setContentType(contentType);
}
// set heading information for caching static content
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
response.setHeader("Date",df.format(cal.getTime())+" GMT");
cal.add(Calendar.DAY_OF_MONTH,1);
response.setHeader("Expires",df.format(cal.getTime())+" GMT");
response.setHeader("Retry-After",df.format(cal.getTime())+" GMT");
response.setHeader("Cache-Control","public");
response.setHeader("Last-Modified",lastModified+" GMT");
try {
copy(is, response.getOutputStream());
} finally {
is.close();
}
return;
}
}
}
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
|
public FilterConfig getFilterConfig() {
return filterConfig;
}
|
protected ServletContext getServletContext(HttpSession session) {
return filterConfig.getServletContext();
}
Servlet 2.3 specifies that the servlet context can be retrieved from the session. Unfortunately, some versions of
WebLogic can only retrieve the servlet context from the filter config. Hence, this method enables subclasses to
retrieve the servlet context from other sources. |
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
String param = filterConfig.getInitParameter("packages");
String packages = "com.opensymphony.webwork.static template com.opensymphony.webwork.interceptor.debugging";
if (param != null) {
packages = param + " " + packages;
}
this.pathPrefixes = parse(packages);
DispatcherUtils.initialize(filterConfig.getServletContext());
}
|
protected String[] parse(String packages) {
if (packages == null) {
return null;
}
List pathPrefixes = new ArrayList();
StringTokenizer st = new StringTokenizer(packages, ", \n\t");
while (st.hasMoreTokens()) {
String pathPrefix = st.nextToken().replace('.", '/");
if (!pathPrefix.endsWith("/")) {
pathPrefix += "/";
}
pathPrefixes.add(pathPrefix);
}
return (String[]) pathPrefixes.toArray(new String[pathPrefixes.size()]);
}
|
protected void setupContainer(HttpServletRequest request) {
ComponentManager container = null;
HttpSession session = request.getSession(false);
ComponentManager fallback = null;
if (session != null) {
fallback = (ComponentManager) session.getAttribute(ComponentManager.COMPONENT_MANAGER_KEY);
}
ServletContext servletContext = getServletContext(session);
if (fallback == null) {
fallback = (ComponentManager) servletContext.getAttribute(ComponentManager.COMPONENT_MANAGER_KEY);
}
if (fallback != null) {
container = createComponentManager();
container.setFallback(fallback);
}
ComponentConfiguration config = (ComponentConfiguration) servletContext.getAttribute("ComponentConfiguration");
if (config != null) {
if (container == null) {
container = createComponentManager();
}
config.configure(container, "request");
request.setAttribute(ComponentManager.COMPONENT_MANAGER_KEY, container);
}
}
|