1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
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><action></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
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 }