Home » apache-ant-1.7.1-src » org.apache.tools » ant » [javadoc | source]
    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    *
   17    */
   18   
   19   package org.apache.tools.ant;
   20   
   21   import java.lang.reflect.Method;
   22   import org.apache.tools.ant.dispatch.Dispatchable;
   23   import org.apache.tools.ant.dispatch.DispatchUtils;
   24   
   25   /**
   26    * Uses introspection to "adapt" an arbitrary Bean which doesn't
   27    * itself extend Task, but still contains an execute method and optionally
   28    * a setProject method.
   29    *
   30    */
   31   public class TaskAdapter extends Task implements TypeAdapter {
   32   
   33       /** Object to act as a proxy for. */
   34       private Object proxy;
   35   
   36       /**
   37        * No-arg constructor for reflection.
   38        */
   39       public TaskAdapter() {
   40       }
   41   
   42       /**
   43        * Constructor for given proxy.
   44        * So you could write easier code
   45        * <pre>
   46        * myTaskContainer.addTask( new TaskAdapter(myProxy) );
   47        * </pre>
   48        *
   49        * @param proxy The object which Ant should use as task.
   50        */
   51       public TaskAdapter(Object proxy) {
   52           this();
   53           setProxy(proxy);
   54       }
   55   
   56       /**
   57        * Checks whether or not a class is suitable to be adapted by TaskAdapter.
   58        * If the class is of type Dispatchable, the check is not performed because
   59        * the method that will be executed will be determined only at runtime of
   60        * the actual task and not during parse time.
   61        *
   62        * This only checks conditions which are additionally required for
   63        * tasks adapted by TaskAdapter. Thus, this method should be called by
   64        * Project.checkTaskClass.
   65        *
   66        * Throws a BuildException and logs as Project.MSG_ERR for
   67        * conditions that will cause the task execution to fail.
   68        * Logs other suspicious conditions with Project.MSG_WARN.
   69        *
   70        * @param taskClass Class to test for suitability.
   71        *                  Must not be <code>null</code>.
   72        * @param project   Project to log warnings/errors to.
   73        *                  Must not be <code>null</code>.
   74        *
   75        * @see Project#checkTaskClass(Class)
   76        */
   77       public static void checkTaskClass(final Class taskClass,
   78                                         final Project project) {
   79           if (!Dispatchable.class.isAssignableFrom(taskClass)) {
   80               // don't have to check for interface, since then
   81               // taskClass would be abstract too.
   82               try {
   83                   final Method executeM = taskClass.getMethod("execute", (Class[]) null);
   84                   // don't have to check for public, since
   85                   // getMethod finds public method only.
   86                   // don't have to check for abstract, since then
   87                   // taskClass would be abstract too.
   88                   if (!Void.TYPE.equals(executeM.getReturnType())) {
   89                       final String message = "return type of execute() should be "
   90                           + "void but was \"" + executeM.getReturnType() + "\" in "
   91                           + taskClass;
   92                       project.log(message, Project.MSG_WARN);
   93                   }
   94               } catch (NoSuchMethodException e) {
   95                   final String message = "No public execute() in " + taskClass;
   96                   project.log(message, Project.MSG_ERR);
   97                   throw new BuildException(message);
   98               } catch (LinkageError e) {
   99                   String message = "Could not load " + taskClass + ": " + e;
  100                   project.log(message, Project.MSG_ERR);
  101                   throw new BuildException(message, e);
  102               }
  103           }
  104       }
  105   
  106       /**
  107        * Check if the proxy class is a valid class to use
  108        * with this adapter.
  109        * The class must have a public no-arg "execute()" method.
  110        * @param proxyClass the class to check.
  111        */
  112       public void checkProxyClass(Class proxyClass) {
  113           checkTaskClass(proxyClass, getProject());
  114       }
  115   
  116       /**
  117        * Executes the proxied task.
  118        *
  119        * @exception BuildException if the project could not be set
  120        * or the method could not be executed.
  121        */
  122       public void execute() throws BuildException {
  123           try {
  124               Method setLocationM = proxy.getClass().getMethod(
  125                   "setLocation", new Class[] {Location.class});
  126               if (setLocationM != null) {
  127                   setLocationM.invoke(proxy, new Object[] {getLocation()});
  128               }
  129           } catch (NoSuchMethodException e) {
  130               // ignore this if the class being used as a task does not have
  131               // a set location method.
  132           } catch (Exception ex) {
  133               log("Error setting location in " + proxy.getClass(),
  134                   Project.MSG_ERR);
  135               throw new BuildException(ex);
  136           }
  137   
  138           try {
  139               Method setProjectM = proxy.getClass().getMethod(
  140                   "setProject", new Class[] {Project.class});
  141               if (setProjectM != null) {
  142                   setProjectM.invoke(proxy, new Object[] {getProject()});
  143               }
  144           } catch (NoSuchMethodException e) {
  145               // ignore this if the class being used as a task does not have
  146               // a set project method.
  147           } catch (Exception ex) {
  148               log("Error setting project in " + proxy.getClass(),
  149                   Project.MSG_ERR);
  150               throw new BuildException(ex);
  151           }
  152   
  153           try {
  154               DispatchUtils.execute(proxy);
  155           } catch (BuildException be) {
  156               throw be;
  157           } catch (Exception ex) {
  158               log("Error in " + proxy.getClass(), Project.MSG_VERBOSE);
  159               throw new BuildException(ex);
  160           }
  161       }
  162   
  163       /**
  164        * Sets the target object to proxy for.
  165        *
  166        * @param o The target object. Must not be <code>null</code>.
  167        */
  168       public void setProxy(Object o) {
  169           this.proxy = o;
  170       }
  171   
  172       /**
  173        * Returns the target object being proxied.
  174        *
  175        * @return the target proxy object.
  176        */
  177       public Object getProxy() {
  178           return proxy;
  179       }
  180   
  181   }

Save This Page
Home » apache-ant-1.7.1-src » org.apache.tools » ant » [javadoc | source]