0001: /*
0002: * $Id: BaseHandlerTag.java 479633 2006-11-27 14:25:35Z pbenedict $
0003: *
0004: * Licensed to the Apache Software Foundation (ASF) under one
0005: * or more contributor license agreements. See the NOTICE file
0006: * distributed with this work for additional information
0007: * regarding copyright ownership. The ASF licenses this file
0008: * to you under the Apache License, Version 2.0 (the
0009: * "License"); you may not use this file except in compliance
0010: * with the License. You may obtain a copy of the License at
0011: *
0012: * http://www.apache.org/licenses/LICENSE-2.0
0013: *
0014: * Unless required by applicable law or agreed to in writing,
0015: * software distributed under the License is distributed on an
0016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0017: * KIND, either express or implied. See the License for the
0018: * specific language governing permissions and limitations
0019: * under the License.
0020: */
0021: package org.apache.struts.taglib.html;
0022:
0023: import org.apache.commons.beanutils.BeanUtils;
0024: import org.apache.commons.logging.Log;
0025: import org.apache.commons.logging.LogFactory;
0026: import org.apache.struts.Globals;
0027: import org.apache.struts.action.ActionMessages;
0028: import org.apache.struts.taglib.TagUtils;
0029: import org.apache.struts.taglib.logic.IterateTag;
0030: import org.apache.struts.util.MessageResources;
0031: import org.apache.struts.util.RequestUtils;
0032:
0033: import javax.servlet.jsp.JspException;
0034: import javax.servlet.jsp.PageContext;
0035: import javax.servlet.jsp.tagext.BodyTagSupport;
0036:
0037: import java.lang.reflect.InvocationTargetException;
0038: import java.lang.reflect.Method;
0039:
0040: /**
0041: * Base class for tags that render form elements capable of including
0042: * JavaScript event handlers and/or CSS Style attributes. This class does not
0043: * implement the doStartTag() or doEndTag() methods. Subclasses should provide
0044: * appropriate implementations of these.
0045: *
0046: * @version $Rev: 479633 $ $Date: 2006-11-27 08:25:35 -0600 (Mon, 27 Nov 2006) $
0047: */
0048: public abstract class BaseHandlerTag extends BodyTagSupport {
0049: /**
0050: * Commons Logging instance.
0051: */
0052: private static Log log = LogFactory.getLog(BaseHandlerTag.class);
0053:
0054: // ----------------------------------------------------- Instance Variables
0055:
0056: /**
0057: * The message resources for this package.
0058: */
0059: protected static MessageResources messages = MessageResources
0060: .getMessageResources(Constants.Package + ".LocalStrings");
0061:
0062: // Navigation Management
0063:
0064: /**
0065: * Access key character.
0066: */
0067: protected String accesskey = null;
0068:
0069: /**
0070: * Tab index value.
0071: */
0072: protected String tabindex = null;
0073:
0074: // Indexing ability for Iterate
0075:
0076: /**
0077: * Whether to created indexed names for fields
0078: *
0079: * @since Struts 1.1
0080: */
0081: protected boolean indexed = false;
0082:
0083: // Mouse Events
0084:
0085: /**
0086: * Mouse click event.
0087: */
0088: private String onclick = null;
0089:
0090: /**
0091: * Mouse double click event.
0092: */
0093: private String ondblclick = null;
0094:
0095: /**
0096: * Mouse over component event.
0097: */
0098: private String onmouseover = null;
0099:
0100: /**
0101: * Mouse exit component event.
0102: */
0103: private String onmouseout = null;
0104:
0105: /**
0106: * Mouse moved over component event.
0107: */
0108: private String onmousemove = null;
0109:
0110: /**
0111: * Mouse pressed on component event.
0112: */
0113: private String onmousedown = null;
0114:
0115: /**
0116: * Mouse released on component event.
0117: */
0118: private String onmouseup = null;
0119:
0120: // Keyboard Events
0121:
0122: /**
0123: * Key down in component event.
0124: */
0125: private String onkeydown = null;
0126:
0127: /**
0128: * Key released in component event.
0129: */
0130: private String onkeyup = null;
0131:
0132: /**
0133: * Key down and up together in component event.
0134: */
0135: private String onkeypress = null;
0136:
0137: // Text Events
0138:
0139: /**
0140: * Text selected in component event.
0141: */
0142: private String onselect = null;
0143:
0144: /**
0145: * Content changed after component lost focus event.
0146: */
0147: private String onchange = null;
0148:
0149: // Focus Events and States
0150:
0151: /**
0152: * Component lost focus event.
0153: */
0154: private String onblur = null;
0155:
0156: /**
0157: * Component has received focus event.
0158: */
0159: private String onfocus = null;
0160:
0161: /**
0162: * Component is disabled.
0163: */
0164: private boolean disabled = false;
0165:
0166: /**
0167: * Indicates whether 'disabled' is a valid attribute
0168: */
0169: protected boolean doDisabled = true;
0170:
0171: /**
0172: * Component is readonly.
0173: */
0174: private boolean readonly = false;
0175:
0176: /**
0177: * <p>Indicates whether 'readonly' is a valid attribute.</p>
0178: *
0179: * <p>According to the HTML 4.0 Specification <readonly> is valid
0180: * for <input type="text">, <input type="password"> and
0181: * <textarea"> elements. Therefore, except for those tags this value
0182: * is set to <code>false</code>.</p>
0183: */
0184: protected boolean doReadonly = false;
0185:
0186: // CSS Style Support
0187:
0188: /**
0189: * Style attribute associated with component.
0190: */
0191: private String style = null;
0192:
0193: /**
0194: * Named Style class associated with component.
0195: */
0196: private String styleClass = null;
0197:
0198: /**
0199: * Identifier associated with component.
0200: */
0201: private String styleId = null;
0202:
0203: /**
0204: * The request attribute key for our error messages (if any).
0205: */
0206: private String errorKey = Globals.ERROR_KEY;
0207:
0208: /**
0209: * Style attribute associated with component when errors exist.
0210: */
0211: private String errorStyle = null;
0212:
0213: /**
0214: * Named Style class associated with component when errors exist.
0215: */
0216: private String errorStyleClass = null;
0217:
0218: /**
0219: * Identifier associated with component when errors exist.
0220: */
0221: private String errorStyleId = null;
0222:
0223: // Other Common Attributes
0224:
0225: /**
0226: * The alternate text of this element.
0227: */
0228: private String alt = null;
0229:
0230: /**
0231: * The message resources key of the alternate text.
0232: */
0233: private String altKey = null;
0234:
0235: /**
0236: * The name of the message resources bundle for message lookups.
0237: */
0238: private String bundle = null;
0239:
0240: /**
0241: * The name of the session attribute key for our locale.
0242: */
0243: private String locale = Globals.LOCALE_KEY;
0244:
0245: /**
0246: * The advisory title of this element.
0247: */
0248: private String title = null;
0249:
0250: /**
0251: * The language code of this element.
0252: */
0253: private String lang = null;
0254:
0255: /**
0256: * The direction for weak/neutral text of this element.
0257: */
0258: private String dir = null;
0259:
0260: /**
0261: * The message resources key of the advisory title.
0262: */
0263: private String titleKey = null;
0264: private Class loopTagClass = null;
0265: private Method loopTagGetStatus = null;
0266: private Class loopTagStatusClass = null;
0267: private Method loopTagStatusGetIndex = null;
0268: private boolean triedJstlInit = false;
0269: private boolean triedJstlSuccess = false;
0270:
0271: // ------------------------------------------------------------- Properties
0272: // Navigation Management
0273:
0274: /**
0275: * Sets the accessKey character.
0276: */
0277: public void setAccesskey(String accessKey) {
0278: this .accesskey = accessKey;
0279: }
0280:
0281: /**
0282: * Returns the accessKey character.
0283: */
0284: public String getAccesskey() {
0285: return (this .accesskey);
0286: }
0287:
0288: /**
0289: * Sets the tabIndex value.
0290: */
0291: public void setTabindex(String tabIndex) {
0292: this .tabindex = tabIndex;
0293: }
0294:
0295: /**
0296: * Returns the tabIndex value.
0297: */
0298: public String getTabindex() {
0299: return (this .tabindex);
0300: }
0301:
0302: // Indexing ability for Iterate [since Struts 1.1]
0303:
0304: /**
0305: * Sets the indexed value.
0306: *
0307: * @since Struts 1.1
0308: */
0309: public void setIndexed(boolean indexed) {
0310: this .indexed = indexed;
0311: }
0312:
0313: /**
0314: * Returns the indexed value.
0315: *
0316: * @since Struts 1.1
0317: */
0318: public boolean getIndexed() {
0319: return (this .indexed);
0320: }
0321:
0322: // Mouse Events
0323:
0324: /**
0325: * Sets the onClick event handler.
0326: */
0327: public void setOnclick(String onClick) {
0328: this .onclick = onClick;
0329: }
0330:
0331: /**
0332: * Returns the onClick event handler.
0333: */
0334: public String getOnclick() {
0335: return onclick;
0336: }
0337:
0338: /**
0339: * Sets the onDblClick event handler.
0340: */
0341: public void setOndblclick(String onDblClick) {
0342: this .ondblclick = onDblClick;
0343: }
0344:
0345: /**
0346: * Returns the onDblClick event handler.
0347: */
0348: public String getOndblclick() {
0349: return ondblclick;
0350: }
0351:
0352: /**
0353: * Sets the onMouseDown event handler.
0354: */
0355: public void setOnmousedown(String onMouseDown) {
0356: this .onmousedown = onMouseDown;
0357: }
0358:
0359: /**
0360: * Returns the onMouseDown event handler.
0361: */
0362: public String getOnmousedown() {
0363: return onmousedown;
0364: }
0365:
0366: /**
0367: * Sets the onMouseUp event handler.
0368: */
0369: public void setOnmouseup(String onMouseUp) {
0370: this .onmouseup = onMouseUp;
0371: }
0372:
0373: /**
0374: * Returns the onMouseUp event handler.
0375: */
0376: public String getOnmouseup() {
0377: return onmouseup;
0378: }
0379:
0380: /**
0381: * Sets the onMouseMove event handler.
0382: */
0383: public void setOnmousemove(String onMouseMove) {
0384: this .onmousemove = onMouseMove;
0385: }
0386:
0387: /**
0388: * Returns the onMouseMove event handler.
0389: */
0390: public String getOnmousemove() {
0391: return onmousemove;
0392: }
0393:
0394: /**
0395: * Sets the onMouseOver event handler.
0396: */
0397: public void setOnmouseover(String onMouseOver) {
0398: this .onmouseover = onMouseOver;
0399: }
0400:
0401: /**
0402: * Returns the onMouseOver event handler.
0403: */
0404: public String getOnmouseover() {
0405: return onmouseover;
0406: }
0407:
0408: /**
0409: * Sets the onMouseOut event handler.
0410: */
0411: public void setOnmouseout(String onMouseOut) {
0412: this .onmouseout = onMouseOut;
0413: }
0414:
0415: /**
0416: * Returns the onMouseOut event handler.
0417: */
0418: public String getOnmouseout() {
0419: return onmouseout;
0420: }
0421:
0422: // Keyboard Events
0423:
0424: /**
0425: * Sets the onKeyDown event handler.
0426: */
0427: public void setOnkeydown(String onKeyDown) {
0428: this .onkeydown = onKeyDown;
0429: }
0430:
0431: /**
0432: * Returns the onKeyDown event handler.
0433: */
0434: public String getOnkeydown() {
0435: return onkeydown;
0436: }
0437:
0438: /**
0439: * Sets the onKeyUp event handler.
0440: */
0441: public void setOnkeyup(String onKeyUp) {
0442: this .onkeyup = onKeyUp;
0443: }
0444:
0445: /**
0446: * Returns the onKeyUp event handler.
0447: */
0448: public String getOnkeyup() {
0449: return onkeyup;
0450: }
0451:
0452: /**
0453: * Sets the onKeyPress event handler.
0454: */
0455: public void setOnkeypress(String onKeyPress) {
0456: this .onkeypress = onKeyPress;
0457: }
0458:
0459: /**
0460: * Returns the onKeyPress event handler.
0461: */
0462: public String getOnkeypress() {
0463: return onkeypress;
0464: }
0465:
0466: // Text Events
0467:
0468: /**
0469: * Sets the onChange event handler.
0470: */
0471: public void setOnchange(String onChange) {
0472: this .onchange = onChange;
0473: }
0474:
0475: /**
0476: * Returns the onChange event handler.
0477: */
0478: public String getOnchange() {
0479: return onchange;
0480: }
0481:
0482: /**
0483: * Sets the onSelect event handler.
0484: */
0485: public void setOnselect(String onSelect) {
0486: this .onselect = onSelect;
0487: }
0488:
0489: /**
0490: * Returns the onSelect event handler.
0491: */
0492: public String getOnselect() {
0493: return onselect;
0494: }
0495:
0496: // Focus Events and States
0497:
0498: /**
0499: * Sets the onBlur event handler.
0500: */
0501: public void setOnblur(String onBlur) {
0502: this .onblur = onBlur;
0503: }
0504:
0505: /**
0506: * Returns the onBlur event handler.
0507: */
0508: public String getOnblur() {
0509: return onblur;
0510: }
0511:
0512: /**
0513: * Sets the onFocus event handler.
0514: */
0515: public void setOnfocus(String onFocus) {
0516: this .onfocus = onFocus;
0517: }
0518:
0519: /**
0520: * Returns the onFocus event handler.
0521: */
0522: public String getOnfocus() {
0523: return onfocus;
0524: }
0525:
0526: /**
0527: * Sets the disabled event handler.
0528: */
0529: public void setDisabled(boolean disabled) {
0530: this .disabled = disabled;
0531: }
0532:
0533: /**
0534: * Returns the disabled event handler.
0535: */
0536: public boolean getDisabled() {
0537: return disabled;
0538: }
0539:
0540: /**
0541: * Sets the readonly event handler.
0542: */
0543: public void setReadonly(boolean readonly) {
0544: this .readonly = readonly;
0545: }
0546:
0547: /**
0548: * Returns the readonly event handler.
0549: */
0550: public boolean getReadonly() {
0551: return readonly;
0552: }
0553:
0554: // CSS Style Support
0555:
0556: /**
0557: * Sets the style attribute.
0558: */
0559: public void setStyle(String style) {
0560: this .style = style;
0561: }
0562:
0563: /**
0564: * Returns the style attribute.
0565: */
0566: public String getStyle() {
0567: return style;
0568: }
0569:
0570: /**
0571: * Sets the style class attribute.
0572: */
0573: public void setStyleClass(String styleClass) {
0574: this .styleClass = styleClass;
0575: }
0576:
0577: /**
0578: * Returns the style class attribute.
0579: */
0580: public String getStyleClass() {
0581: return styleClass;
0582: }
0583:
0584: /**
0585: * Sets the style id attribute.
0586: */
0587: public void setStyleId(String styleId) {
0588: this .styleId = styleId;
0589: }
0590:
0591: /**
0592: * Returns the style id attribute.
0593: */
0594: public String getStyleId() {
0595: return styleId;
0596: }
0597:
0598: /**
0599: * Returns the error key attribute.
0600: */
0601: public String getErrorKey() {
0602: return errorKey;
0603: }
0604:
0605: /**
0606: * Sets the error key attribute.
0607: */
0608: public void setErrorKey(String errorKey) {
0609: this .errorKey = errorKey;
0610: }
0611:
0612: /**
0613: * Returns the error style attribute.
0614: */
0615: public String getErrorStyle() {
0616: return errorStyle;
0617: }
0618:
0619: /**
0620: * Sets the error style attribute.
0621: */
0622: public void setErrorStyle(String errorStyle) {
0623: this .errorStyle = errorStyle;
0624: }
0625:
0626: /**
0627: * Returns the error style class attribute.
0628: */
0629: public String getErrorStyleClass() {
0630: return errorStyleClass;
0631: }
0632:
0633: /**
0634: * Sets the error style class attribute.
0635: */
0636: public void setErrorStyleClass(String errorStyleClass) {
0637: this .errorStyleClass = errorStyleClass;
0638: }
0639:
0640: /**
0641: * Returns the error style id attribute.
0642: */
0643: public String getErrorStyleId() {
0644: return errorStyleId;
0645: }
0646:
0647: /**
0648: * Sets the error style id attribute.
0649: */
0650: public void setErrorStyleId(String errorStyleId) {
0651: this .errorStyleId = errorStyleId;
0652: }
0653:
0654: // Other Common Elements
0655:
0656: /**
0657: * Returns the alternate text attribute.
0658: */
0659: public String getAlt() {
0660: return alt;
0661: }
0662:
0663: /**
0664: * Sets the alternate text attribute.
0665: */
0666: public void setAlt(String alt) {
0667: this .alt = alt;
0668: }
0669:
0670: /**
0671: * Returns the message resources key of the alternate text.
0672: */
0673: public String getAltKey() {
0674: return altKey;
0675: }
0676:
0677: /**
0678: * Sets the message resources key of the alternate text.
0679: */
0680: public void setAltKey(String altKey) {
0681: this .altKey = altKey;
0682: }
0683:
0684: /**
0685: * Returns the name of the message resources bundle to use.
0686: */
0687: public String getBundle() {
0688: return bundle;
0689: }
0690:
0691: /**
0692: * Sets the name of the message resources bundle to use.
0693: */
0694: public void setBundle(String bundle) {
0695: this .bundle = bundle;
0696: }
0697:
0698: /**
0699: * Returns the name of the session attribute for our locale.
0700: */
0701: public String getLocale() {
0702: return locale;
0703: }
0704:
0705: /**
0706: * Sets the name of the session attribute for our locale.
0707: */
0708: public void setLocale(String locale) {
0709: this .locale = locale;
0710: }
0711:
0712: /**
0713: * Returns the advisory title attribute.
0714: */
0715: public String getTitle() {
0716: return title;
0717: }
0718:
0719: /**
0720: * Sets the advisory title attribute.
0721: */
0722: public void setTitle(String title) {
0723: this .title = title;
0724: }
0725:
0726: /**
0727: * Returns the message resources key of the advisory title.
0728: */
0729: public String getTitleKey() {
0730: return titleKey;
0731: }
0732:
0733: /**
0734: * Sets the message resources key of the advisory title.
0735: */
0736: public void setTitleKey(String titleKey) {
0737: this .titleKey = titleKey;
0738: }
0739:
0740: /**
0741: * Returns the language code of this element.
0742: *
0743: * @since Struts 1.3.6
0744: */
0745: public String getLang() {
0746: return this .lang;
0747: }
0748:
0749: /**
0750: * Sets the language code of this element.
0751: *
0752: * @since Struts 1.3.6
0753: */
0754: public void setLang(String lang) {
0755: this .lang = lang;
0756: }
0757:
0758: /**
0759: * Returns the direction for weak/neutral text this element.
0760: *
0761: * @since Struts 1.3.6
0762: */
0763: public String getDir() {
0764: return this .dir;
0765: }
0766:
0767: /**
0768: * Sets the direction for weak/neutral text of this element.
0769: *
0770: * @since Struts 1.3.6
0771: */
0772: public void setDir(String dir) {
0773: this .dir = dir;
0774: }
0775:
0776: // --------------------------------------------------------- Public Methods
0777:
0778: /**
0779: * Release any acquired resources.
0780: */
0781: public void release() {
0782: super .release();
0783: accesskey = null;
0784: alt = null;
0785: altKey = null;
0786: bundle = null;
0787: dir = null;
0788: errorKey = Globals.ERROR_KEY;
0789: errorStyle = null;
0790: errorStyleClass = null;
0791: errorStyleId = null;
0792: indexed = false;
0793: lang = null;
0794: locale = Globals.LOCALE_KEY;
0795: onclick = null;
0796: ondblclick = null;
0797: onmouseover = null;
0798: onmouseout = null;
0799: onmousemove = null;
0800: onmousedown = null;
0801: onmouseup = null;
0802: onkeydown = null;
0803: onkeyup = null;
0804: onkeypress = null;
0805: onselect = null;
0806: onchange = null;
0807: onblur = null;
0808: onfocus = null;
0809: disabled = false;
0810: readonly = false;
0811: style = null;
0812: styleClass = null;
0813: styleId = null;
0814: tabindex = null;
0815: title = null;
0816: titleKey = null;
0817: }
0818:
0819: // ------------------------------------------------------ Protected Methods
0820:
0821: /**
0822: * Return the text specified by the literal value or the message resources
0823: * key, if any; otherwise return <code>null</code>.
0824: *
0825: * @param literal Literal text value or <code>null</code>
0826: * @param key Message resources key or <code>null</code>
0827: * @throws JspException if both arguments are non-null
0828: */
0829: protected String message(String literal, String key)
0830: throws JspException {
0831: if (literal != null) {
0832: if (key != null) {
0833: JspException e = new JspException(messages
0834: .getMessage("common.both"));
0835:
0836: TagUtils.getInstance().saveException(pageContext, e);
0837: throw e;
0838: } else {
0839: return (literal);
0840: }
0841: } else {
0842: if (key != null) {
0843: return TagUtils.getInstance().message(pageContext,
0844: getBundle(), getLocale(), key);
0845: } else {
0846: return null;
0847: }
0848: }
0849: }
0850:
0851: private Integer getJstlLoopIndex() {
0852: if (!triedJstlInit) {
0853: triedJstlInit = true;
0854:
0855: try {
0856: loopTagClass = RequestUtils
0857: .applicationClass("javax.servlet.jsp.jstl.core.LoopTag");
0858:
0859: loopTagGetStatus = loopTagClass.getDeclaredMethod(
0860: "getLoopStatus", null);
0861:
0862: loopTagStatusClass = RequestUtils
0863: .applicationClass("javax.servlet.jsp.jstl.core.LoopTagStatus");
0864:
0865: loopTagStatusGetIndex = loopTagStatusClass
0866: .getDeclaredMethod("getIndex", null);
0867:
0868: triedJstlSuccess = true;
0869: } catch (ClassNotFoundException ex) {
0870: // These just mean that JSTL isn't loaded, so ignore
0871: } catch (NoSuchMethodException ex) {
0872: }
0873: }
0874:
0875: if (triedJstlSuccess) {
0876: try {
0877: Object loopTag = findAncestorWithClass(this ,
0878: loopTagClass);
0879:
0880: if (loopTag == null) {
0881: return null;
0882: }
0883:
0884: Object status = loopTagGetStatus.invoke(loopTag, null);
0885:
0886: return (Integer) loopTagStatusGetIndex.invoke(status,
0887: null);
0888: } catch (IllegalAccessException ex) {
0889: log.error(ex.getMessage(), ex);
0890: } catch (IllegalArgumentException ex) {
0891: log.error(ex.getMessage(), ex);
0892: } catch (InvocationTargetException ex) {
0893: log.error(ex.getMessage(), ex);
0894: } catch (NullPointerException ex) {
0895: log.error(ex.getMessage(), ex);
0896: } catch (ExceptionInInitializerError ex) {
0897: log.error(ex.getMessage(), ex);
0898: }
0899: }
0900:
0901: return null;
0902: }
0903:
0904: /**
0905: * Appends bean name with index in brackets for tags with 'true' value in
0906: * 'indexed' attribute.
0907: *
0908: * @param handlers The StringBuffer that output will be appended to.
0909: * @throws JspException if 'indexed' tag used outside of iterate tag.
0910: */
0911: protected void prepareIndex(StringBuffer handlers, String name)
0912: throws JspException {
0913: if (name != null) {
0914: handlers.append(name);
0915: }
0916:
0917: handlers.append("[");
0918: handlers.append(getIndexValue());
0919: handlers.append("]");
0920:
0921: if (name != null) {
0922: handlers.append(".");
0923: }
0924: }
0925:
0926: /**
0927: * Returns the index value for tags with 'true' value in 'indexed'
0928: * attribute.
0929: *
0930: * @return the index value.
0931: * @throws JspException if 'indexed' tag used outside of iterate tag.
0932: */
0933: protected int getIndexValue() throws JspException {
0934: // look for outer iterate tag
0935: IterateTag iterateTag = (IterateTag) findAncestorWithClass(
0936: this , IterateTag.class);
0937:
0938: if (iterateTag != null) {
0939: return iterateTag.getIndex();
0940: }
0941:
0942: // Look for JSTL loops
0943: Integer i = getJstlLoopIndex();
0944:
0945: if (i != null) {
0946: return i.intValue();
0947: }
0948:
0949: // this tag should be nested in an IterateTag or JSTL loop tag, if it's not, throw exception
0950: JspException e = new JspException(messages
0951: .getMessage("indexed.noEnclosingIterate"));
0952:
0953: TagUtils.getInstance().saveException(pageContext, e);
0954: throw e;
0955: }
0956:
0957: /**
0958: * Prepares the style attributes for inclusion in the component's HTML
0959: * tag.
0960: *
0961: * @return The prepared String for inclusion in the HTML tag.
0962: * @throws JspException if invalid attributes are specified
0963: */
0964: protected String prepareStyles() throws JspException {
0965: StringBuffer styles = new StringBuffer();
0966:
0967: boolean errorsExist = doErrorsExist();
0968:
0969: if (errorsExist && (getErrorStyleId() != null)) {
0970: prepareAttribute(styles, "id", getErrorStyleId());
0971: } else {
0972: prepareAttribute(styles, "id", getStyleId());
0973: }
0974:
0975: if (errorsExist && (getErrorStyle() != null)) {
0976: prepareAttribute(styles, "style", getErrorStyle());
0977: } else {
0978: prepareAttribute(styles, "style", getStyle());
0979: }
0980:
0981: if (errorsExist && (getErrorStyleClass() != null)) {
0982: prepareAttribute(styles, "class", getErrorStyleClass());
0983: } else {
0984: prepareAttribute(styles, "class", getStyleClass());
0985: }
0986:
0987: prepareAttribute(styles, "title", message(getTitle(),
0988: getTitleKey()));
0989: prepareAttribute(styles, "alt", message(getAlt(), getAltKey()));
0990: prepareInternationalization(styles);
0991:
0992: return styles.toString();
0993: }
0994:
0995: /**
0996: * Determine if there are errors for the component.
0997: *
0998: * @return Whether errors exist.
0999: */
1000: protected boolean doErrorsExist() throws JspException {
1001: boolean errorsExist = false;
1002:
1003: if ((getErrorStyleId() != null) || (getErrorStyle() != null)
1004: || (getErrorStyleClass() != null)) {
1005: String actualName = prepareName();
1006:
1007: if (actualName != null) {
1008: ActionMessages errors = TagUtils.getInstance()
1009: .getActionMessages(pageContext, errorKey);
1010:
1011: errorsExist = ((errors != null) && (errors
1012: .size(actualName) > 0));
1013: }
1014: }
1015:
1016: return errorsExist;
1017: }
1018:
1019: /**
1020: * Prepares the actual name of the component.
1021: *
1022: * @return The actual component name.
1023: */
1024: protected String prepareName() throws JspException {
1025: return null;
1026: }
1027:
1028: /**
1029: * Prepares the event handlers for inclusion in the component's HTML tag.
1030: *
1031: * @return The prepared String for inclusion in the HTML tag.
1032: */
1033: protected String prepareEventHandlers() {
1034: StringBuffer handlers = new StringBuffer();
1035:
1036: prepareMouseEvents(handlers);
1037: prepareKeyEvents(handlers);
1038: prepareTextEvents(handlers);
1039: prepareFocusEvents(handlers);
1040:
1041: return handlers.toString();
1042: }
1043:
1044: /**
1045: * Prepares the mouse event handlers, appending them to the the given
1046: * StringBuffer.
1047: *
1048: * @param handlers The StringBuffer that output will be appended to.
1049: */
1050: protected void prepareMouseEvents(StringBuffer handlers) {
1051: prepareAttribute(handlers, "onclick", getOnclick());
1052: prepareAttribute(handlers, "ondblclick", getOndblclick());
1053: prepareAttribute(handlers, "onmouseover", getOnmouseover());
1054: prepareAttribute(handlers, "onmouseout", getOnmouseout());
1055: prepareAttribute(handlers, "onmousemove", getOnmousemove());
1056: prepareAttribute(handlers, "onmousedown", getOnmousedown());
1057: prepareAttribute(handlers, "onmouseup", getOnmouseup());
1058: }
1059:
1060: /**
1061: * Prepares the keyboard event handlers, appending them to the the given
1062: * StringBuffer.
1063: *
1064: * @param handlers The StringBuffer that output will be appended to.
1065: */
1066: protected void prepareKeyEvents(StringBuffer handlers) {
1067: prepareAttribute(handlers, "onkeydown", getOnkeydown());
1068: prepareAttribute(handlers, "onkeyup", getOnkeyup());
1069: prepareAttribute(handlers, "onkeypress", getOnkeypress());
1070: }
1071:
1072: /**
1073: * Prepares the text event handlers, appending them to the the given
1074: * StringBuffer.
1075: *
1076: * @param handlers The StringBuffer that output will be appended to.
1077: */
1078: protected void prepareTextEvents(StringBuffer handlers) {
1079: prepareAttribute(handlers, "onselect", getOnselect());
1080: prepareAttribute(handlers, "onchange", getOnchange());
1081: }
1082:
1083: /**
1084: * Prepares the focus event handlers, appending them to the the given
1085: * StringBuffer.
1086: *
1087: * @param handlers The StringBuffer that output will be appended to.
1088: */
1089: protected void prepareFocusEvents(StringBuffer handlers) {
1090: prepareAttribute(handlers, "onblur", getOnblur());
1091: prepareAttribute(handlers, "onfocus", getOnfocus());
1092:
1093: // Get the parent FormTag (if necessary)
1094: FormTag formTag = null;
1095:
1096: if ((doDisabled && !getDisabled())
1097: || (doReadonly && !getReadonly())) {
1098: formTag = (FormTag) pageContext.getAttribute(
1099: Constants.FORM_KEY, PageContext.REQUEST_SCOPE);
1100: }
1101:
1102: // Format Disabled
1103: if (doDisabled) {
1104: boolean formDisabled = (formTag == null) ? false : formTag
1105: .isDisabled();
1106:
1107: if (formDisabled || getDisabled()) {
1108: handlers.append(" disabled=\"disabled\"");
1109: }
1110: }
1111:
1112: // Format Read Only
1113: if (doReadonly) {
1114: boolean formReadOnly = (formTag == null) ? false : formTag
1115: .isReadonly();
1116:
1117: if (formReadOnly || getReadonly()) {
1118: handlers.append(" readonly=\"readonly\"");
1119: }
1120: }
1121: }
1122:
1123: /**
1124: * Prepares the internationalization attribtes, appending them to the the given
1125: * StringBuffer.
1126: *
1127: * @param handlers The StringBuffer that output will be appended to.
1128: * @since Struts 1.3.6
1129: */
1130: protected void prepareInternationalization(StringBuffer handlers) {
1131: prepareAttribute(handlers, "lang", getLang());
1132: prepareAttribute(handlers, "dir", getDir());
1133: }
1134:
1135: /**
1136: * 'Hook' to enable tags to be extended and additional attributes added.
1137: *
1138: * @param handlers The StringBuffer that output will be appended to.
1139: */
1140: protected void prepareOtherAttributes(StringBuffer handlers) {
1141: }
1142:
1143: /**
1144: * Prepares an attribute if the value is not null, appending it to the the
1145: * given StringBuffer.
1146: *
1147: * @param handlers The StringBuffer that output will be appended to.
1148: */
1149: protected void prepareAttribute(StringBuffer handlers, String name,
1150: Object value) {
1151: if (value != null) {
1152: handlers.append(" ");
1153: handlers.append(name);
1154: handlers.append("=\"");
1155: handlers.append(value);
1156: handlers.append("\"");
1157: }
1158: }
1159:
1160: /**
1161: * Allows HTML tags to find out if they're nested within an
1162: * %lt;html:html> tag that has xhtml set to true.
1163: *
1164: * @return true if the tag is nested within an html tag with xhtml set to
1165: * true, false otherwise.
1166: * @since Struts 1.1
1167: */
1168: protected boolean isXhtml() {
1169: return TagUtils.getInstance().isXhtml(this .pageContext);
1170: }
1171:
1172: /**
1173: * Returns the closing brace for an input element depending on xhtml
1174: * status. The tag must be nested within an %lt;html:html> tag that
1175: * has xhtml set to true.
1176: *
1177: * @return String - > if xhtml is false, /> if xhtml is true
1178: * @since Struts 1.1
1179: */
1180: protected String getElementClose() {
1181: return this .isXhtml() ? " />" : ">";
1182: }
1183:
1184: /**
1185: * Searches all scopes for the bean and calls BeanUtils.getProperty() with
1186: * the given arguments and converts any exceptions into JspException.
1187: *
1188: * @param beanName The name of the object to get the property from.
1189: * @param property The name of the property to get.
1190: * @return The value of the property.
1191: * @throws JspException
1192: * @since Struts 1.1
1193: */
1194: protected String lookupProperty(String beanName, String property)
1195: throws JspException {
1196: Object bean = TagUtils.getInstance().lookup(this .pageContext,
1197: beanName, null);
1198:
1199: if (bean == null) {
1200: throw new JspException(messages.getMessage("getter.bean",
1201: beanName));
1202: }
1203:
1204: try {
1205: return BeanUtils.getProperty(bean, property);
1206: } catch (IllegalAccessException e) {
1207: throw new JspException(messages.getMessage("getter.access",
1208: property, beanName));
1209: } catch (InvocationTargetException e) {
1210: Throwable t = e.getTargetException();
1211:
1212: throw new JspException(messages.getMessage("getter.result",
1213: property, t.toString()));
1214: } catch (NoSuchMethodException e) {
1215: throw new JspException(messages.getMessage("getter.method",
1216: property, beanName));
1217: }
1218: }
1219: }
|