You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

TaskAdapter.java 6.5 kB

11 years ago
11 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. package org.apache.tools.ant;
  19. import java.lang.reflect.Method;
  20. import org.apache.tools.ant.dispatch.DispatchUtils;
  21. import org.apache.tools.ant.dispatch.Dispatchable;
  22. /**
  23. * Uses introspection to "adapt" an arbitrary Bean which doesn't
  24. * itself extend Task, but still contains an execute method and optionally
  25. * a setProject method.
  26. *
  27. */
  28. public class TaskAdapter extends Task implements TypeAdapter {
  29. /** Object to act as a proxy for. */
  30. private Object proxy;
  31. /**
  32. * No-arg constructor for reflection.
  33. */
  34. public TaskAdapter() {
  35. }
  36. /**
  37. * Constructor for given proxy.
  38. * So you could write easier code
  39. * <pre>
  40. * myTaskContainer.addTask( new TaskAdapter(myProxy) );
  41. * </pre>
  42. *
  43. * @param proxy The object which Ant should use as task.
  44. */
  45. public TaskAdapter(Object proxy) {
  46. this();
  47. setProxy(proxy);
  48. }
  49. /**
  50. * Checks whether or not a class is suitable to be adapted by TaskAdapter.
  51. * If the class is of type Dispatchable, the check is not performed because
  52. * the method that will be executed will be determined only at runtime of
  53. * the actual task and not during parse time.
  54. *
  55. * This only checks conditions which are additionally required for
  56. * tasks adapted by TaskAdapter. Thus, this method should be called by
  57. * Project.checkTaskClass.
  58. *
  59. * Throws a BuildException and logs as Project.MSG_ERR for
  60. * conditions that will cause the task execution to fail.
  61. * Logs other suspicious conditions with Project.MSG_WARN.
  62. *
  63. * @param taskClass Class to test for suitability.
  64. * Must not be <code>null</code>.
  65. * @param project Project to log warnings/errors to.
  66. * Must not be <code>null</code>.
  67. *
  68. * @see Project#checkTaskClass(Class)
  69. */
  70. public static void checkTaskClass(final Class<?> taskClass,
  71. final Project project) {
  72. if (!Dispatchable.class.isAssignableFrom(taskClass)) {
  73. // don't have to check for interface, since then
  74. // taskClass would be abstract too.
  75. try {
  76. final Method executeM = taskClass.getMethod("execute");
  77. // don't have to check for public, since
  78. // getMethod finds public method only.
  79. // don't have to check for abstract, since then
  80. // taskClass would be abstract too.
  81. if (!Void.TYPE.equals(executeM.getReturnType())) {
  82. final String message = "return type of execute() should be "
  83. + "void but was \"" + executeM.getReturnType() + "\" in "
  84. + taskClass;
  85. project.log(message, Project.MSG_WARN);
  86. }
  87. } catch (NoSuchMethodException e) {
  88. final String message = "No public execute() in " + taskClass;
  89. project.log(message, Project.MSG_ERR);
  90. throw new BuildException(message);
  91. } catch (LinkageError e) {
  92. String message = "Could not load " + taskClass + ": " + e;
  93. project.log(message, Project.MSG_ERR);
  94. throw new BuildException(message, e);
  95. }
  96. }
  97. }
  98. /**
  99. * Check if the proxy class is a valid class to use
  100. * with this adapter.
  101. * The class must have a public no-arg "execute()" method.
  102. * @param proxyClass the class to check.
  103. */
  104. public void checkProxyClass(Class<?> proxyClass) {
  105. checkTaskClass(proxyClass, getProject());
  106. }
  107. /**
  108. * Executes the proxied task.
  109. *
  110. * @exception BuildException if the project could not be set
  111. * or the method could not be executed.
  112. */
  113. public void execute() throws BuildException {
  114. try {
  115. Method setLocationM =
  116. proxy.getClass().getMethod("setLocation", Location.class);
  117. if (setLocationM != null) {
  118. setLocationM.invoke(proxy, getLocation());
  119. }
  120. } catch (NoSuchMethodException e) {
  121. // ignore this if the class being used as a task does not have
  122. // a set location method.
  123. } catch (Exception ex) {
  124. log("Error setting location in " + proxy.getClass(),
  125. Project.MSG_ERR);
  126. throw new BuildException(ex);
  127. }
  128. try {
  129. Method setProjectM =
  130. proxy.getClass().getMethod("setProject", Project.class);
  131. if (setProjectM != null) {
  132. setProjectM.invoke(proxy, getProject());
  133. }
  134. } catch (NoSuchMethodException e) {
  135. // ignore this if the class being used as a task does not have
  136. // a set project method.
  137. } catch (Exception ex) {
  138. log("Error setting project in " + proxy.getClass(),
  139. Project.MSG_ERR);
  140. throw new BuildException(ex);
  141. }
  142. try {
  143. DispatchUtils.execute(proxy);
  144. } catch (BuildException be) {
  145. throw be;
  146. } catch (Exception ex) {
  147. log("Error in " + proxy.getClass(), Project.MSG_VERBOSE);
  148. throw new BuildException(ex);
  149. }
  150. }
  151. /**
  152. * Sets the target object to proxy for.
  153. *
  154. * @param o The target object. Must not be <code>null</code>.
  155. */
  156. public void setProxy(Object o) {
  157. this.proxy = o;
  158. }
  159. /**
  160. * Returns the target object being proxied.
  161. *
  162. * @return the target proxy object.
  163. */
  164. public Object getProxy() {
  165. return proxy;
  166. }
  167. }