1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.struts.faces.component;
18
19
20 import java.util.Map;
21 import javax.faces.component.UIForm;
22 import javax.faces.context.FacesContext;
23 import javax.faces.el.ValueBinding;
24 import javax.servlet.http.HttpSession;
25 import org.apache.commons.beanutils.DynaBean;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.struts.Globals;
29 import org.apache.struts.action.ActionForm;
30 import org.apache.struts.action.ActionServlet;
31 import org.apache.struts.action.DynaActionFormClass;
32 import org.apache.struts.config.ActionConfig;
33 import org.apache.struts.config.FormBeanConfig;
34 import org.apache.struts.config.ModuleConfig;
35 import org.apache.struts.util.RequestUtils;
36
37
38 /***
39 * <p><strong>FormComponent</strong> is a specialized subclass of
40 * <code>javax.faces.component.UIForm</code> that supports automatic
41 * creation of form beans in request or session scope.</p>
42 *
43 * @version $Rev: 421138 $ $Date: 2006-07-11 22:41:40 -0700 (Tue, 11 Jul 2006) $
44 */
45 public class FormComponent extends UIForm {
46
47
48
49
50
51 /***
52 * <p>The <code>Log</code> instance for this class.</p>
53 */
54 protected static Log log = LogFactory.getLog(FormComponent.class);
55
56
57
58
59
60 private String action = null;
61 private String enctype = null;
62 private String focus = null;
63 private String focusIndex = null;
64 private String onreset = null;
65 private String onsubmit = null;
66 private String style = null;
67 private String styleClass = null;
68 private String target = null;
69
70
71
72
73
74 /***
75 * <p>Return the Struts action path to which this form should be submitted.
76 * </p>
77 */
78 public String getAction() {
79
80 if (this.action != null) {
81 return (this.action);
82 }
83 ValueBinding vb = getValueBinding("action");
84 if (vb != null) {
85 return ((String) vb.getValue(getFacesContext()));
86 } else {
87 return (null);
88 }
89
90 }
91
92
93 /***
94 * <p>Set the Struts action to which this form should be submitted.</p>
95 *
96 * @param action The new action path
97 */
98 public void setAction(String action) {
99
100 this.action = action;
101
102 }
103
104
105 /***
106 * <p>Return the encoding type for this form submit.</p>
107 */
108 public String getEnctype() {
109
110 if (this.enctype != null) {
111 return (this.enctype);
112 }
113 ValueBinding vb = getValueBinding("enctype");
114 if (vb != null) {
115 return ((String) vb.getValue(getFacesContext()));
116 } else {
117 return (null);
118 }
119
120 }
121
122
123 /***
124 * <p>Set the encoding type for this form submit.</p>
125 *
126 * @param enctype The new enctype path
127 */
128 public void setEnctype(String enctype) {
129
130 this.enctype = enctype;
131
132 }
133
134
135 /***
136 * <p>Return the component family to which this component belongs.</p>
137 */
138 public String getFamily() {
139
140 return "org.apache.struts.faces.Form";
141
142 }
143
144
145 /***
146 * <p>Return the focus element name.</p>
147 */
148 public String getFocus() {
149
150 if (this.focus != null) {
151 return (this.focus);
152 }
153 ValueBinding vb = getValueBinding("focus");
154 if (vb != null) {
155 return ((String) vb.getValue(getFacesContext()));
156 } else {
157 return (null);
158 }
159
160 }
161
162
163 /***
164 * <p>Set the focus element name.</p>
165 *
166 * @param focus The new focus path
167 */
168 public void setFocus(String focus) {
169
170 this.focus = focus;
171
172 }
173
174
175 /***
176 * <p>Return the focus element index.</p>
177 */
178 public String getFocusIndex() {
179
180 if (this.focusIndex != null) {
181 return (this.focusIndex);
182 }
183 ValueBinding vb = getValueBinding("focusIndex");
184 if (vb != null) {
185 return ((String) vb.getValue(getFacesContext()));
186 } else {
187 return (null);
188 }
189
190 }
191
192
193 /***
194 * <p>Set the focus element index.</p>
195 *
196 * @param focusIndex The new focusIndex path
197 */
198 public void setFocusIndex(String focusIndex) {
199
200 this.focusIndex = focusIndex;
201
202 }
203
204
205 /***
206 * <p>Return the JavaScript to execute on form reset.</p>
207 */
208 public String getOnreset() {
209
210 if (this.onreset != null) {
211 return (this.onreset);
212 }
213 ValueBinding vb = getValueBinding("onreset");
214 if (vb != null) {
215 return ((String) vb.getValue(getFacesContext()));
216 } else {
217 return (null);
218 }
219
220 }
221
222
223 /***
224 * <p>Set the JavaScript to execute on form reset.</p>
225 *
226 * @param onreset The new onreset path
227 */
228 public void setOnreset(String onreset) {
229
230 this.onreset = onreset;
231
232 }
233
234
235 /***
236 * <p>Return the JavaScript to execute on form submit.</p>
237 */
238 public String getOnsubmit() {
239
240 if (this.onsubmit != null) {
241 return (this.onsubmit);
242 }
243 ValueBinding vb = getValueBinding("onsubmit");
244 if (vb != null) {
245 return ((String) vb.getValue(getFacesContext()));
246 } else {
247 return (null);
248 }
249
250 }
251
252
253 /***
254 * <p>Set the JavaScript to execute on form submit.</p>
255 *
256 * @param onsubmit The new onsubmit path
257 */
258 public void setOnsubmit(String onsubmit) {
259
260 this.onsubmit = onsubmit;
261
262 }
263
264
265 /***
266 * <p>Return the CSS style(s) to be rendered for this component.</p>
267 */
268 public String getStyle() {
269
270 ValueBinding vb = getValueBinding("style");
271 if (vb != null) {
272 return (String) vb.getValue(getFacesContext());
273 } else {
274 return style;
275 }
276
277 }
278
279
280 /***
281 * <p>Set the CSS style(s) to be rendered for this component.</p>
282 *
283 * @param style The new CSS style(s)
284 */
285 public void setStyle(String style) {
286
287 this.style = style;
288
289 }
290
291
292 /***
293 * <p>Return the CSS style class(es) to be rendered for this component.</p>
294 */
295 public String getStyleClass() {
296
297 ValueBinding vb = getValueBinding("styleClass");
298 if (vb != null) {
299 return (String) vb.getValue(getFacesContext());
300 } else {
301 return styleClass;
302 }
303
304 }
305
306
307 /***
308 * <p>Set the CSS style class(es) to be rendered for this component.</p>
309 *
310 * @param styleClass The new CSS style class(es)
311 */
312 public void setStyleClass(String styleClass) {
313
314 this.styleClass = styleClass;
315
316 }
317
318
319 /***
320 * <p>Return the target frame for the response to this form submit.</p>
321 */
322 public String getTarget() {
323
324 ValueBinding vb = getValueBinding("target");
325 if (vb != null) {
326 return (String) vb.getValue(getFacesContext());
327 } else {
328 return target;
329 }
330
331 }
332
333
334 /***
335 * <p>Set the target frame for the response to this form submit.</p>
336 *
337 * @param target The new CSS target(s)
338 */
339 public void setTarget(String target) {
340
341 this.target = target;
342
343 }
344
345
346
347
348
349 /***
350 * <p>Create an instance of the form bean (if necessary) before
351 * delegating to the standard decoding process.</p>
352 *
353 * @param context FacesContext for the request we are processing
354 */
355 public void processDecodes(FacesContext context) {
356
357 if (context == null) {
358 throw new NullPointerException();
359 }
360
361 if (log.isDebugEnabled()) {
362 log.debug("processDecodes(" + getClientId(context) + ")");
363 }
364
365
366 Map params = context.getExternalContext().getRequestParameterMap();
367 if (params.containsKey(getClientId(context))) {
368 createActionForm(context);
369 }
370
371
372 super.processDecodes(context);
373
374 }
375
376
377 /***
378 * <p>Restore our state from the specified object.</p>
379 *
380 * @param context <code>FacesContext</code> for the current request
381 * @param state Object containing our saved state
382 */
383 public void restoreState(FacesContext context, Object state) {
384
385 Object values[] = (Object[]) state;
386 super.restoreState(context, values[0]);
387 action = (String) values[1];
388 enctype = (String) values[2];
389 focus = (String) values[3];
390 focusIndex = (String) values[4];
391 onreset = (String) values[5];
392 onsubmit = (String) values[6];
393 style = (String) values[7];
394 styleClass = (String) values[8];
395 target = (String) values[9];
396
397 }
398
399
400 /***
401 * <p>Create and return an object representing our state to be saved.</p>
402 *
403 * @param context <code>FacesContext</code> for the current request
404 */
405 public Object saveState(FacesContext context) {
406
407 Object values[] = new Object[10];
408 values[0] = super.saveState(context);
409 values[1] = action;
410 values[2] = enctype;
411 values[3] = focus;
412 values[4] = focusIndex;
413 values[5] = onreset;
414 values[6] = onsubmit;
415 values[7] = style;
416 values[8] = styleClass;
417 values[9] = target;
418 return (values);
419
420 }
421
422
423
424
425
426
427 /***
428 * <p>Create an appropriate form bean in the appropriate scope, if one
429 * does not already exist.</p>
430 *
431 * @param context FacesContext for the current request
432 *
433 * @exception IllegalArgumentException if no ActionConfig for the
434 * specified action attribute can be located
435 * @exception IllegalArgumentException if no FormBeanConfig for the
436 * specified form bean can be located
437 * @exception IllegalArgumentException if no ModuleConfig can be
438 * located for this application module
439 */
440 public void createActionForm(FacesContext context) {
441
442
443 ModuleConfig moduleConfig = lookupModuleConfig(context);
444
445
446 String action = getAction();
447 ActionConfig actionConfig = moduleConfig.findActionConfig(action);
448 if (actionConfig == null) {
449 throw new IllegalArgumentException("Cannot find action '" +
450 action + "' configuration");
451 }
452
453
454 String name = actionConfig.getName();
455 if (name == null) {
456 return;
457 }
458
459
460 FormBeanConfig fbConfig = moduleConfig.findFormBeanConfig(name);
461 if (fbConfig == null) {
462 throw new IllegalArgumentException("Cannot find form bean '" +
463 name + "' configuration");
464 }
465
466
467 String attribute = actionConfig.getAttribute();
468 String scope = actionConfig.getScope();
469 ActionForm instance = null;
470 if ("request".equals(scope)) {
471 instance = (ActionForm)
472 context.getExternalContext().getRequestMap().get(attribute);
473 } else if ("session".equals(scope)) {
474 HttpSession session = (HttpSession)
475 context.getExternalContext().getSession(true);
476 instance = (ActionForm)
477 context.getExternalContext().getSessionMap().get(attribute);
478 }
479 if (instance != null) {
480 if (fbConfig.getDynamic()) {
481 String className =
482 ((DynaBean) instance).getDynaClass().getName();
483 if (className.equals(fbConfig.getName())) {
484 if (log.isDebugEnabled()) {
485 log.debug
486 (" Recycling existing DynaActionForm instance " +
487 "of type '" + className + "'");
488 }
489 return;
490 }
491 } else {
492 try {
493 Class configClass =
494 RequestUtils.applicationClass(fbConfig.getType());
495 if (configClass.isAssignableFrom(instance.getClass())) {
496 if (log.isDebugEnabled()) {
497 log.debug
498 (" Recycling existing ActionForm instance " +
499 "of class '" + instance.getClass().getName()
500 + "'");
501 }
502 return;
503 }
504 } catch (Throwable t) {
505 throw new IllegalArgumentException
506 ("Cannot load form bean class '" +
507 fbConfig.getType() + "'");
508 }
509 }
510 }
511
512
513 if (fbConfig.getDynamic()) {
514 try {
515 DynaActionFormClass dynaClass =
516 DynaActionFormClass.createDynaActionFormClass(fbConfig);
517 instance = (ActionForm) dynaClass.newInstance();
518 if (log.isDebugEnabled()) {
519 log.debug
520 (" Creating new DynaActionForm instance " +
521 "of type '" + fbConfig.getType() + "'");
522 log.trace(" --> " + instance);
523 }
524 } catch (Throwable t) {
525 throw new IllegalArgumentException
526 ("Cannot create form bean of type '" +
527 fbConfig.getType() + "'");
528 }
529 } else {
530 try {
531 instance = (ActionForm)
532 RequestUtils.applicationInstance(fbConfig.getType());
533 if (log.isDebugEnabled()) {
534 log.debug
535 (" Creating new ActionForm instance " +
536 "of type '" + fbConfig.getType() + "'");
537 log.trace(" --> " + instance);
538 }
539 } catch (Throwable t) {
540 throw new IllegalArgumentException
541 ("Cannot create form bean of class '" +
542 fbConfig.getType() + "'");
543 }
544 }
545
546
547 ActionServlet servlet = (ActionServlet)
548 context.getExternalContext().getApplicationMap().get
549 (Globals.ACTION_SERVLET_KEY);
550 instance.setServlet(servlet);
551 if ("request".equals(scope)) {
552 context.getExternalContext().getRequestMap().put
553 (attribute, instance);
554 } else if ("session".equals(scope)) {
555 context.getExternalContext().getSessionMap().put
556 (attribute, instance);
557 }
558
559 }
560
561
562 /***
563 * <p>Return the <code>ModuleConfig</code> for the application module
564 * this form is being processed for.</p>
565 *
566 * @param context The <code>FacesContext</code> for the current request
567 *
568 * @exception IllegalArgumentException if no <code>ModuleConfig</code>
569 * can be found
570 */
571 public ModuleConfig lookupModuleConfig(FacesContext context) {
572
573
574 ModuleConfig modConfig = (ModuleConfig)
575 context.getExternalContext().getRequestMap().get
576 (Globals.MODULE_KEY);
577 if (modConfig == null) {
578 modConfig = (ModuleConfig)
579 context.getExternalContext().getApplicationMap().get
580 (Globals.MODULE_KEY);
581 }
582 if (modConfig == null) {
583 throw new IllegalArgumentException
584 ("Cannot find module configuration");
585 }
586 return (modConfig);
587
588 }
589
590
591 }