View Javadoc

1   /*
2    * $Id: CopyFormToContext.java 376862 2006-02-10 21:14:54Z husted $
3    *
4    * Copyright 2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.struts.chain.commands.generic;
19  
20  import org.apache.struts.action.ActionForm;
21  import org.apache.struts.chain.commands.ActionCommandBase;
22  import org.apache.struts.chain.contexts.ActionContext;
23  import org.apache.struts.chain.contexts.ActionContextBase;
24  import org.apache.struts.config.ActionConfig;
25  
26  /***
27   * <p>Subclass this command and configure it as part of a per-forward chain to
28   * perform any necessary pre-population or other preparation for a form before
29   * control is dispatched to the view layer.</p>
30   *
31   * @version $Id: CopyFormToContext.java 376862 2006-02-10 21:14:54Z husted $
32   */
33  public class CopyFormToContext extends ActionCommandBase {
34      // ------------------------------------------------------ Instance Variables
35  
36      /***
37       * <p>The name of a form bean as configured in a struts-config.xml file
38       * for this module.  </p>
39       *
40       * <p> Either actionPath or both this and scope are required configuration
41       * properties.</p>
42       */
43      private String formName = null;
44  
45      /***
46       * <p>The name of a scope, such as "request" or "session" in which the
47       * form to be prepared will be placed for reference by the view and other
48       * parts of Struts.</p>
49       *
50       * <p>Either <code>actionPath</code> or both this and
51       * <code>formName</code> are required configuration properties.</p>
52       */
53      private String scope = null;
54  
55      /***
56       * <p>The path of an <code>&lt;action&gt;</code> mapping as configured in
57       * a <code>struts-config.xml</code> file for this module.  This action
58       * will be looked up, and its <code>name</code> and <code>scope</code>
59       * values will be used as if those values were configured directly in this
60       * instance's <code>formName</code> and <code>scope</code>
61       * properties.</p>
62       *
63       * <p>Either <code>this</code> or both <code>scope</code> and
64       * <code>formName</code> are required configuration properties.</p>
65       */
66      private String actionPath = null;
67  
68      /***
69       * The context key under which the form which was looked up will be
70       * stored. Defaults to "actionForm" but may be overridden in cases where
71       * the "request" ActionForm must be preserved.
72       */
73      private String toKey = ActionContextBase.ACTION_FORM_KEY;
74  
75      // ------------------------------------------------------ Properties
76  
77      /***
78       * <p>Return ActionPath property.</p>
79       *
80       * @return ActionPath property
81       */
82      public String getActionPath() {
83          return this.actionPath;
84      }
85  
86      /***
87       * <p>Set ActionPath property.</p>
88       *
89       * @param actionPath New valuefor ActionPath
90       */
91      public void setActionPath(String actionPath) {
92          this.actionPath = actionPath;
93      }
94  
95      /***
96       * <p>Return FormName property.</p>
97       *
98       * @return FormName property
99       */
100     public String getFormName() {
101         return this.formName;
102     }
103 
104     /***
105      * <p>Set FormName property.</p>
106      *
107      * @param formName New valuefor FormName
108      */
109     public void setFormName(String formName) {
110         this.formName = formName;
111     }
112 
113     /***
114      * <p>Return Scope property.</p>
115      *
116      * @return Scope property
117      */
118     public String getScope() {
119         return this.scope;
120     }
121 
122     /***
123      * <p>Set Scope property.</p>
124      *
125      * @param scope New valuefor Scope
126      */
127     public void setScope(String scope) {
128         this.scope = scope;
129     }
130 
131     /***
132      * <p>Return ToKey property.</p>
133      *
134      * @return ToKey property
135      */
136     public String getToKey() {
137         return this.toKey;
138     }
139 
140     /***
141      * <p>Set ToKey property.</p>
142      *
143      * @param toKey New valuefor FormName
144      */
145     public void setToKey(String toKey) {
146         this.toKey = toKey;
147     }
148 
149     // ------------------------------------------------------
150 
151     /***
152      * <p>Look up an ActionForm instance based on the configured properties of
153      * this command and copy it into the <code>Context</code>.  After this
154      * command successfully executes, an ActionForm instance will exist in the
155      * specified scope and will be available, for example for backing fields
156      * in an HTML form.  It will also be in the <code>ActionContext</code>
157      * available for another command to do prepopulation of values or other
158      * preparation.</p>
159      *
160      * @param actionContext Our ActionContext
161      * @return TRUE if processing should halt
162      * @throws Exception on any error
163      */
164     public boolean execute(ActionContext actionContext)
165         throws Exception {
166         ActionForm form = findOrCreateForm(actionContext);
167 
168         if (isEmpty(getToKey())) {
169             throw new IllegalStateException("Property 'toKey' must be defined.");
170         }
171 
172         actionContext.put(getToKey(), form);
173 
174         return false;
175     }
176 
177     /***
178      * <p>Based on the properties of this command and the given
179      * <code>ActionContext</code>, find or create an ActionForm instance for
180      * preparation.</p>
181      *
182      * @param context ActionContextBase class that we are processing
183      * @return ActionForm instance
184      * @throws IllegalArgumentException On ActionConfig not found
185      * @throws IllegalStateException    On undefined scope and formbean
186      * @throws IllegalAccessException   On failed instantiation
187      * @throws InstantiationException   If ActionContext is not subsclass of
188      *                                  ActionContextBase
189      */
190     protected ActionForm findOrCreateForm(ActionContext context)
191         throws IllegalAccessException, InstantiationException {
192         String effectiveFormName;
193         String effectiveScope;
194 
195         if (!(isEmpty(this.getActionPath()))) {
196             ActionConfig actionConfig =
197                 context.getModuleConfig().findActionConfig(this.getActionPath());
198 
199             if (actionConfig == null) {
200                 throw new IllegalArgumentException(
201                     "No ActionConfig found for path " + this.getActionPath());
202             }
203 
204             effectiveFormName = actionConfig.getName();
205             effectiveScope = actionConfig.getScope();
206         } else {
207             effectiveFormName = this.getFormName();
208             effectiveScope = this.getScope();
209         }
210 
211         if (isEmpty(effectiveScope) || isEmpty(effectiveFormName)) {
212             throw new IllegalStateException("Both scope [" + effectiveScope
213                 + "] and formName [" + effectiveFormName + "] must be defined.");
214         }
215 
216         return findOrCreateForm(context, effectiveFormName, effectiveScope);
217     }
218 
219     /***
220      * <p>Actually find or create an instance of ActionForm configured under
221      * the form-bean-name <code>effectiveFormName</code>, looking in in the
222      * <code>ActionContext's</code> scope as identified by
223      * <code>effectiveScope</code>. If a form is created, it will also be
224      * stored in that scope.</p>
225      *
226      * <p><b>NOTE:</b> This specific method depends on the instance of
227      * <code>ActionContext</code> which is passed being a subclass of
228      * <code>ActionContextBase</code>, which implements the utility method
229      * <code>findOrCreateActionForm</code>. </p>
230      *
231      * @param ctx               The ActionContext we are processing
232      * @param effectiveFormName the target form name
233      * @param effectiveScope    The target scope
234      * @return ActionForm instnace, storing in scope if created
235      * @throws InstantiationException   If ActionContext is not subsclass of
236      *                                  ActionContextBase
237      * @throws InstantiationException   If object cannot be created
238      * @throws IllegalArgumentException On form not found in/ scope
239      * @throws IllegalAccessException   On failed instantiation
240      * @throws IllegalStateException    If ActionContext is not a subclass of
241      *                                  ActionBase
242      */
243     protected ActionForm findOrCreateForm(ActionContext ctx,
244         String effectiveFormName, String effectiveScope)
245         throws IllegalAccessException, InstantiationException {
246         ActionContextBase context;
247 
248         try {
249             context = (ActionContextBase) ctx;
250         } catch (ClassCastException e) {
251             throw new IllegalStateException("ActionContext [" + ctx + "]"
252                 + " must be subclass of ActionContextBase");
253         }
254 
255         ActionForm form =
256             context.findOrCreateActionForm(effectiveFormName, effectiveScope);
257 
258         if (form == null) {
259             throw new IllegalArgumentException("No form found under scope ["
260                 + effectiveScope + "] and formName [" + effectiveFormName + "]");
261         }
262 
263         return form;
264     }
265 
266     /***
267      * <p>Convenience method to test for an empty string.</p>
268      *
269      * @param test String to test
270      * @return TRUE if test is null or zero-length
271      */
272     private boolean isEmpty(String test) {
273         return (test == null) || (test.trim().length() == 0);
274     }
275 }