View Javadoc

    1   /*
    2    * Copyright 2002,2004 The Apache Software Foundation.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.jelly.tags.core;
    17
    18  import java.lang.reflect.InvocationTargetException;
    19  import java.lang.reflect.Method;
    20  import java.util.ArrayList;
    21  import java.util.List;
    22
    23  import org.apache.commons.jelly.JellyTagException;
    24  import org.apache.commons.jelly.MissingAttributeException;
    25  import org.apache.commons.jelly.TagSupport;
    26  import org.apache.commons.jelly.XMLOutput;
    27  import org.apache.commons.jelly.util.ClassLoaderUtils;
    28
    29  /***
    30    * A Tag which can invoke a static method on a class, without an
    31    * instance of the class being needed.
    32    * <p>
    33    * Like the {@link InvokeTag}, this tag can take a set of
    34    * arguments using the {@link ArgTag}.
    35    * </p>
    36    * <p>
    37    *  The following attributes are required:<br />
    38    * <ul>
    39    *   <li>var - The variable to assign the return of the method call to</li>
    40    *   <li>method - The name of the static method to invoke</li>
    41    *   <li>className - The name of the class containing the static method</li>
    42    * </ul>
    43    * </p>
    44    *
    45    * @author <a href="mailto:robert@bull-enterprises.com>Robert McIntosh</a>
    46    * @version $Revision: 155420 $
    47    */
    48  public class InvokeStaticTag extends TagSupport implements ArgTagParent {
    49
    50      /*** the variable exported */
    51      private String var;
    52
    53      /*** the variable where the method's exception is exported */
    54      private String exceptionVar;
    55
    56      /*** the method to invoke */
    57      private String methodName;
    58
    59      /*** the object to invoke the method on */
    60      private String className;
    61
    62      private List paramTypes = new ArrayList();
    63      private List paramValues = new ArrayList();
    64
    65      public InvokeStaticTag() {
    66      }
    67
    68      /***
    69       * Sets the name of the variable exported by this tag
    70       *
    71       * @param var The variable name
    72       */
    73      public void setVar(String var) {
    74          this.var = var;
    75      }
    76
    77      /*** Sets the name of a variable that exports the exception thrown by
    78       * the method's invocation (if any)
    79       */
    80      public void setExceptionVar(String var) {
    81          this.exceptionVar = var;
    82      }
    83
    84      /***
    85       * Sets the name of the method to invoke
    86       *
    87       * @param method The method name
    88       */
    89      public void setMethod(String methodName) {
    90          this.methodName = methodName;
    91      }
    92
    93      /***
    94       * Sets the fully qualified class name containing the static method
    95       *
    96       * @param className The name of the class
    97       */
    98      public void setClassName(String className) {
    99          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.toArray(new Class[paramTypes.size()]));
    124             Method method = loadClass().getMethod( methodName, types );
    125             Object result = method.invoke( null, values );
    126             if(null != var) {
    127                 context.setVariable(var, result);
    128             }
    129
    130             ArgTag parentArg = (ArgTag)(findAncestorWithClass(ArgTag.class));
    131             if(null != parentArg) {
    132                 parentArg.setValue(result);
    133             }
    134         }
    135         catch (ClassNotFoundException e) {
    136             throw createLoadClassFailedException(e);
    137         }
    138         catch (NoSuchMethodException e) {
    139             throw createLoadClassFailedException(e);
    140         }
    141         catch (IllegalAccessException e) {
    142             throw createLoadClassFailedException(e);
    143         }
    144         catch (InvocationTargetException e) {
    145             if(null != exceptionVar) {
    146                 context.setVariable(exceptionVar,e.getTargetException());
    147             } else {
    148                 throw new JellyTagException("method " + methodName +
    149                     " threw exception: "+ e.getTargetException().getMessage(),
    150                     e.getTargetException() );
    151             }
    152         }
    153         finally {
    154             paramTypes.clear();
    155             paramValues.clear();
    156         }
    157     }
    158
    159     // Tag interface
    160     //-------------------------------------------------------------------------
    161
    162     /***
    163      * Loads the class using either the class loader which loaded me or the
    164      * current threads context class loader
    165      */
    166     protected Class loadClass() throws ClassNotFoundException {
    167         return ClassLoaderUtils.loadClass(className, getClass());
    168     }
    169
    170     /***
    171      * Factory method to create a new JellyTagException instance from a given
    172      * failure exception
    173      * @param e is the exception which occurred attempting to load the class
    174      * @return JellyTagException
    175      */
    176     protected JellyTagException createLoadClassFailedException(Exception e) {
    177         return new JellyTagException(
    178             "Could not load class: " + className + ". Reason: " + e, e
    179         );
    180     }
    181 }
    182