001: /*
002: * Copyright 2002,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.jelly.tags.core;
017:
018: import java.lang.reflect.InvocationTargetException;
019: import java.lang.reflect.Method;
020: import java.util.ArrayList;
021: import java.util.List;
022:
023: import org.apache.commons.jelly.JellyTagException;
024: import org.apache.commons.jelly.MissingAttributeException;
025: import org.apache.commons.jelly.TagSupport;
026: import org.apache.commons.jelly.XMLOutput;
027: import org.apache.commons.jelly.util.ClassLoaderUtils;
028:
029: /**
030: * A Tag which can invoke a static method on a class, without an
031: * instance of the class being needed.
032: * <p>
033: * Like the {@link InvokeTag}, this tag can take a set of
034: * arguments using the {@link ArgTag}.
035: * </p>
036: * <p>
037: * The following attributes are required:<br />
038: * <ul>
039: * <li>var - The variable to assign the return of the method call to</li>
040: * <li>method - The name of the static method to invoke</li>
041: * <li>className - The name of the class containing the static method</li>
042: * </ul>
043: * </p>
044: *
045: * @author <a href="mailto:robert@bull-enterprises.com>Robert McIntosh</a>
046: * @version $Revision: 155420 $
047: */
048: public class InvokeStaticTag extends TagSupport implements ArgTagParent {
049:
050: /** the variable exported */
051: private String var;
052:
053: /** the variable where the method's exception is exported */
054: private String exceptionVar;
055:
056: /** the method to invoke */
057: private String methodName;
058:
059: /** the object to invoke the method on */
060: private String className;
061:
062: private List paramTypes = new ArrayList();
063: private List paramValues = new ArrayList();
064:
065: public InvokeStaticTag() {
066: }
067:
068: /**
069: * Sets the name of the variable exported by this tag
070: *
071: * @param var The variable name
072: */
073: public void setVar(String var) {
074: this .var = var;
075: }
076:
077: /** Sets the name of a variable that exports the exception thrown by
078: * the method's invocation (if any)
079: */
080: public void setExceptionVar(String var) {
081: this .exceptionVar = var;
082: }
083:
084: /**
085: * Sets the name of the method to invoke
086: *
087: * @param method The method name
088: */
089: public void setMethod(String methodName) {
090: this .methodName = methodName;
091: }
092:
093: /**
094: * Sets the fully qualified class name containing the static method
095: *
096: * @param className The name of the class
097: */
098: public void setClassName(String className) {
099: this .className = className;
100: }
101:
102: /**
103: * Adds an argument to supply to the method
104: *
105: * @param type The Class type of the argument
106: * @param value The value of the argument
107: */
108: public void addArgument(Class type, Object value) {
109: paramTypes.add(type);
110: paramValues.add(value);
111: }
112:
113: // Tag interface
114: //-------------------------------------------------------------------------
115: public void doTag(XMLOutput output) throws JellyTagException {
116: try {
117: if (null == methodName) {
118: throw new MissingAttributeException("method");
119: }
120: invokeBody(output);
121:
122: Object[] values = paramValues.toArray();
123: Class[] types = (Class[]) (paramTypes
124: .toArray(new Class[paramTypes.size()]));
125: Method method = loadClass().getMethod(methodName, types);
126: Object result = method.invoke(null, values);
127: if (null != var) {
128: context.setVariable(var, result);
129: }
130:
131: ArgTag parentArg = (ArgTag) (findAncestorWithClass(ArgTag.class));
132: if (null != parentArg) {
133: parentArg.setValue(result);
134: }
135: } catch (ClassNotFoundException e) {
136: throw createLoadClassFailedException(e);
137: } catch (NoSuchMethodException e) {
138: throw createLoadClassFailedException(e);
139: } catch (IllegalAccessException e) {
140: throw createLoadClassFailedException(e);
141: } catch (InvocationTargetException e) {
142: if (null != exceptionVar) {
143: context.setVariable(exceptionVar, e
144: .getTargetException());
145: } else {
146: throw new JellyTagException("method " + methodName
147: + " threw exception: "
148: + e.getTargetException().getMessage(), e
149: .getTargetException());
150: }
151: } finally {
152: paramTypes.clear();
153: paramValues.clear();
154: }
155: }
156:
157: // Tag interface
158: //-------------------------------------------------------------------------
159:
160: /**
161: * Loads the class using either the class loader which loaded me or the
162: * current threads context class loader
163: */
164: protected Class loadClass() throws ClassNotFoundException {
165: return ClassLoaderUtils.loadClass(className, getClass());
166: }
167:
168: /**
169: * Factory method to create a new JellyTagException instance from a given
170: * failure exception
171: * @param e is the exception which occurred attempting to load the class
172: * @return JellyTagException
173: */
174: protected JellyTagException createLoadClassFailedException(
175: Exception e) {
176: return new JellyTagException("Could not load class: "
177: + className + ". Reason: " + e, e);
178: }
179: }
|