Author: germuska
Date: Fri Apr 15 09:33:24 2005
New Revision: 161497

URL: http://svn.apache.org/viewcvs?view=rev&rev=161497
Log:
Add the ability to FormBeanConfig to create an ActionForm based on an 
ActionContext instead of a Servlet, hiding a dependency on the Servlet API.

This enables the elimination of o.a.s.chain.commands.AbstractCreateForm and 
it's subclass in the o.a.s.c.c.servlet package.  These are deprecated, but will 
be removed before the first Struts 1.3 release, but are preserved temporarily 
to smooth the transition for users who have customized the default 
chain-config.xml file.  (In that file, 
"org.apache.struts.chain.commands.servlet.CreateActionForm" should be changed 
to "org.apache.struts.chain.commands.CreateActionForm".

Change chain-config.xml to use new version of CreateActionForm.

Add convenience method to ActionContextBase to findOrCreateForm given a form 
name and scope name, since it contains all the necessary referents to achieve 
that.

Add logger property to ActionContextBase, with default initialization strategy.

Create generic command which can use configuration parameters to lookup or 
create an ActionForm and place it in the ActionContext under a specified key, 
so that a subsequent command can prepopulate fields.

Centralize logic to determine whether a given ActionForm instance can be 
"re-used" for a given FormBeanConfig as an instance method of FormBeanConfig.  
Adjust RequestUtils to use newly centralized logic.



Added:
    
struts/core/trunk/src/share/org/apache/struts/chain/commands/CreateActionForm.java
   (with props)
    
struts/core/trunk/src/share/org/apache/struts/chain/commands/generic/CopyFormToContext.java
   (with props)
    
struts/core/trunk/src/test/org/apache/struts/chain/commands/generic/TestCopyFormToContext.java
   (with props)
Modified:
    struts/core/trunk/conf/share/chain-config.xml
    
struts/core/trunk/src/share/org/apache/struts/chain/commands/AbstractCreateActionForm.java
    
struts/core/trunk/src/share/org/apache/struts/chain/commands/servlet/CreateActionForm.java
    
struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContext.java
    
struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContextBase.java
    struts/core/trunk/src/share/org/apache/struts/config/FormBeanConfig.java
    struts/core/trunk/src/share/org/apache/struts/util/RequestUtils.java

Modified: struts/core/trunk/conf/share/chain-config.xml
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/conf/share/chain-config.xml?view=diff&r1=161496&r2=161497
==============================================================================
--- struts/core/trunk/conf/share/chain-config.xml (original)
+++ struts/core/trunk/conf/share/chain-config.xml Fri Apr 15 09:33:24 2005
@@ -141,7 +141,7 @@
 
       <!-- Create (if needed) the ActionForm for this request -->
       <command
-          
className="org.apache.struts.chain.commands.servlet.CreateActionForm"/>
+          className="org.apache.struts.chain.commands.CreateActionForm"/>
 
 
       <!-- Populate the ActionForm for this request -->

Modified: 
struts/core/trunk/src/share/org/apache/struts/chain/commands/AbstractCreateActionForm.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/chain/commands/AbstractCreateActionForm.java?view=diff&r1=161496&r2=161497
==============================================================================
--- 
struts/core/trunk/src/share/org/apache/struts/chain/commands/AbstractCreateActionForm.java
 (original)
+++ 
struts/core/trunk/src/share/org/apache/struts/chain/commands/AbstractCreateActionForm.java
 Fri Apr 15 09:33:24 2005
@@ -32,6 +32,9 @@
  *
  * @author Craig R. McClanahan
  * @version $Id$
+ * @deprecated This class no longer needs to be abstract.  Use 
+ * <code>org.apache.struts.chain.commands.CreateActionForm</code> instead.
+ * This will be removed BEFORE a full Struts 1.3.0 release.
  */
 
 public abstract class AbstractCreateActionForm extends ActionCommandBase {

Added: 
struts/core/trunk/src/share/org/apache/struts/chain/commands/CreateActionForm.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/chain/commands/CreateActionForm.java?view=auto&rev=161497
==============================================================================
--- 
struts/core/trunk/src/share/org/apache/struts/chain/commands/CreateActionForm.java
 (added)
+++ 
struts/core/trunk/src/share/org/apache/struts/chain/commands/CreateActionForm.java
 Fri Apr 15 09:33:24 2005
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2003,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.chain.commands;
+
+
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.chain.contexts.ActionContext;
+import org.apache.struts.chain.contexts.ServletActionContext;
+import org.apache.struts.config.ActionConfig;
+import org.apache.struts.config.FormBeanConfig;
+
+
+/**
+ * <p>Create (if necessary) and cache a form bean for this request.</p>
+ *
+ * @version $Id$
+ */
+public class CreateActionForm extends ActionCommandBase {
+
+
+    // ------------------------------------------------------ Instance 
Variables
+
+
+    private static final Log log =
+        LogFactory.getLog(CreateActionForm.class);
+
+    // ---------------------------------------------------------- Public 
Methods
+
+
+    /**
+     * <p>Create (if necessary) and cache a form bean for this request.</p>
+     *
+     * @param context The <code>Context</code> for the current request
+     *
+     * @return <code>false</code> so that processing continues
+     */
+    public boolean execute(ActionContext actionCtx) throws Exception {
+
+        // Is there a form bean associated with this ActionConfig?
+        ActionConfig actionConfig = actionCtx.getActionConfig();
+        String name = actionConfig.getName();
+        if (name == null) {
+            actionCtx.setActionForm(null);
+            return (false);
+        }
+
+        log.trace("Look up form-bean " + name);
+
+        // Look up the corresponding FormBeanConfig (if any)
+        FormBeanConfig formBeanConfig =
+            actionConfig.getModuleConfig().findFormBeanConfig(name);
+        if (formBeanConfig == null) {
+            log.warn("No FormBeanConfig found in module "
+                     + actionConfig.getModuleConfig().getPrefix()
+                     + " under name " + name);
+            actionCtx.setActionForm(null);
+            return (false);
+        }
+
+        Map scope = actionCtx.getScope(actionConfig.getScope());
+
+        ActionForm instance = null;
+        instance = (ActionForm) scope.get(actionConfig.getAttribute());
+
+        // Can we recycle the existing instance (if any)?
+        if (!formBeanConfig.canReuse(instance)) {
+            instance = formBeanConfig.createActionForm(actionCtx);
+        }
+
+        // TODO Remove this when ActionForm no longer directly depends on 
ActionServlet 
+        if (actionCtx instanceof ServletActionContext) {
+            // The servlet property of ActionForm is transient, so
+            // ActionForms which are restored from a serialized state
+            // need to have their servlet restored.
+            ServletActionContext sac = (ServletActionContext) actionCtx;
+            instance.setServlet(sac.getActionServlet());
+        }
+        
+        actionCtx.setActionForm(instance);
+
+        scope.put(actionConfig.getAttribute(), instance);
+
+        return (false);
+
+    }
+
+}

Propchange: 
struts/core/trunk/src/share/org/apache/struts/chain/commands/CreateActionForm.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
struts/core/trunk/src/share/org/apache/struts/chain/commands/CreateActionForm.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: 
struts/core/trunk/src/share/org/apache/struts/chain/commands/generic/CopyFormToContext.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/chain/commands/generic/CopyFormToContext.java?view=auto&rev=161497
==============================================================================
--- 
struts/core/trunk/src/share/org/apache/struts/chain/commands/generic/CopyFormToContext.java
 (added)
+++ 
struts/core/trunk/src/share/org/apache/struts/chain/commands/generic/CopyFormToContext.java
 Fri Apr 15 09:33:24 2005
@@ -0,0 +1,203 @@
+/*
+ * $Id$
+ * 
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.chain.commands.generic;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.chain.commands.ActionCommandBase;
+import org.apache.struts.chain.contexts.ActionContext;
+import org.apache.struts.chain.contexts.ActionContextBase;
+import org.apache.struts.config.ActionConfig;
+
+/**
+ * <p>Subclass this command and configure it as part of a per-forward chain to
+ * perform any necessary pre-population or other preparation for a form before 
+ * control is dispatched to the view layer.</p>
+ *
+ * @version $Id$
+ */
+public class CopyFormToContext extends ActionCommandBase {
+
+    // ------------------------------------------------------ Instance 
Variables
+
+    /**
+     * <p>The name of a form bean as configured in a 
<code>struts-config.xml</code> file 
+     * for this module.  </p>
+
+     * <p>
+     * Either <code>actionPath</code> or both this and <code>scope</code> are 
required
+     * configuration properties.</p>
+     */
+    private String formName = null;
+
+    /**
+     * <p>The name of a scope, such as "request" or "session" in which
+     * the form to be prepared will be placed for reference by the view and
+     * other parts of Struts.</p>
+
+     * <p>
+     * Either <code>actionPath</code> or both this and <code>formName</code> 
are required
+     * configuration properties.</p>
+     */
+    private String scope = null;
+
+    /**
+     * <p>The path of an <code>&lt;action&gt;</code> mapping as configured in 
a <code>struts-config.xml</code> file 
+     * for this module.  This action will be looked up, and its 
<code>name</code> and
+     * <code>scope</code> values will be used as if those values were 
configured directly
+     * in this instance's <code>formName</code> and <code>scope</code> 
properties.</p>
+
+     * <p>Either <code>this</code> or both <code>scope</code> and 
<code>formName</code> are required
+     * configuration properties.</p>
+     */
+    private String actionPath = null;
+    
+    /**
+     * The context key under which the form which was looked up will be 
stored.  Defaults
+     * to "actionForm" but may be overridden in cases where the "request" 
ActionForm must
+     * be preserved.
+     */
+    private String toKey = ActionContextBase.ACTION_FORM_KEY;
+    
+    // ------------------------------------------------------ Properties
+    public String getActionPath() {
+        return this.actionPath;
+    }
+    public void setActionPath(String actionPath) {
+        this.actionPath = actionPath;
+    }
+    public String getFormName() {
+        return this.formName;
+    }
+    public void setFormName(String formName) {
+        this.formName = formName;
+    }
+    public String getScope() {
+        return this.scope;
+    }
+    public void setScope(String scope) {
+        this.scope = scope;
+    }
+    public String getToKey() {
+        return this.toKey;
+    }
+    public void setToKey(String toKey) {
+        this.toKey = toKey;
+    }
+
+    
+    // ------------------------------------------------------ 
+
+    /**
+     * <p>Look up an ActionForm instance based on the configured properties of 
this command and 
+     * copy it into the <code>Context</code>.  After this command successfully
+     * executes, an ActionForm instance will exist in the specified scope
+     * and will be available, for example for backing fields in an HTML form.  
It
+     * will also be in the <code>ActionContext</code> available for another 
command
+     * to do prepopulation of values or other preparation.</p>
+     */
+    public boolean execute(ActionContext actionContext) throws Exception {
+
+        ActionForm form = findOrCreateForm(actionContext);
+        if (isEmpty(getToKey())) {
+            throw new IllegalStateException("Property 'toKey' must be 
defined.");
+        }
+        actionContext.put(getToKey(), form);
+        return false;
+    }
+    
+    /**
+     * <p>Based on the properties of this command and the given 
<code>ActionContext</code>,
+     * find or create an ActionForm instance for preparation.</p>
+     * 
+     * @param context
+     * @return
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     */
+    protected ActionForm findOrCreateForm(ActionContext context) throws 
IllegalAccessException, InstantiationException {
+        String effectiveFormName = null;
+        String effectiveScope = null;
+        if ( !(isEmpty(this.getActionPath())) ) {
+
+            ActionConfig actionConfig = 
context.getModuleConfig().findActionConfig(this.getActionPath());
+
+            if (actionConfig == null) {
+                throw new IllegalArgumentException("No ActionConfig found for 
path " + this.getActionPath());
+            }
+
+            effectiveFormName = actionConfig.getName();
+            effectiveScope = actionConfig.getScope();
+            
+        } else {
+            effectiveFormName = this.getFormName();
+            effectiveScope = this.getScope();
+        }
+        if (isEmpty(effectiveScope) || isEmpty(effectiveFormName)) {
+            throw new IllegalStateException("Both scope [" 
+                    + effectiveScope
+                    + "] and formName ["
+                    + effectiveFormName
+                    + "] must be defined.");
+        }
+
+        return findOrCreateForm(context, effectiveFormName, effectiveScope);
+    }
+
+    /**
+     *  Actually find or create an instance of ActionForm configured under 
+     * the form-bean-name <code>effectiveFormName</code>, looking in
+     * in the <code>ActionContext's</code> scope as identified by 
<code>effectiveScope</code>.
+     * If a form is created, it will also be stored in that scope.
+     * 
+     * <p><b>NOTE:</b> This specific method depends on the instance of 
+     * <code>ActionContext</code> which is passed being a subclass of 
+     * <code>ActionContextBase</code>, which implements the utility method
+     * <code>findOrCreateActionForm</code>.
+     * </p>
+     * 
+     * @param ctx
+     * @param effectiveFormName
+     * @param effectiveScope
+     * @return
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @throws IllegalArgumentException
+     */
+    protected ActionForm findOrCreateForm(ActionContext ctx, String 
effectiveFormName, String effectiveScope) throws IllegalAccessException, 
InstantiationException, IllegalArgumentException {
+        ActionContextBase context;
+        try {
+            context = (ActionContextBase) ctx;
+        } catch (ClassCastException e) {
+            throw new IllegalStateException("ActionContext [" + ctx + "] must 
be subclass of ActionContextBase");
+        }
+        ActionForm form = context.findOrCreateActionForm(effectiveFormName, 
effectiveScope);
+        if (form == null) {
+            throw new IllegalArgumentException("No form found under scope [" 
+                    + effectiveScope
+                    + "] and formName ["
+                    + effectiveFormName
+                    + "]");
+        }
+        return form;
+    }
+    private boolean isEmpty(String test) {
+        return test == null || test.trim().length() == 0;
+    }
+}
+

Propchange: 
struts/core/trunk/src/share/org/apache/struts/chain/commands/generic/CopyFormToContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
struts/core/trunk/src/share/org/apache/struts/chain/commands/generic/CopyFormToContext.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: 
struts/core/trunk/src/share/org/apache/struts/chain/commands/servlet/CreateActionForm.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/chain/commands/servlet/CreateActionForm.java?view=diff&r1=161496&r2=161497
==============================================================================
--- 
struts/core/trunk/src/share/org/apache/struts/chain/commands/servlet/CreateActionForm.java
 (original)
+++ 
struts/core/trunk/src/share/org/apache/struts/chain/commands/servlet/CreateActionForm.java
 Fri Apr 15 09:33:24 2005
@@ -27,6 +27,11 @@
 import org.apache.struts.config.ActionConfig;
 import org.apache.struts.config.FormBeanConfig;
 
+/**
+ * @deprecated This class and its parent are no longer necessary.  Use 
+ * <code>org.apache.struts.chain.commands.CreateActionForm</code> instead.
+ * This will be removed BEFORE a full Struts 1.3.0 release.
+ */
 public class CreateActionForm extends
         org.apache.struts.chain.commands.AbstractCreateActionForm {
 

Modified: 
struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContext.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContext.java?view=diff&r1=161496&r2=161497
==============================================================================
--- 
struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContext.java 
(original)
+++ 
struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContext.java 
Fri Apr 15 09:33:24 2005
@@ -95,6 +95,16 @@
     Map getRequestScope();
 
     /**
+     * Return the Map representing the scope identified by 
<code>scopeName</code>.
+     * Implementations should support at minimum the names associated with the 
constants
+     * <code>APPLICATION_SCOPE</code>, <code>SESSION_SCOPE</code>, and 
+     * <code>REQUEST_SCOPE</code>, but are permitted to support others as well.
+     * @param scopeName
+     * @return
+     */
+    Map getScope(String scopeName);
+    
+    /**
      * <p>Return a <code>Map</code> of parameters submitted by the user
      * as part of this request.</p>
      * 

Modified: 
struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContextBase.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContextBase.java?view=diff&r1=161496&r2=161497
==============================================================================
--- 
struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContextBase.java
 (original)
+++ 
struts/core/trunk/src/share/org/apache/struts/chain/contexts/ActionContextBase.java
 Fri Apr 15 09:33:24 2005
@@ -21,17 +21,19 @@
 import java.util.Map;
 
 import org.apache.commons.chain.Context;
-import org.apache.struts.action.ActionMessages;
-import org.apache.struts.util.MessageResources;
 import org.apache.commons.chain.impl.ContextBase;
-import org.apache.struts.util.TokenProcessor;
-import org.apache.struts.chain.Constants;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.Action;
 import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMessages;
+import org.apache.struts.chain.Constants;
 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.action.Action;
-
+import org.apache.struts.util.MessageResources;
+import org.apache.struts.util.TokenProcessor;
 
 
 /**
@@ -75,12 +77,15 @@
     public static final String TRANSACTION_TOKEN_KEY = "TRANSACTION_TOKEN_KEY";
 
     public static final String TOKEN_KEY = "TOKEN_KEY";
+    
+    protected TokenProcessor token = null;
 
-    TokenProcessor token = null;
-
+    private Log logger = null;
+    
     public ActionContextBase(Context context) {
         super(context);
         token = TokenProcessor.getInstance();
+        logger = LogFactory.getLog(this.getClass());
     }
 
     public ActionContextBase() {
@@ -101,7 +106,13 @@
 
     public abstract Map getSessionScope();
    
-    
+    public Map getScope(String scopeName) {
+        if (REQUEST_SCOPE.equals(scopeName)) return this.getRequestScope();
+        if (SESSION_SCOPE.equals(scopeName)) return this.getSessionScope();
+        if (APPLICATION_SCOPE.equals(scopeName)) return 
this.getApplicationScope();
+        throw new IllegalArgumentException("Invalid scope: " + scopeName);
+    }
+
     // -------------------------------
     // General Struts properties
     // -------------------------------
@@ -334,5 +345,76 @@
     public Locale getLocale() {
         return (Locale) this.get(LOCALE_KEY);
     }
+
+    // -------------------------------
+    // Convenience Methods: these are not part of the formal ActionContext API,
+    // but are likely to be commonly useful.
+    // -------------------------------
+    /**
+     * <p>Return the currently configured commons-logging <code>Log</code> 
instance.</p>
+     * @return
+     */
+    public Log getLogger() {
+        return this.logger;
+    }
+
+    /**
+     * <p>Set the commons-logging <code>Log</code> instance which should be 
used to log messages.
+     * This is initialized at instantiation time but may be overridden.  Be 
advised not to set the value
+     * to null, as <code>ActionContextBase</code> uses the logger for some of 
its own operations.</p>
+     */
+    public void setLogger(Log logger) {
+        this.logger = logger;
+    }
+
+    /**
+     * Using this <code>ActionContext</code>'s default 
<code>ModuleConfig</code>, return an existing
+     * <code>ActionForm</code> in the specified scope, or create a new one and 
add it to the specified scope.
+     * @param formName
+     * @param scopeName
+     * @return
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @see findOrCreateActionForm(String, String, ModuleConfig)
+     */
+    public ActionForm findOrCreateActionForm(String formName, String 
scopeName) throws IllegalAccessException, InstantiationException {
+        return this.findOrCreateActionForm(formName, scopeName, 
this.getModuleConfig());
+    }
+    
+    /**
+     * <p>In the context of the given <code>ModuleConfig</code> and this 
<code>ActionContext</code>, 
+     * look for an existing <code>ActionForm</code> in the specified scope.  
If one is found, return
+     * it; otherwise, create a new instance, add it to that scope, and then 
return it.</p>
+     * @param formName
+     * @param scopeName
+     * @return
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     */
+    public ActionForm findOrCreateActionForm(String formName, String 
scopeName, ModuleConfig moduleConfig) throws IllegalAccessException, 
InstantiationException {
+        Map scope = this.getScope(scopeName);
+        
+        ActionForm instance = null;
+        FormBeanConfig formBeanConfig = 
moduleConfig.findFormBeanConfig(formName);
+
+        if (formBeanConfig == null) {
+            throw new IllegalArgumentException("No form config found under " + 
formName + " in module " + moduleConfig.getPrefix() );
+        }
+        
+        instance = (ActionForm) scope.get(formName);
+        // Can we recycle the existing instance (if any)?
+        if (instance != null) {
+            getLogger().trace("Found an instance in scope " + scopeName + "; 
test for reusability");
+            if (formBeanConfig.canReuse(instance)) {
+                return instance;
+            }
+        }
+
+        ActionForm form = formBeanConfig.createActionForm(this);
+        scope.put(formName, form);
+        return form;
+    }
+
+    
 
 }

Modified: 
struts/core/trunk/src/share/org/apache/struts/config/FormBeanConfig.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/config/FormBeanConfig.java?view=diff&r1=161496&r2=161497
==============================================================================
--- struts/core/trunk/src/share/org/apache/struts/config/FormBeanConfig.java 
(original)
+++ struts/core/trunk/src/share/org/apache/struts/config/FormBeanConfig.java 
Fri Apr 15 09:33:24 2005
@@ -27,10 +27,15 @@
 import org.apache.commons.beanutils.DynaBean;
 import org.apache.commons.beanutils.MutableDynaClass;
 import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.struts.action.DynaActionForm;
 import org.apache.struts.action.DynaActionFormClass;
 import org.apache.struts.action.ActionServlet;
 import org.apache.struts.action.ActionForm;
+import org.apache.struts.chain.commands.util.ClassUtils;
+import org.apache.struts.chain.contexts.ActionContext;
+import org.apache.struts.chain.contexts.ServletActionContext;
 import org.apache.struts.validator.BeanValidatorForm;
 import org.apache.struts.util.RequestUtils;
 
@@ -46,7 +51,7 @@
 
 public class FormBeanConfig implements Serializable {
 
-
+    private static final Log log = LogFactory.getLog(FormBeanConfig.class);
     // ----------------------------------------------------- Instance Variables
 
 
@@ -296,6 +301,11 @@
      * <p>Create and return an <code>ActionForm</code> instance appropriate
      * to the information in this <code>FormBeanConfig</code>.</p>
      *
+     * <p>Although this method is not formally deprecated yet, where possible, 
the
+     * form which accepts an <code>ActionContext</code> as an argument is 
preferred,
+     * to help sever direct dependencies on the Servlet API.  As the 
ActionContext becomes
+     * more familiar in Struts, this method will almost certainly be 
deprecated.</p>
+     * 
      * @param servlet The action servlet
      * @return ActionForm instance
      * @exception IllegalAccessException if the Class or the appropriate
@@ -345,7 +355,69 @@
 
     }
 
+    /**
+     * <p>Create and return an <code>ActionForm</code> instance appropriate
+     * to the information in this <code>FormBeanConfig</code>.</p>
+     * <p><b>NOTE:</b> If the given <code>ActionContext</code> is not of type 
+     * <code>ServletActionContext</code> (or a subclass), then the form which 
is
+     * returned will have a null <code>servlet</code> property.  Some of 
+     * the subclasses of <code>ActionForm</code> included in Struts will 
+     * later throw a <code>NullPointerException</code> in this case. 
+     * </p>
+     * <p>TODO: Find a way to control this direct dependency on the Servlet 
API.</p>
+     * 
+     * @param context The ActionContext.
+     * @return ActionForm instance
+     * @exception IllegalAccessException if the Class or the appropriate
+     *  constructor is not accessible
+     * @exception InstantiationException if this Class represents an abstract
+     *  class, an array class, a primitive type, or void; or if instantiation
+     *  fails for some other reason
+     */
+    public ActionForm createActionForm(ActionContext context)
+        throws IllegalAccessException, InstantiationException {
+
+        ActionServlet actionServlet = null;
+        if (context instanceof ServletActionContext) {
+            ServletActionContext saContext = (ServletActionContext) context;
+            actionServlet = saContext.getActionServlet();
+        }
+        return createActionForm(actionServlet);
+    }
 
+    /**
+     * Is the given <code>ActionForm</code> instance suitable for use as an
+     * alternative to calling this <code>FormBeanConfig</code> instance's 
+     * <code>createActionForm</code> method. 
+     * @param form
+     * @return
+     */
+    public boolean canReuse(ActionForm form) {
+        if (form != null) {
+            if (this.getDynamic()) {
+                String className =
+                    ((DynaBean) form).getDynaClass().getName();
+                if (className.equals(this.getName())) {
+                    log.debug("Can reuse existing instance (dynamic)");
+                    return (true);
+                }
+            } else {
+                try {
+                    Class configClass =
+                        ClassUtils.getApplicationClass
+                        (this.getType());
+                    if (configClass.isAssignableFrom(form.getClass())) {
+                        log.debug("Can reuse existing instance (non-dynamic)");
+                        return (true);
+                    }
+                } catch (Exception e) {
+                    log.debug("Error testing existing instance for 
reusability; just create a new instance", e);
+                }
+            }
+        }
+        return false;
+    }
+    
     /**
      * Add a new <code>FormPropertyConfig</code> instance to the set associated
      * with this module.

Modified: struts/core/trunk/src/share/org/apache/struts/util/RequestUtils.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/util/RequestUtils.java?view=diff&r1=161496&r2=161497
==============================================================================
--- struts/core/trunk/src/share/org/apache/struts/util/RequestUtils.java 
(original)
+++ struts/core/trunk/src/share/org/apache/struts/util/RequestUtils.java Fri 
Apr 15 09:33:24 2005
@@ -33,7 +33,6 @@
 import javax.servlet.http.HttpSession;
 
 import org.apache.commons.beanutils.BeanUtils;
-import org.apache.commons.beanutils.DynaBean;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.struts.Globals;
@@ -172,13 +171,8 @@
         ActionForm instance = lookupActionForm(request, attribute, 
mapping.getScope());
 
         // Can we recycle the existing form bean instance (if there is one)?
-        try {
-            if (instance != null && canReuseActionForm(instance, config)) {
-                return (instance);
-            }
-        } catch(ClassNotFoundException e) {
-            log.error(servlet.getInternal().getMessage("formBean", 
config.getType()), e);
-            return (null);
+        if (instance != null && config.canReuse(instance)) {
+            return (instance);
         }
 
         return createActionForm(config, servlet);
@@ -207,55 +201,6 @@
         }
 
         return (instance);
-    }
-
-    /**
-     * <p>Determine whether <code>instance</code> of <code>ActionForm</code> is
-     * suitable for re-use as an instance of the form described by
-     * <code>config</code>.</p>
-     * @param instance an instance of <code>ActionForm</code> which was found,
-     * probably in either request or session scope.
-     * @param config the configuration for the ActionForm which is needed.
-     * @return true if the instance found is "compatible" with the type 
required
-     * in the <code>FormBeanConfig</code>; false if not, or if 
<code>instance</code>
-     * is null.
-     * @throws ClassNotFoundException if the <code>type</code> property of
-     * <code>config</code> is not a valid Class name.
-     */
-    private static boolean canReuseActionForm(ActionForm instance, 
FormBeanConfig config)
-            throws ClassNotFoundException
-    {
-        if (instance == null) {
-            return (false);
-        }
-
-        boolean canReuse = false;
-        String formType = null;
-        String className = null;
-
-        if (config.getDynamic()) {
-            className = ((DynaBean) instance).getDynaClass().getName();
-            canReuse = className.equals(config.getName());
-            formType = "DynaActionForm";
-        } else {
-            Class configClass = applicationClass(config.getType());
-            className = instance.getClass().getName();
-            canReuse = configClass.isAssignableFrom(instance.getClass());
-            formType = "ActionForm";
-        }
-
-        if (log.isDebugEnabled()) {
-            log.debug(
-                    " Can recycle existing "
-                    + formType
-                    + " instance "
-                    + "of type '"
-                    + className
-                    + "'?: "
-                    + canReuse);
-            log.trace(" --> " + instance);
-        }
-        return (canReuse);
     }
 
     /**

Added: 
struts/core/trunk/src/test/org/apache/struts/chain/commands/generic/TestCopyFormToContext.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/test/org/apache/struts/chain/commands/generic/TestCopyFormToContext.java?view=auto&rev=161497
==============================================================================
--- 
struts/core/trunk/src/test/org/apache/struts/chain/commands/generic/TestCopyFormToContext.java
 (added)
+++ 
struts/core/trunk/src/test/org/apache/struts/chain/commands/generic/TestCopyFormToContext.java
 Fri Apr 15 09:33:24 2005
@@ -0,0 +1,190 @@
+/*
+ * $Id$
+ * 
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.chain.commands.generic;
+
+import junit.framework.TestCase;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.DynaActionForm;
+import org.apache.struts.chain.contexts.MockActionContext;
+import org.apache.struts.config.ActionConfig;
+import org.apache.struts.config.FormBeanConfig;
+import org.apache.struts.config.FormPropertyConfig;
+import org.apache.struts.config.impl.ModuleConfigImpl;
+import org.apache.struts.mock.MockFormBean;
+
+/**
+ * @version $Id$
+ */
+public class TestCopyFormToContext extends TestCase {
+
+    private static final String POST_EXECUTION_CONTEXT_KEY = "afterTest";
+    private MockActionContext context = null;
+    
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(TestCopyFormToContext.class);
+    }
+
+    /*
+     * @see TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        context = new MockActionContext();
+
+        ModuleConfigImpl moduleConfig = new ModuleConfigImpl("/");
+        context.setModuleConfig(moduleConfig);
+
+        FormBeanConfig fooFBC = new FormBeanConfig();
+        fooFBC.setName("foo");
+        fooFBC.setType("org.apache.struts.mock.MockFormBean");
+        moduleConfig.addFormBeanConfig(fooFBC);
+        
+        FormBeanConfig barFBC = new FormBeanConfig();
+        barFBC.setName("bar");
+        barFBC.setType("org.apache.struts.action.DynaActionForm"); // use a 
different type so we can verify lookups better
+        FormPropertyConfig fpc = new FormPropertyConfig();
+        fpc.setName("property");
+        fpc.setType("java.lang.String");
+        fpc.setInitial("test");
+        barFBC.addFormPropertyConfig(fpc);
+        moduleConfig.addFormBeanConfig(barFBC);
+
+        ActionConfig testActionConfig = new ActionConfig();
+        testActionConfig.setPath("/Test");
+        testActionConfig.setName("foo");
+        testActionConfig.setScope("request");
+        moduleConfig.addActionConfig(testActionConfig);
+
+        moduleConfig.freeze(); // otherwise, ActionConfigMatcher will be null 
and we'll get an NPE... 
+    }
+
+    public void testLookupByNameAndRequestScope() throws Exception {
+        CopyFormToContext command = new CopyFormToContext();
+        String formName = "foo";
+        command.setFormName(formName);
+        command.setScope("request");
+        command.setToKey(POST_EXECUTION_CONTEXT_KEY);
+
+        assertNull(context.get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getRequestScope().get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getSessionScope().get(POST_EXECUTION_CONTEXT_KEY));
+        
+        command.execute(context);
+
+        assertNotNull(context.get(POST_EXECUTION_CONTEXT_KEY));
+        assertNotNull(context.getRequestScope().get(formName));
+        assertNull(context.getSessionScope().get(formName));
+
+        assertSame(context.get(POST_EXECUTION_CONTEXT_KEY), 
context.getRequestScope().get(formName));
+        ActionForm theForm = (ActionForm) 
context.get(POST_EXECUTION_CONTEXT_KEY);
+        assertTrue(theForm instanceof MockFormBean);
+    }
+    
+    public void testLookupByActionPath() throws Exception {
+        CopyFormToContext command = new CopyFormToContext();
+        command.setActionPath("/Test");
+        command.setToKey(POST_EXECUTION_CONTEXT_KEY);
+
+        assertNull(context.get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getRequestScope().get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getSessionScope().get(POST_EXECUTION_CONTEXT_KEY));
+        
+        command.execute(context);
+
+        assertNotNull(context.get(POST_EXECUTION_CONTEXT_KEY));
+        String formName = "foo";
+        assertNotNull(context.getRequestScope().get(formName));
+        assertNull(context.getSessionScope().get(formName));
+
+        assertSame(context.get(POST_EXECUTION_CONTEXT_KEY), 
context.getRequestScope().get(formName));
+        ActionForm theForm = (ActionForm) 
context.get(POST_EXECUTION_CONTEXT_KEY);
+        assertTrue(theForm instanceof MockFormBean);
+    }
+    
+    public void testLookupByNameAndSessionScope() throws Exception {
+        CopyFormToContext command = new CopyFormToContext();
+        String formName = "bar";
+        command.setFormName(formName);
+        command.setScope("session");
+        command.setToKey(POST_EXECUTION_CONTEXT_KEY);
+
+        assertNull(context.get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getRequestScope().get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getSessionScope().get(POST_EXECUTION_CONTEXT_KEY));
+        
+        command.execute(context);
+
+        assertNotNull(context.get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getRequestScope().get(formName));
+        assertNotNull(context.getSessionScope().get(formName));
+
+        assertSame(context.get(POST_EXECUTION_CONTEXT_KEY), 
context.getSessionScope().get(formName));
+        ActionForm theForm = (ActionForm) 
context.get(POST_EXECUTION_CONTEXT_KEY);
+        assertTrue(theForm instanceof DynaActionForm);
+
+        DynaActionForm dForm = (DynaActionForm) theForm;
+        assertEquals("test", dForm.get("property"));
+    }
+ 
+    public void testExceptionHandlingWithNullFormName() throws Exception {
+        CopyFormToContext command = new CopyFormToContext();
+        String formName = "bar";
+        // skip setting form name to test exception
+        // command.setFormName(formName);
+        command.setScope("session");
+        command.setToKey(POST_EXECUTION_CONTEXT_KEY);
+
+        assertNull(context.get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getRequestScope().get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getSessionScope().get(POST_EXECUTION_CONTEXT_KEY));
+        
+        try {
+            command.execute(context);
+            fail("Execution should throw an exception when form name is not 
set.");
+        } catch (IllegalStateException e) {
+            ; // expected.
+        }
+
+    }
+
+
+    public void testExceptionHandlingWithNullEverything() throws Exception {
+        CopyFormToContext command = new CopyFormToContext();
+        String formName = "bar";
+        // skip setting form name to test exception
+        // command.setFormName(formName);
+        // command.setScope("session");
+        // command.setToKey(POST_EXECUTION_CONTEXT_KEY);
+
+        assertNull(context.get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getRequestScope().get(POST_EXECUTION_CONTEXT_KEY));
+        assertNull(context.getSessionScope().get(POST_EXECUTION_CONTEXT_KEY));
+        
+        try {
+            command.execute(context);
+            fail("Execution should throw an exception when no properties are 
set.");
+        } catch (IllegalStateException e) {
+            ; // expected.
+        }
+
+    }
+
+
+}
+

Propchange: 
struts/core/trunk/src/test/org/apache/struts/chain/commands/generic/TestCopyFormToContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
struts/core/trunk/src/test/org/apache/struts/chain/commands/generic/TestCopyFormToContext.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to