1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts.taglib.html;
19
20 import org.apache.commons.beanutils.BeanUtils;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.struts.Globals;
24 import org.apache.struts.action.ActionMessages;
25 import org.apache.struts.taglib.TagUtils;
26 import org.apache.struts.taglib.logic.IterateTag;
27 import org.apache.struts.util.MessageResources;
28 import org.apache.struts.util.RequestUtils;
29
30 import javax.servlet.jsp.JspException;
31 import javax.servlet.jsp.PageContext;
32 import javax.servlet.jsp.tagext.BodyTagSupport;
33
34 import java.lang.reflect.InvocationTargetException;
35 import java.lang.reflect.Method;
36
37 /***
38 * Base class for tags that render form elements capable of including
39 * JavaScript event handlers and/or CSS Style attributes. This class does not
40 * implement the doStartTag() or doEndTag() methods. Subclasses should provide
41 * appropriate implementations of these.
42 *
43 * @version $Rev: 377073 $ $Date: 2006-02-11 15:32:59 -0700 (Sat, 11 Feb 2006) $
44 */
45 public abstract class BaseHandlerTag extends BodyTagSupport {
46 /***
47 * Commons Logging instance.
48 */
49 private static Log log = LogFactory.getLog(BaseHandlerTag.class);
50
51
52
53 /***
54 * The message resources for this package.
55 */
56 protected static MessageResources messages =
57 MessageResources.getMessageResources(Constants.Package
58 + ".LocalStrings");
59
60
61
62 /***
63 * Access key character.
64 */
65 protected String accesskey = null;
66
67 /***
68 * Tab index value.
69 */
70 protected String tabindex = null;
71
72
73
74 /***
75 * Whether to created indexed names for fields
76 *
77 * @since Struts 1.1
78 */
79 protected boolean indexed = false;
80
81
82
83 /***
84 * Mouse click event.
85 */
86 private String onclick = null;
87
88 /***
89 * Mouse double click event.
90 */
91 private String ondblclick = null;
92
93 /***
94 * Mouse over component event.
95 */
96 private String onmouseover = null;
97
98 /***
99 * Mouse exit component event.
100 */
101 private String onmouseout = null;
102
103 /***
104 * Mouse moved over component event.
105 */
106 private String onmousemove = null;
107
108 /***
109 * Mouse pressed on component event.
110 */
111 private String onmousedown = null;
112
113 /***
114 * Mouse released on component event.
115 */
116 private String onmouseup = null;
117
118
119
120 /***
121 * Key down in component event.
122 */
123 private String onkeydown = null;
124
125 /***
126 * Key released in component event.
127 */
128 private String onkeyup = null;
129
130 /***
131 * Key down and up together in component event.
132 */
133 private String onkeypress = null;
134
135
136
137 /***
138 * Text selected in component event.
139 */
140 private String onselect = null;
141
142 /***
143 * Content changed after component lost focus event.
144 */
145 private String onchange = null;
146
147
148
149 /***
150 * Component lost focus event.
151 */
152 private String onblur = null;
153
154 /***
155 * Component has received focus event.
156 */
157 private String onfocus = null;
158
159 /***
160 * Component is disabled.
161 */
162 private boolean disabled = false;
163
164 /***
165 * Indicates whether 'disabled' is a valid attribute
166 */
167 protected boolean doDisabled = true;
168
169 /***
170 * Component is readonly.
171 */
172 private boolean readonly = false;
173
174 /***
175 * <p>Indicates whether 'readonly' is a valid attribute.</p>
176 *
177 * <p>According to the HTML 4.0 Specification <readonly> is valid
178 * for <input type="text">, <input type="password"> and
179 * <textarea"> elements. Therefore, except for those tags this value
180 * is set to <code>false</code>.</p>
181 */
182 protected boolean doReadonly = false;
183
184
185
186 /***
187 * Style attribute associated with component.
188 */
189 private String style = null;
190
191 /***
192 * Named Style class associated with component.
193 */
194 private String styleClass = null;
195
196 /***
197 * Identifier associated with component.
198 */
199 private String styleId = null;
200
201 /***
202 * The request attribute key for our error messages (if any).
203 */
204 private String errorKey = Globals.ERROR_KEY;
205
206 /***
207 * Style attribute associated with component when errors exist.
208 */
209 private String errorStyle = null;
210
211 /***
212 * Named Style class associated with component when errors exist.
213 */
214 private String errorStyleClass = null;
215
216 /***
217 * Identifier associated with component when errors exist.
218 */
219 private String errorStyleId = null;
220
221
222
223 /***
224 * The alternate text of this element.
225 */
226 private String alt = null;
227
228 /***
229 * The message resources key of the alternate text.
230 */
231 private String altKey = null;
232
233 /***
234 * The name of the message resources bundle for message lookups.
235 */
236 private String bundle = null;
237
238 /***
239 * The name of the session attribute key for our locale.
240 */
241 private String locale = Globals.LOCALE_KEY;
242
243 /***
244 * The advisory title of this element.
245 */
246 private String title = null;
247
248 /***
249 * The message resources key of the advisory title.
250 */
251 private String titleKey = null;
252 private Class loopTagClass = null;
253 private Method loopTagGetStatus = null;
254 private Class loopTagStatusClass = null;
255 private Method loopTagStatusGetIndex = null;
256 private boolean triedJstlInit = false;
257 private boolean triedJstlSuccess = false;
258
259
260
261
262 /***
263 * Sets the accessKey character.
264 */
265 public void setAccesskey(String accessKey) {
266 this.accesskey = accessKey;
267 }
268
269 /***
270 * Returns the accessKey character.
271 */
272 public String getAccesskey() {
273 return (this.accesskey);
274 }
275
276 /***
277 * Sets the tabIndex value.
278 */
279 public void setTabindex(String tabIndex) {
280 this.tabindex = tabIndex;
281 }
282
283 /***
284 * Returns the tabIndex value.
285 */
286 public String getTabindex() {
287 return (this.tabindex);
288 }
289
290
291
292 /***
293 * Sets the indexed value.
294 *
295 * @since Struts 1.1
296 */
297 public void setIndexed(boolean indexed) {
298 this.indexed = indexed;
299 }
300
301 /***
302 * Returns the indexed value.
303 *
304 * @since Struts 1.1
305 */
306 public boolean getIndexed() {
307 return (this.indexed);
308 }
309
310
311
312 /***
313 * Sets the onClick event handler.
314 */
315 public void setOnclick(String onClick) {
316 this.onclick = onClick;
317 }
318
319 /***
320 * Returns the onClick event handler.
321 */
322 public String getOnclick() {
323 return onclick;
324 }
325
326 /***
327 * Sets the onDblClick event handler.
328 */
329 public void setOndblclick(String onDblClick) {
330 this.ondblclick = onDblClick;
331 }
332
333 /***
334 * Returns the onDblClick event handler.
335 */
336 public String getOndblclick() {
337 return ondblclick;
338 }
339
340 /***
341 * Sets the onMouseDown event handler.
342 */
343 public void setOnmousedown(String onMouseDown) {
344 this.onmousedown = onMouseDown;
345 }
346
347 /***
348 * Returns the onMouseDown event handler.
349 */
350 public String getOnmousedown() {
351 return onmousedown;
352 }
353
354 /***
355 * Sets the onMouseUp event handler.
356 */
357 public void setOnmouseup(String onMouseUp) {
358 this.onmouseup = onMouseUp;
359 }
360
361 /***
362 * Returns the onMouseUp event handler.
363 */
364 public String getOnmouseup() {
365 return onmouseup;
366 }
367
368 /***
369 * Sets the onMouseMove event handler.
370 */
371 public void setOnmousemove(String onMouseMove) {
372 this.onmousemove = onMouseMove;
373 }
374
375 /***
376 * Returns the onMouseMove event handler.
377 */
378 public String getOnmousemove() {
379 return onmousemove;
380 }
381
382 /***
383 * Sets the onMouseOver event handler.
384 */
385 public void setOnmouseover(String onMouseOver) {
386 this.onmouseover = onMouseOver;
387 }
388
389 /***
390 * Returns the onMouseOver event handler.
391 */
392 public String getOnmouseover() {
393 return onmouseover;
394 }
395
396 /***
397 * Sets the onMouseOut event handler.
398 */
399 public void setOnmouseout(String onMouseOut) {
400 this.onmouseout = onMouseOut;
401 }
402
403 /***
404 * Returns the onMouseOut event handler.
405 */
406 public String getOnmouseout() {
407 return onmouseout;
408 }
409
410
411
412 /***
413 * Sets the onKeyDown event handler.
414 */
415 public void setOnkeydown(String onKeyDown) {
416 this.onkeydown = onKeyDown;
417 }
418
419 /***
420 * Returns the onKeyDown event handler.
421 */
422 public String getOnkeydown() {
423 return onkeydown;
424 }
425
426 /***
427 * Sets the onKeyUp event handler.
428 */
429 public void setOnkeyup(String onKeyUp) {
430 this.onkeyup = onKeyUp;
431 }
432
433 /***
434 * Returns the onKeyUp event handler.
435 */
436 public String getOnkeyup() {
437 return onkeyup;
438 }
439
440 /***
441 * Sets the onKeyPress event handler.
442 */
443 public void setOnkeypress(String onKeyPress) {
444 this.onkeypress = onKeyPress;
445 }
446
447 /***
448 * Returns the onKeyPress event handler.
449 */
450 public String getOnkeypress() {
451 return onkeypress;
452 }
453
454
455
456 /***
457 * Sets the onChange event handler.
458 */
459 public void setOnchange(String onChange) {
460 this.onchange = onChange;
461 }
462
463 /***
464 * Returns the onChange event handler.
465 */
466 public String getOnchange() {
467 return onchange;
468 }
469
470 /***
471 * Sets the onSelect event handler.
472 */
473 public void setOnselect(String onSelect) {
474 this.onselect = onSelect;
475 }
476
477 /***
478 * Returns the onSelect event handler.
479 */
480 public String getOnselect() {
481 return onselect;
482 }
483
484
485
486 /***
487 * Sets the onBlur event handler.
488 */
489 public void setOnblur(String onBlur) {
490 this.onblur = onBlur;
491 }
492
493 /***
494 * Returns the onBlur event handler.
495 */
496 public String getOnblur() {
497 return onblur;
498 }
499
500 /***
501 * Sets the onFocus event handler.
502 */
503 public void setOnfocus(String onFocus) {
504 this.onfocus = onFocus;
505 }
506
507 /***
508 * Returns the onFocus event handler.
509 */
510 public String getOnfocus() {
511 return onfocus;
512 }
513
514 /***
515 * Sets the disabled event handler.
516 */
517 public void setDisabled(boolean disabled) {
518 this.disabled = disabled;
519 }
520
521 /***
522 * Returns the disabled event handler.
523 */
524 public boolean getDisabled() {
525 return disabled;
526 }
527
528 /***
529 * Sets the readonly event handler.
530 */
531 public void setReadonly(boolean readonly) {
532 this.readonly = readonly;
533 }
534
535 /***
536 * Returns the readonly event handler.
537 */
538 public boolean getReadonly() {
539 return readonly;
540 }
541
542
543
544 /***
545 * Sets the style attribute.
546 */
547 public void setStyle(String style) {
548 this.style = style;
549 }
550
551 /***
552 * Returns the style attribute.
553 */
554 public String getStyle() {
555 return style;
556 }
557
558 /***
559 * Sets the style class attribute.
560 */
561 public void setStyleClass(String styleClass) {
562 this.styleClass = styleClass;
563 }
564
565 /***
566 * Returns the style class attribute.
567 */
568 public String getStyleClass() {
569 return styleClass;
570 }
571
572 /***
573 * Sets the style id attribute.
574 */
575 public void setStyleId(String styleId) {
576 this.styleId = styleId;
577 }
578
579 /***
580 * Returns the style id attribute.
581 */
582 public String getStyleId() {
583 return styleId;
584 }
585
586 /***
587 * Returns the error key attribute.
588 */
589 public String getErrorKey() {
590 return errorKey;
591 }
592
593 /***
594 * Sets the error key attribute.
595 */
596 public void setErrorKey(String errorKey) {
597 this.errorKey = errorKey;
598 }
599
600 /***
601 * Returns the error style attribute.
602 */
603 public String getErrorStyle() {
604 return errorStyle;
605 }
606
607 /***
608 * Sets the error style attribute.
609 */
610 public void setErrorStyle(String errorStyle) {
611 this.errorStyle = errorStyle;
612 }
613
614 /***
615 * Returns the error style class attribute.
616 */
617 public String getErrorStyleClass() {
618 return errorStyleClass;
619 }
620
621 /***
622 * Sets the error style class attribute.
623 */
624 public void setErrorStyleClass(String errorStyleClass) {
625 this.errorStyleClass = errorStyleClass;
626 }
627
628 /***
629 * Returns the error style id attribute.
630 */
631 public String getErrorStyleId() {
632 return errorStyleId;
633 }
634
635 /***
636 * Sets the error style id attribute.
637 */
638 public void setErrorStyleId(String errorStyleId) {
639 this.errorStyleId = errorStyleId;
640 }
641
642
643
644 /***
645 * Returns the alternate text attribute.
646 */
647 public String getAlt() {
648 return alt;
649 }
650
651 /***
652 * Sets the alternate text attribute.
653 */
654 public void setAlt(String alt) {
655 this.alt = alt;
656 }
657
658 /***
659 * Returns the message resources key of the alternate text.
660 */
661 public String getAltKey() {
662 return altKey;
663 }
664
665 /***
666 * Sets the message resources key of the alternate text.
667 */
668 public void setAltKey(String altKey) {
669 this.altKey = altKey;
670 }
671
672 /***
673 * Returns the name of the message resources bundle to use.
674 */
675 public String getBundle() {
676 return bundle;
677 }
678
679 /***
680 * Sets the name of the message resources bundle to use.
681 */
682 public void setBundle(String bundle) {
683 this.bundle = bundle;
684 }
685
686 /***
687 * Returns the name of the session attribute for our locale.
688 */
689 public String getLocale() {
690 return locale;
691 }
692
693 /***
694 * Sets the name of the session attribute for our locale.
695 */
696 public void setLocale(String locale) {
697 this.locale = locale;
698 }
699
700 /***
701 * Returns the advisory title attribute.
702 */
703 public String getTitle() {
704 return title;
705 }
706
707 /***
708 * Sets the advisory title attribute.
709 */
710 public void setTitle(String title) {
711 this.title = title;
712 }
713
714 /***
715 * Returns the message resources key of the advisory title.
716 */
717 public String getTitleKey() {
718 return titleKey;
719 }
720
721 /***
722 * Sets the message resources key of the advisory title.
723 */
724 public void setTitleKey(String titleKey) {
725 this.titleKey = titleKey;
726 }
727
728
729
730 /***
731 * Release any acquired resources.
732 */
733 public void release() {
734 super.release();
735 accesskey = null;
736 alt = null;
737 altKey = null;
738 bundle = null;
739 errorKey = Globals.ERROR_KEY;
740 errorStyle = null;
741 errorStyleClass = null;
742 errorStyleId = null;
743 indexed = false;
744 locale = Globals.LOCALE_KEY;
745 onclick = null;
746 ondblclick = null;
747 onmouseover = null;
748 onmouseout = null;
749 onmousemove = null;
750 onmousedown = null;
751 onmouseup = null;
752 onkeydown = null;
753 onkeyup = null;
754 onkeypress = null;
755 onselect = null;
756 onchange = null;
757 onblur = null;
758 onfocus = null;
759 disabled = false;
760 readonly = false;
761 style = null;
762 styleClass = null;
763 styleId = null;
764 tabindex = null;
765 title = null;
766 titleKey = null;
767 }
768
769
770
771 /***
772 * Return the text specified by the literal value or the message resources
773 * key, if any; otherwise return <code>null</code>.
774 *
775 * @param literal Literal text value or <code>null</code>
776 * @param key Message resources key or <code>null</code>
777 * @throws JspException if both arguments are non-null
778 */
779 protected String message(String literal, String key)
780 throws JspException {
781 if (literal != null) {
782 if (key != null) {
783 JspException e =
784 new JspException(messages.getMessage("common.both"));
785
786 TagUtils.getInstance().saveException(pageContext, e);
787 throw e;
788 } else {
789 return (literal);
790 }
791 } else {
792 if (key != null) {
793 return TagUtils.getInstance().message(pageContext, getBundle(),
794 getLocale(), key);
795 } else {
796 return null;
797 }
798 }
799 }
800
801 private Integer getJstlLoopIndex() {
802 if (!triedJstlInit) {
803 triedJstlInit = true;
804
805 try {
806 loopTagClass =
807 RequestUtils.applicationClass(
808 "javax.servlet.jsp.jstl.core.LoopTag");
809
810 loopTagGetStatus =
811 loopTagClass.getDeclaredMethod("getLoopStatus", null);
812
813 loopTagStatusClass =
814 RequestUtils.applicationClass(
815 "javax.servlet.jsp.jstl.core.LoopTagStatus");
816
817 loopTagStatusGetIndex =
818 loopTagStatusClass.getDeclaredMethod("getIndex", null);
819
820 triedJstlSuccess = true;
821 } catch (ClassNotFoundException ex) {
822
823 } catch (NoSuchMethodException ex) {
824 }
825 }
826
827 if (triedJstlSuccess) {
828 try {
829 Object loopTag =
830 findAncestorWithClass(this, loopTagClass);
831
832 if (loopTag == null) {
833 return null;
834 }
835
836 Object status = loopTagGetStatus.invoke(loopTag, null);
837
838 return (Integer) loopTagStatusGetIndex.invoke(status, null);
839 } catch (IllegalAccessException ex) {
840 log.error(ex.getMessage(), ex);
841 } catch (IllegalArgumentException ex) {
842 log.error(ex.getMessage(), ex);
843 } catch (InvocationTargetException ex) {
844 log.error(ex.getMessage(), ex);
845 } catch (NullPointerException ex) {
846 log.error(ex.getMessage(), ex);
847 } catch (ExceptionInInitializerError ex) {
848 log.error(ex.getMessage(), ex);
849 }
850 }
851
852 return null;
853 }
854
855 /***
856 * Appends bean name with index in brackets for tags with 'true' value in
857 * 'indexed' attribute.
858 *
859 * @param handlers The StringBuffer that output will be appended to.
860 * @throws JspException if 'indexed' tag used outside of iterate tag.
861 */
862 protected void prepareIndex(StringBuffer handlers, String name)
863 throws JspException {
864 if (name != null) {
865 handlers.append(name);
866 }
867
868 handlers.append("[");
869 handlers.append(getIndexValue());
870 handlers.append("]");
871
872 if (name != null) {
873 handlers.append(".");
874 }
875 }
876
877 /***
878 * Returns the index value for tags with 'true' value in 'indexed'
879 * attribute.
880 *
881 * @return the index value.
882 * @throws JspException if 'indexed' tag used outside of iterate tag.
883 */
884 protected int getIndexValue()
885 throws JspException {
886
887 IterateTag iterateTag =
888 (IterateTag) findAncestorWithClass(this, IterateTag.class);
889
890 if (iterateTag != null) {
891 return iterateTag.getIndex();
892 }
893
894
895 Integer i = getJstlLoopIndex();
896
897 if (i != null) {
898 return i.intValue();
899 }
900
901
902 JspException e =
903 new JspException(messages.getMessage("indexed.noEnclosingIterate"));
904
905 TagUtils.getInstance().saveException(pageContext, e);
906 throw e;
907 }
908
909 /***
910 * Prepares the style attributes for inclusion in the component's HTML
911 * tag.
912 *
913 * @return The prepared String for inclusion in the HTML tag.
914 * @throws JspException if invalid attributes are specified
915 */
916 protected String prepareStyles()
917 throws JspException {
918 StringBuffer styles = new StringBuffer();
919
920 boolean errorsExist = doErrorsExist();
921
922 if (errorsExist && (getErrorStyleId() != null)) {
923 prepareAttribute(styles, "id", getErrorStyleId());
924 } else {
925 prepareAttribute(styles, "id", getStyleId());
926 }
927
928 if (errorsExist && (getErrorStyle() != null)) {
929 prepareAttribute(styles, "style", getErrorStyle());
930 } else {
931 prepareAttribute(styles, "style", getStyle());
932 }
933
934 if (errorsExist && (getErrorStyleClass() != null)) {
935 prepareAttribute(styles, "class", getErrorStyleClass());
936 } else {
937 prepareAttribute(styles, "class", getStyleClass());
938 }
939
940 prepareAttribute(styles, "title", message(getTitle(), getTitleKey()));
941 prepareAttribute(styles, "alt", message(getAlt(), getAltKey()));
942
943 return styles.toString();
944 }
945
946 /***
947 * Determine if there are errors for the component.
948 *
949 * @return Whether errors exist.
950 */
951 protected boolean doErrorsExist()
952 throws JspException {
953 boolean errorsExist = false;
954
955 if ((getErrorStyleId() != null) || (getErrorStyle() != null)
956 || (getErrorStyleClass() != null)) {
957 String actualName = prepareName();
958
959 if (actualName != null) {
960 ActionMessages errors =
961 TagUtils.getInstance().getActionMessages(pageContext,
962 errorKey);
963
964 errorsExist = ((errors != null)
965 && (errors.size(actualName) > 0));
966 }
967 }
968
969 return errorsExist;
970 }
971
972 /***
973 * Prepares the actual name of the component.
974 *
975 * @return The actual component name.
976 */
977 protected String prepareName()
978 throws JspException {
979 return null;
980 }
981
982 /***
983 * Prepares the event handlers for inclusion in the component's HTML tag.
984 *
985 * @return The prepared String for inclusion in the HTML tag.
986 */
987 protected String prepareEventHandlers() {
988 StringBuffer handlers = new StringBuffer();
989
990 prepareMouseEvents(handlers);
991 prepareKeyEvents(handlers);
992 prepareTextEvents(handlers);
993 prepareFocusEvents(handlers);
994
995 return handlers.toString();
996 }
997
998 /***
999 * Prepares the mouse event handlers, appending them to the the given
1000 * StringBuffer.
1001 *
1002 * @param handlers The StringBuffer that output will be appended to.
1003 */
1004 protected void prepareMouseEvents(StringBuffer handlers) {
1005 prepareAttribute(handlers, "onclick", getOnclick());
1006 prepareAttribute(handlers, "ondblclick", getOndblclick());
1007 prepareAttribute(handlers, "onmouseover", getOnmouseover());
1008 prepareAttribute(handlers, "onmouseout", getOnmouseout());
1009 prepareAttribute(handlers, "onmousemove", getOnmousemove());
1010 prepareAttribute(handlers, "onmousedown", getOnmousedown());
1011 prepareAttribute(handlers, "onmouseup", getOnmouseup());
1012 }
1013
1014 /***
1015 * Prepares the keyboard event handlers, appending them to the the given
1016 * StringBuffer.
1017 *
1018 * @param handlers The StringBuffer that output will be appended to.
1019 */
1020 protected void prepareKeyEvents(StringBuffer handlers) {
1021 prepareAttribute(handlers, "onkeydown", getOnkeydown());
1022 prepareAttribute(handlers, "onkeyup", getOnkeyup());
1023 prepareAttribute(handlers, "onkeypress", getOnkeypress());
1024 }
1025
1026 /***
1027 * Prepares the text event handlers, appending them to the the given
1028 * StringBuffer.
1029 *
1030 * @param handlers The StringBuffer that output will be appended to.
1031 */
1032 protected void prepareTextEvents(StringBuffer handlers) {
1033 prepareAttribute(handlers, "onselect", getOnselect());
1034 prepareAttribute(handlers, "onchange", getOnchange());
1035 }
1036
1037 /***
1038 * Prepares the focus event handlers, appending them to the the given
1039 * StringBuffer.
1040 *
1041 * @param handlers The StringBuffer that output will be appended to.
1042 */
1043 protected void prepareFocusEvents(StringBuffer handlers) {
1044 prepareAttribute(handlers, "onblur", getOnblur());
1045 prepareAttribute(handlers, "onfocus", getOnfocus());
1046
1047
1048 FormTag formTag = null;
1049
1050 if ((doDisabled && !getDisabled()) || (doReadonly && !getReadonly())) {
1051 formTag =
1052 (FormTag) pageContext.getAttribute(Constants.FORM_KEY,
1053 PageContext.REQUEST_SCOPE);
1054 }
1055
1056
1057 if (doDisabled) {
1058 boolean formDisabled =
1059 (formTag == null) ? false : formTag.isDisabled();
1060
1061 if (formDisabled || getDisabled()) {
1062 handlers.append(" disabled=\"disabled\"");
1063 }
1064 }
1065
1066
1067 if (doReadonly) {
1068 boolean formReadOnly =
1069 (formTag == null) ? false : formTag.isReadonly();
1070
1071 if (formReadOnly || getReadonly()) {
1072 handlers.append(" readonly=\"readonly\"");
1073 }
1074 }
1075 }
1076
1077 /***
1078 * 'Hook' to enable tags to be extended and additional attributes added.
1079 *
1080 * @param handlers The StringBuffer that output will be appended to.
1081 */
1082 protected void prepareOtherAttributes(StringBuffer handlers) {
1083 }
1084
1085 /***
1086 * Prepares an attribute if the value is not null, appending it to the the
1087 * given StringBuffer.
1088 *
1089 * @param handlers The StringBuffer that output will be appended to.
1090 */
1091 protected void prepareAttribute(StringBuffer handlers, String name,
1092 Object value) {
1093 if (value != null) {
1094 handlers.append(" ");
1095 handlers.append(name);
1096 handlers.append("=\"");
1097 handlers.append(value);
1098 handlers.append("\"");
1099 }
1100 }
1101
1102 /***
1103 * Allows HTML tags to find out if they're nested within an
1104 * %lt;html:html> tag that has xhtml set to true.
1105 *
1106 * @return true if the tag is nested within an html tag with xhtml set to
1107 * true, false otherwise.
1108 * @since Struts 1.1
1109 */
1110 protected boolean isXhtml() {
1111 return TagUtils.getInstance().isXhtml(this.pageContext);
1112 }
1113
1114 /***
1115 * Returns the closing brace for an input element depending on xhtml
1116 * status. The tag must be nested within an %lt;html:html> tag that
1117 * has xhtml set to true.
1118 *
1119 * @return String - > if xhtml is false, /> if xhtml is true
1120 * @since Struts 1.1
1121 */
1122 protected String getElementClose() {
1123 return this.isXhtml() ? " />" : ">";
1124 }
1125
1126 /***
1127 * Searches all scopes for the bean and calls BeanUtils.getProperty() with
1128 * the given arguments and converts any exceptions into JspException.
1129 *
1130 * @param beanName The name of the object to get the property from.
1131 * @param property The name of the property to get.
1132 * @return The value of the property.
1133 * @throws JspException
1134 * @since Struts 1.1
1135 */
1136 protected String lookupProperty(String beanName, String property)
1137 throws JspException {
1138 Object bean =
1139 TagUtils.getInstance().lookup(this.pageContext, beanName, null);
1140
1141 if (bean == null) {
1142 throw new JspException(messages.getMessage("getter.bean", beanName));
1143 }
1144
1145 try {
1146 return BeanUtils.getProperty(bean, property);
1147 } catch (IllegalAccessException e) {
1148 throw new JspException(messages.getMessage("getter.access",
1149 property, beanName));
1150 } catch (InvocationTargetException e) {
1151 Throwable t = e.getTargetException();
1152
1153 throw new JspException(messages.getMessage("getter.result",
1154 property, t.toString()));
1155 } catch (NoSuchMethodException e) {
1156 throw new JspException(messages.getMessage("getter.method",
1157 property, beanName));
1158 }
1159 }
1160 }