001: package com.mockrunner.tag;
002:
003: import java.io.IOException;
004: import java.util.Iterator;
005: import java.util.List;
006: import java.util.Map;
007:
008: //import javax.servlet.jsp.JspContext;
009: import javax.servlet.jsp.JspException;
010: import javax.servlet.jsp.PageContext;
011: import javax.servlet.jsp.tagext.BodyTag; //import javax.servlet.jsp.tagext.DynamicAttributes;
012: //import javax.servlet.jsp.tagext.SimpleTag;
013: import javax.servlet.jsp.tagext.Tag;
014: import javax.servlet.jsp.tagext.TryCatchFinally;
015:
016: import org.apache.commons.beanutils.BeanUtils;
017: import org.apache.commons.beanutils.PropertyUtils;
018:
019: import com.mockrunner.base.NestedApplicationException;
020: import com.mockrunner.util.common.StringUtil;
021:
022: /**
023: * Util class for tag test framework.
024: * Please note, that the methods of this class take
025: * <code>Object</code> parameters where <code>JspTag</code>
026: * or <code>JspContext</code> would be suitable. The reason is,
027: * that these classes do not exist in J2EE 1.3. This class is
028: * usable with J2EE 1.3 and J2EE 1.4.
029: */
030: public class TagUtil {
031: /**
032: * Creates an {@link com.mockrunner.tag.NestedTag} instance wrapping the
033: * specified tag. Returns an instance of {@link com.mockrunner.tag.NestedStandardTag}
034: * or {@link com.mockrunner.tag.NestedBodyTag} depending on the
035: * type of specified tag.
036: * @param tag the tag class
037: * @param pageContext the corresponding <code>PageContext</code> or <code>JspContext</code>
038: * @param attributes the attribute map
039: * @return the instance of {@link com.mockrunner.tag.NestedTag}
040: * @throws IllegalArgumentException if <code>tag</code> is <code>null</code>
041: */
042: public static Object createNestedTagInstance(Class tag,
043: Object pageContext, Map attributes) {
044: if (null == tag)
045: throw new IllegalArgumentException("tag must not be null");
046: Object tagObject;
047: try {
048: tagObject = tag.newInstance();
049: } catch (Exception exc) {
050: throw new NestedApplicationException(exc);
051: }
052: return createNestedTagInstance(tagObject, pageContext,
053: attributes);
054: }
055:
056: /**
057: * Creates an {@link com.mockrunner.tag.NestedTag} instance wrapping the
058: * specified tag. Returns an instance of {@link com.mockrunner.tag.NestedStandardTag}
059: * or {@link com.mockrunner.tag.NestedBodyTag} depending on the
060: * type of specified tag.
061: * @param tag the tag
062: * @param pageContext the corresponding <code>PageContext</code> or <code>JspContext</code>
063: * @param attributes the attribute map
064: * @return the instance of {@link com.mockrunner.tag.NestedTag}
065: * @throws IllegalArgumentException if <code>tag</code> is <code>null</code>
066: */
067: public static Object createNestedTagInstance(Object tag,
068: Object pageContext, Map attributes) {
069: if (null == tag)
070: throw new IllegalArgumentException("tag must not be null");
071: Object nestedTag = null;
072: if (tag instanceof BodyTag) {
073: checkPageContext(pageContext);
074: nestedTag = new NestedBodyTag((BodyTag) tag,
075: (PageContext) pageContext, attributes);
076: } else if (tag instanceof Tag) {
077: checkPageContext(pageContext);
078: nestedTag = new NestedStandardTag((Tag) tag,
079: (PageContext) pageContext, attributes);
080: }
081: /*else if(tag instanceof SimpleTag)
082: {
083: checkJspContext(pageContext);
084: nestedTag = new NestedSimpleTag((SimpleTag)tag, (JspContext)pageContext, attributes);
085: }*/
086: else {
087: throw new IllegalArgumentException(
088: "tag must be an instance of Tag or SimpleTag");
089: }
090: return nestedTag;
091: }
092:
093: /**
094: * Handles an exception that is thrown during tag lifecycle processing.
095: * Invokes <code>doCatch()</code>, if the tag implements
096: * <code>TryCatchFinally</code>.
097: * @param tag the tag
098: * @param exc the exception to be handled
099: */
100: public static void handleException(Tag tag, Throwable exc)
101: throws JspException {
102: if (tag instanceof TryCatchFinally) {
103: try {
104: ((TryCatchFinally) tag).doCatch(exc);
105: return;
106: } catch (Throwable otherExc) {
107: exc = otherExc;
108: }
109: }
110: if (exc instanceof JspException) {
111: throw ((JspException) exc);
112: }
113: if (exc instanceof RuntimeException) {
114: throw ((RuntimeException) exc);
115: }
116: throw new JspException(exc);
117: }
118:
119: /**
120: * Handles the finally block of tag lifecycle processing.
121: * Invokes <code>doFinally()</code>, if the tag implements
122: * <code>TryCatchFinally</code>.
123: * @param tag the tag
124: */
125: public static void handleFinally(Tag tag) {
126: if (tag instanceof TryCatchFinally) {
127: ((TryCatchFinally) tag).doFinally();
128: }
129: }
130:
131: private static void checkPageContext(Object pageContext) {
132: if (pageContext instanceof PageContext)
133: return;
134: throw new IllegalArgumentException(
135: "pageContext must be an instance of PageContext");
136: }
137:
138: /*private static void checkJspContext(Object pageContext)
139: {
140: if(pageContext instanceof JspContext) return;
141: throw new IllegalArgumentException("pageContext must be an instance of JspContext");
142: }*/
143:
144: /**
145: * Populates the specified attributes to the specified tag.
146: * @param tag the tag
147: * @param attributes the attribute map
148: */
149: public static void populateTag(Object tag, Map attributes) {
150: if (null == attributes || attributes.isEmpty())
151: return;
152: try {
153: Iterator names = attributes.keySet().iterator();
154: while (names.hasNext()) {
155: String currentName = (String) names.next();
156: /*Object currentValue = attributes.get(currentName);
157: if(currentValue instanceof DynamicAttribute)
158: {
159: populateDynamicAttribute(tag, currentName, (DynamicAttribute)currentValue);
160: continue;
161: }*/
162: if (PropertyUtils.isWriteable(tag, currentName)) {
163: BeanUtils.copyProperty(tag, currentName,
164: evaluateValue(attributes.get(currentName)));
165: }
166: /*else if(tag instanceof DynamicAttributes)
167: {
168: populateDynamicAttribute(tag, currentName, new DynamicAttribute(null, currentValue));
169: }*/
170: }
171: } catch (IllegalArgumentException exc) {
172: throw exc;
173: } catch (Exception exc) {
174: throw new NestedApplicationException(exc);
175: }
176: }
177:
178: /*private static void populateDynamicAttribute(Object tag, String name, DynamicAttribute attribute) throws JspException
179: {
180: if(!(tag instanceof DynamicAttributes))
181: {
182: String message = "Attribute " + name + " specified as dynamic attribute but tag ";
183: message += "is not an instance of " + DynamicAttributes.class.getName();
184: throw new IllegalArgumentException(message);
185: }
186: ((DynamicAttributes)tag).setDynamicAttribute(attribute.getUri(), name, evaluateValue(attribute.getValue()));
187: }*/
188:
189: private static Object evaluateValue(Object value) {
190: if (value instanceof RuntimeAttribute) {
191: value = ((RuntimeAttribute) value).evaluate();
192: }
193: return value;
194: }
195:
196: /**
197: * Handles body evaluation of a tag. Iterated through the childs.
198: * If the child is an instance of {@link com.mockrunner.tag.NestedTag},
199: * the {@link com.mockrunner.tag.NestedTag#doLifecycle} method of
200: * this tag is called. If the child is an instance of
201: * {@link com.mockrunner.tag.DynamicChild}, the
202: * {@link com.mockrunner.tag.DynamicChild#evaluate} method is called
203: * and the result is written to the out <code>JspWriter</code> as a
204: * string. If the result is another object (usually a string) it is written
205: * to the out <code>JspWriter</code> (the <code>toString</code> method will
206: * be called).
207: * @param bodyList the list of body entries
208: * @param pageContext the corresponding <code>PageContext</code> or <code>JspContext</code>
209: */
210: public static void evalBody(List bodyList, Object pageContext)
211: throws JspException {
212: for (int ii = 0; ii < bodyList.size(); ii++) {
213: Object nextChild = bodyList.get(ii);
214: if (nextChild instanceof NestedBodyTag) {
215: int result = ((NestedBodyTag) nextChild).doLifecycle();
216: if (Tag.SKIP_PAGE == result)
217: return;
218: } else if (nextChild instanceof NestedStandardTag) {
219: int result = ((NestedStandardTag) nextChild)
220: .doLifecycle();
221: if (Tag.SKIP_PAGE == result)
222: return;
223: }
224: /*else if(nextChild instanceof NestedSimpleTag)
225: {
226: ((NestedSimpleTag)nextChild).doLifecycle();
227: }*/
228: else {
229: try {
230: if (pageContext instanceof PageContext) {
231: ((PageContext) pageContext).getOut().print(
232: getChildText(nextChild));
233: }
234: /*else if(pageContext instanceof JspContext)
235: {
236: ((JspContext)pageContext).getOut().print(getChildText(nextChild));
237: }*/
238: else {
239: throw new IllegalArgumentException(
240: "pageContext must be an instance of JspContext");
241: }
242: } catch (IOException exc) {
243: throw new NestedApplicationException(exc);
244: }
245: }
246: }
247: }
248:
249: private static String getChildText(Object child) {
250: if (null == child)
251: return "null";
252: if (child instanceof DynamicChild) {
253: Object result = ((DynamicChild) child).evaluate();
254: if (null == result)
255: return "null";
256: return result.toString();
257: }
258: return child.toString();
259: }
260:
261: /**
262: * Helper method to dump tags incl. child tags.
263: */
264: public static String dumpTag(NestedTag tag, StringBuffer buffer,
265: int level) {
266: StringUtil.appendTabs(buffer, level);
267: buffer.append("<" + tag.getClass().getName() + ">\n");
268: TagUtil.dumpTagTree(tag.getChilds(), buffer, level);
269: StringUtil.appendTabs(buffer, level);
270: buffer.append("</" + tag.getClass().getName() + ">");
271: return buffer.toString();
272: }
273:
274: /**
275: * Helper method to dump tags incl. child tags.
276: */
277: public static void dumpTagTree(List bodyList, StringBuffer buffer,
278: int level) {
279: for (int ii = 0; ii < bodyList.size(); ii++) {
280: Object nextChild = bodyList.get(ii);
281: if (nextChild instanceof NestedTag) {
282: dumpTag((NestedTag) nextChild, buffer, level + 1);
283: } else {
284: StringUtil.appendTabs(buffer, level + 1);
285: buffer.append(bodyList.get(ii).toString());
286: }
287: buffer.append("\n");
288: }
289: }
290: }
|