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