Coverage Report - org.apache.commons.workflow.core.InvokeStep
 
Classes in this File Line Coverage Branch Coverage Complexity
InvokeStep
0%
0/74
0%
0/26
3
 
 1  
 /*
 2  
  * Copyright 1999-2001,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  
 
 17  
 package org.apache.commons.workflow.core;
 18  
 
 19  
 
 20  
 import java.lang.reflect.InvocationTargetException;
 21  
 import java.lang.reflect.Method;
 22  
 import java.util.ArrayList;
 23  
 import org.apache.commons.jxpath.JXPathContext;
 24  
 import org.apache.commons.workflow.Context;
 25  
 import org.apache.commons.workflow.Descriptor;
 26  
 import org.apache.commons.workflow.StepException;
 27  
 import org.apache.commons.workflow.base.DescriptorStep;
 28  
 
 29  
 
 30  
 /**
 31  
  * <p>Call the specified method of the specified bean in the specified
 32  
  * scope, passing arguments as specified by associated <code>Descriptor</code>
 33  
  * objects.  The <strong>first</strong> associated <code>Descriptor</code>
 34  
  * identifies the Java object on whom method invocation shall take place.</p>
 35  
  *
 36  
  * <p><strong>FIXME</strong> - Better way to deal with exceptions???</p>
 37  
  *
 38  
  * <p>Supported Attributes:</p>
 39  
  * <ul>
 40  
  * <li><strong>method</strong> - Name of the public method to be called
 41  
  *     on the bean specified by either <code>name</code> and
 42  
  *     <code>scope</code>, or by <code>xpath</code>.</li>
 43  
  * </ul>
 44  
  *
 45  
  * @version $Revision: 155475 $ $Date: 2005-02-26 13:31:11 +0000 (Sat, 26 Feb 2005) $
 46  
  * @author Craig R. McClanahan
 47  
  */
 48  
 
 49  
 public class InvokeStep extends DescriptorStep {
 50  
 
 51  
 
 52  
     // ----------------------------------------------------------= Constructors
 53  
 
 54  
 
 55  
     /**
 56  
      * Construct a default instance of this Step.
 57  
      */
 58  
     public InvokeStep() {
 59  
 
 60  0
         super();
 61  
 
 62  0
     }
 63  
 
 64  
 
 65  
     /**
 66  
      * Construct an instance of this Step with the specified identifier.
 67  
      *
 68  
      * @param id Step identifier
 69  
      */
 70  
     public InvokeStep(String id) {
 71  
 
 72  0
         super();
 73  0
         setId(id);
 74  
 
 75  0
     }
 76  
 
 77  
 
 78  
     /**
 79  
      * Construct a fully configured instance of this Step.
 80  
      *
 81  
      * @param id Step identifier
 82  
      * @param method Method name
 83  
      */
 84  
     public InvokeStep(String id, String method) {
 85  
 
 86  0
         super();
 87  0
         setId(id);
 88  0
         setMethod(method);
 89  
 
 90  0
     }
 91  
 
 92  
 
 93  
     /**
 94  
      * Construct a fully configured instance of this Step.
 95  
      *
 96  
      * @param id Step identifier
 97  
      * @param method Method name
 98  
      * @param descriptor Descriptor for the bean on which to invoke
 99  
      */
 100  
     public InvokeStep(String id, String method, Descriptor descriptor) {
 101  
 
 102  0
         super();
 103  0
         setId(id);
 104  0
         setMethod(method);
 105  0
         addDescriptor(descriptor);
 106  
 
 107  0
     }
 108  
 
 109  
 
 110  
     // ------------------------------------------------------------- Properties
 111  
 
 112  
 
 113  
     /**
 114  
      * The method name to be invoked.
 115  
      */
 116  0
     protected String method = null;
 117  
 
 118  
     public String getMethod() {
 119  0
         return (this.method);
 120  
     }
 121  
 
 122  
     public void setMethod(String method) {
 123  0
         this.method = method;
 124  0
     }
 125  
 
 126  
 
 127  
     // --------------------------------------------------------- Public Methods
 128  
 
 129  
 
 130  
     /**
 131  
      * Perform the executable actions related to this Step, in the context of
 132  
      * the specified Context.
 133  
      *
 134  
      * @param context The Context that is tracking our execution state
 135  
      *
 136  
      * @exception StepException if a processing error has occurred
 137  
      */
 138  
     public void execute(Context context) throws StepException {
 139  
 
 140  
         // Identify the object on whom a method is to be invoked
 141  0
         Descriptor descriptors[] = findDescriptors();
 142  0
         if (descriptors.length < 1)
 143  0
             throw new StepException("No object descriptor on which to invoke",
 144  
                                     this);
 145  0
         Object bean = descriptors[0].get(context);
 146  0
         if (bean == null)
 147  0
             throw new StepException("No object bean on which to invoke",
 148  
                                     this);
 149  
 
 150  
         // Assembe arrays of parameter types and values
 151  0
         Class types[] = new Class[descriptors.length - 1];
 152  0
         Object values[] = new Object[descriptors.length - 1];
 153  0
         for (int i = 1; i < descriptors.length; i++) {
 154  0
             values[i-1] = descriptors[i].get(context);
 155  0
             types[i-1] = descriptors[i].getType();
 156  0
             if (types[i-1] == null) {
 157  0
                 if (values[i-1] == null)
 158  0
                     types[i-1] = Object.class;
 159  
                 else
 160  0
                     types[i-1] = values[i-1].getClass();
 161  
             }
 162  
         }
 163  
 
 164  
         // Identify a compatible method signature on the bean
 165  0
         Method method = findMethod(bean, this.method, types);
 166  0
         if (method == null)
 167  0
             throw new StepException("No available method " +
 168  
                                     signature(this.method, types),
 169  
                                     this);
 170  
 
 171  
         // Invoke the requested method on the requested bean
 172  
         // FIXME - better way to deal with exceptions?
 173  
         try {
 174  0
             Class clazz = method.getReturnType();
 175  0
             if ((clazz != null) && (clazz != Void.TYPE)) {
 176  0
                 Object result = method.invoke(bean, values);
 177  0
                 context.push(result);
 178  0
             } else {
 179  0
                 method.invoke(bean, values);
 180  
             }
 181  0
         } catch (InvocationTargetException t) {
 182  0
             Throwable cause = t.getTargetException();
 183  0
             throw new StepException("Invoke exception", cause, this);
 184  0
         } catch (Throwable t) {
 185  0
             throw new StepException("Invoke exception", t, this);
 186  0
         }
 187  
 
 188  0
     }
 189  
 
 190  
 
 191  
     /**
 192  
      * Render a string representation of this Step.
 193  
      */
 194  
     public String toString() {
 195  
 
 196  0
         StringBuffer sb = new StringBuffer("<core:invoke");
 197  0
         if (getId() != null) {
 198  0
             sb.append(" id=\"");
 199  0
             sb.append(getId());
 200  0
             sb.append("\"");
 201  
         }
 202  0
         sb.append(" method=\"");
 203  0
         sb.append(getMethod());
 204  0
         sb.append("\"");
 205  0
         sb.append(">");
 206  0
         Descriptor descriptors[] = findDescriptors();
 207  0
         for (int i = 0; i < descriptors.length; i++)
 208  0
             sb.append(descriptors[i].toString());
 209  0
         sb.append("</core:invoke>");
 210  0
         return (sb.toString());
 211  
 
 212  
     }
 213  
 
 214  
 
 215  
     // ------------------------------------------------------ Protected Methods
 216  
 
 217  
 
 218  
     /**
 219  
      * Return a <code>Method</code> of the specified <code>Class</code> with
 220  
      * the specified method name, that takes the specified parameter types,
 221  
      * if there is one.  Otherwise, return <code>null</code>.
 222  
      *
 223  
      * @param bean Bean on which method searching is to be done
 224  
      * @param name Method name to search for
 225  
      * @param types Parameter types to search for
 226  
      */
 227  
     protected Method findMethod(Object bean, String name, Class types[]) {
 228  
 
 229  
         try {
 230  0
             return (bean.getClass().getMethod(name, types));
 231  0
         } catch (NoSuchMethodException e) {
 232  0
             return (null);
 233  
         }
 234  
 
 235  
     }
 236  
 
 237  
 
 238  
     /**
 239  
      * Return a method signature useful in debugging and exception messages.
 240  
      *
 241  
      * @param name Method name
 242  
      * @param types Parameter types
 243  
      */
 244  
     protected String signature(String name, Class types[]) {
 245  
 
 246  0
         StringBuffer sb = new StringBuffer(name);
 247  0
         sb.append('(');
 248  0
         for (int i = 0; i < types.length; i++) {
 249  0
             if (i > 0)
 250  0
                 sb.append(',');
 251  0
             sb.append(types[i].getName());
 252  
         }
 253  0
         sb.append(')');
 254  0
         return (sb.toString());
 255  
 
 256  
     }
 257  
 
 258  
 
 259  
 }