Author: germuska
Date: Tue Nov 1 11:58:40 2005
New Revision: 330112
URL: http://svn.apache.org/viewcvs?rev=330112&view=rev
Log:
Provide support for specifying an alternative ActionContext implementation
class
in struts-config.xml rather than requiring subclassing of
ComposableRequestProcessor. See JavaDoc for details.
Modified:
struts/core/trunk/src/java/org/apache/struts/chain/ComposableRequestProcessor.java
Modified:
struts/core/trunk/src/java/org/apache/struts/chain/ComposableRequestProcessor.java
URL:
http://svn.apache.org/viewcvs/struts/core/trunk/src/java/org/apache/struts/chain/ComposableRequestProcessor.java?rev=330112&r1=330111&r2=330112&view=diff
==============================================================================
---
struts/core/trunk/src/java/org/apache/struts/chain/ComposableRequestProcessor.java
(original)
+++
struts/core/trunk/src/java/org/apache/struts/chain/ComposableRequestProcessor.java
Tue Nov 1 11:58:40 2005
@@ -18,11 +18,15 @@
import java.io.IOException;
+import java.lang.reflect.Constructor;
+import javax.servlet.ServletContext;
import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.beanutils.ConstructorUtils;
import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.CatalogFactory;
import org.apache.commons.chain.Command;
@@ -35,6 +39,7 @@
import org.apache.struts.config.ControllerConfig;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.upload.MultipartRequestWrapper;
+import org.apache.struts.util.RequestUtils;
/**
@@ -63,6 +68,12 @@
// ------------------------------------------------------ Instance
Variables
+ private static final Class[] SERVLET_ACTION_CONTEXT_CTOR_SIGNATURE = new
Class[] { ServletContext.class, HttpServletRequest.class,
HttpServletResponse.class };
+
+
+ public static final String ACTION_CONTEXT_CLASS = "ACTION_CONTEXT_CLASS";
+
+
/**
* <p>The [EMAIL PROTECTED] CatalogFactory} from which catalog containing
the the
* base request-processing [EMAIL PROTECTED] Command} will be
retrieved.</p>
@@ -83,6 +94,10 @@
protected Command command = null;
+ private Class actionContextClass;
+
+ private Constructor servletActionContextConstructor = null;
+
/**
* <p>The <code>Log</code> instance for this class.</p>
*/
@@ -102,6 +117,8 @@
catalogFactory = null;
catalog = null;
command = null;
+ actionContextClass = null;
+ servletActionContextConstructor = null;
}
@@ -140,8 +157,45 @@
commandName + "'");
}
+ this.setActionContextClassName(
controllerConfig.getProperty(ACTION_CONTEXT_CLASS) );
+
}
+ private void setActionContextClass(Class actionContextClass) throws
ServletException {
+ this.actionContextClass = actionContextClass;
+ // if there is a custom class provided and if it uses our "preferred"
constructor,
+ // cache a reference to that constructor rather than looking it up
every time.
+ if (actionContextClass != null) {
+ this.servletActionContextConstructor =
ConstructorUtils.getAccessibleConstructor(actionContextClass,
SERVLET_ACTION_CONTEXT_CTOR_SIGNATURE);
+ } else {
+ this.servletActionContextConstructor = null;
+ }
+
+ }
+
+ /**
+ * Make sure that the specified <code>className</code> identfies a class
which can be found
+ * and which implements the <code>ActionContext</code> interface.
+ * @param className
+ * @throws ServletException
+ */
+ private void setActionContextClassName(String className) throws
ServletException {
+ if (className != null && className.trim().length() > 0) {
+ log.debug("setActionContextClassName: requested context class: " +
className);
+ try {
+ Class actionContextClass =
RequestUtils.applicationClass(className);
+ if (!ActionContext.class.isAssignableFrom(actionContextClass))
{
+ throw new UnavailableException("ActionContextClass [" +
className + "] must implement ActionContext interface.");
+ }
+ this.setActionContextClass(actionContextClass);
+ } catch (ClassNotFoundException e) {
+ throw new UnavailableException("ActionContextClass " +
className + " not found.");
+ }
+ } else {
+ log.debug("setActionContextClassName: no actionContextClass
specified");
+ this.setActionContextClass(null);
+ }
+ }
/**
* <p>Establish the <code>CatalogFactory</code> which will be used to look
up
@@ -196,15 +250,59 @@
context.release();
}
+ /**
+ * Provide the initialized <code>ActionContext</code> instance which will
be used by this request.
+ * Internally, this simply calls <code>createActionContextInstance</code>
followed by
+ * <code>initializeActionContext</code>.
+ * @param request
+ * @param response
+ * @return
+ * @throws ServletException
+ */
protected ActionContext contextInstance(HttpServletRequest request,
- HttpServletResponse response) {
- // Create and populate a Context for this request
- ServletActionContext context = new
ServletActionContext(getServletContext(), request, response);
- context.setActionServlet(this.servlet);
- context.setModuleConfig(this.moduleConfig);
+ HttpServletResponse response)
throws ServletException {
+ ActionContext context =
createActionContextInstance(getServletContext(), request, response);
+ initializeActionContext(context);
return context;
}
+ /**
+ * Create a new instance of <code>ActionContext</code> according to
configuration. If no alternative was specified at initialization,
+ * a new instance <code>ServletActionContext</code> is returned. If an
alternative was specified using the
+ * <code>ACTION_CONTEXT_CLASS</code> property, then that value is treated
as a classname, and an instance of that class
+ * is created. If that class implements the same constructor that
<code>ServletActionContext</code> does, then that constructor
+ * will be used: <code>ServletContext, HttpServletRequest,
HttpServletResponse</code>; otherwise, it is assumed that the class
+ * has a no-arguments constructor. If these constraints do not suit you,
simply override this method in a subclass.
+ * @param servletContext
+ * @param request
+ * @param response
+ * @return
+ * @throws ServletException
+ */
+ protected ActionContext createActionContextInstance(ServletContext
servletContext, HttpServletRequest request, HttpServletResponse response)
throws ServletException {
+ if (this.actionContextClass == null) return new
ServletActionContext(servletContext, request, response);
+ try {
+ if (this.servletActionContextConstructor == null) return
(ActionContext) this.actionContextClass.newInstance();
+ return (ActionContext)
this.servletActionContextConstructor.newInstance(new Object[] { servletContext,
request, response });
+ } catch (Exception e) {
+ throw new ServletException("Error creating ActionContext instance
of type " + this.actionContextClass, e);
+ }
+ }
+
+ /**
+ * Set common properties on the given <code>ActionContext</code> instance
so that commands in the chain
+ * can count on their presence. Note that while this method does not
require that its argument
+ * be an instance of <code>ServletActionContext</code>, at this time many
common Struts
+ * commands will be expecting to receive an <code>ActionContext</code>
which is also a <code>ServletActionContext</code>.
+ * @param context
+ */
+ protected void initializeActionContext(ActionContext context) {
+ if (context instanceof ServletActionContext) {
+ ((ServletActionContext) context).setActionServlet(this.servlet);
+ }
+ context.setModuleConfig(this.moduleConfig);
+ }
+
/**
* If this is a multipart request, wrap it with a special wrapper.
* Otherwise, return the request unchanged.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]