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