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