1 | /*
|
---|
2 | * Copyright 2000-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 |
|
---|
18 | package org.apache.tools.ant;
|
---|
19 |
|
---|
20 | import java.lang.reflect.Method;
|
---|
21 |
|
---|
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 |
|
---|
30 | /** Object to act as a proxy for. */
|
---|
31 | private Object proxy;
|
---|
32 |
|
---|
33 | /**
|
---|
34 | * Checks whether or not a class is suitable to be adapted by TaskAdapter.
|
---|
35 | *
|
---|
36 | * This only checks conditions which are additionally required for
|
---|
37 | * tasks adapted by TaskAdapter. Thus, this method should be called by
|
---|
38 | * Project.checkTaskClass.
|
---|
39 | *
|
---|
40 | * Throws a BuildException and logs as Project.MSG_ERR for
|
---|
41 | * conditions that will cause the task execution to fail.
|
---|
42 | * Logs other suspicious conditions with Project.MSG_WARN.
|
---|
43 | *
|
---|
44 | * @param taskClass Class to test for suitability.
|
---|
45 | * Must not be <code>null</code>.
|
---|
46 | * @param project Project to log warnings/errors to.
|
---|
47 | * Must not be <code>null</code>.
|
---|
48 | *
|
---|
49 | * @see Project#checkTaskClass(Class)
|
---|
50 | */
|
---|
51 | public static void checkTaskClass(final Class taskClass,
|
---|
52 | final Project project) {
|
---|
53 | // don't have to check for interface, since then
|
---|
54 | // taskClass would be abstract too.
|
---|
55 | try {
|
---|
56 | final Method executeM = taskClass.getMethod("execute", null);
|
---|
57 | // don't have to check for public, since
|
---|
58 | // getMethod finds public method only.
|
---|
59 | // don't have to check for abstract, since then
|
---|
60 | // taskClass would be abstract too.
|
---|
61 | if (!Void.TYPE.equals(executeM.getReturnType())) {
|
---|
62 | final String message = "return type of execute() should be "
|
---|
63 | + "void but was \"" + executeM.getReturnType() + "\" in "
|
---|
64 | + taskClass;
|
---|
65 | project.log(message, Project.MSG_WARN);
|
---|
66 | }
|
---|
67 | } catch (NoSuchMethodException e) {
|
---|
68 | final String message = "No public execute() in " + taskClass;
|
---|
69 | project.log(message, Project.MSG_ERR);
|
---|
70 | throw new BuildException(message);
|
---|
71 | } catch (LinkageError e) {
|
---|
72 | String message = "Could not load " + taskClass + ": " + e;
|
---|
73 | project.log(message, Project.MSG_ERR);
|
---|
74 | throw new BuildException(message, e);
|
---|
75 | }
|
---|
76 | }
|
---|
77 |
|
---|
78 | /**
|
---|
79 | * check if the proxy class is a valid class to use
|
---|
80 | * with this adapter.
|
---|
81 | * the class must have a public no-arg "execute()" method.
|
---|
82 | * @param proxyClass the class to check
|
---|
83 | */
|
---|
84 | public void checkProxyClass(Class proxyClass) {
|
---|
85 | checkTaskClass(proxyClass, getProject());
|
---|
86 | }
|
---|
87 |
|
---|
88 | /**
|
---|
89 | * Executes the proxied task.
|
---|
90 | *
|
---|
91 | * @exception BuildException if the project could not be set
|
---|
92 | * or the method could not be executed.
|
---|
93 | */
|
---|
94 | public void execute() throws BuildException {
|
---|
95 | Method setProjectM = null;
|
---|
96 | try {
|
---|
97 | Class c = proxy.getClass();
|
---|
98 | setProjectM =
|
---|
99 | c.getMethod("setProject", new Class[] {Project.class});
|
---|
100 | if (setProjectM != null) {
|
---|
101 | setProjectM.invoke(proxy, new Object[] {getProject()});
|
---|
102 | }
|
---|
103 | } catch (NoSuchMethodException e) {
|
---|
104 | // ignore this if the class being used as a task does not have
|
---|
105 | // a set project method.
|
---|
106 | } catch (Exception ex) {
|
---|
107 | log("Error setting project in " + proxy.getClass(),
|
---|
108 | Project.MSG_ERR);
|
---|
109 | throw new BuildException(ex);
|
---|
110 | }
|
---|
111 |
|
---|
112 |
|
---|
113 | Method executeM = null;
|
---|
114 | try {
|
---|
115 | Class c = proxy.getClass();
|
---|
116 | executeM = c.getMethod("execute", new Class[0]);
|
---|
117 | if (executeM == null) {
|
---|
118 | log("No public execute() in " + proxy.getClass(),
|
---|
119 | Project.MSG_ERR);
|
---|
120 | throw new BuildException("No public execute() in "
|
---|
121 | + proxy.getClass());
|
---|
122 | }
|
---|
123 | executeM.invoke(proxy, null);
|
---|
124 | return;
|
---|
125 | } catch (java.lang.reflect.InvocationTargetException ie) {
|
---|
126 | log("Error in " + proxy.getClass(), Project.MSG_VERBOSE);
|
---|
127 | Throwable t = ie.getTargetException();
|
---|
128 | if (t instanceof BuildException) {
|
---|
129 | throw ((BuildException) t);
|
---|
130 | } else {
|
---|
131 | throw new BuildException(t);
|
---|
132 | }
|
---|
133 | } catch (Exception ex) {
|
---|
134 | log("Error in " + proxy.getClass(), Project.MSG_VERBOSE);
|
---|
135 | throw new BuildException(ex);
|
---|
136 | }
|
---|
137 |
|
---|
138 | }
|
---|
139 |
|
---|
140 | /**
|
---|
141 | * Sets the target object to proxy for.
|
---|
142 | *
|
---|
143 | * @param o The target object. Must not be <code>null</code>.
|
---|
144 | */
|
---|
145 | public void setProxy(Object o) {
|
---|
146 | this.proxy = o;
|
---|
147 | }
|
---|
148 |
|
---|
149 | /**
|
---|
150 | * Returns the target object being proxied.
|
---|
151 | *
|
---|
152 | * @return the target proxy object
|
---|
153 | */
|
---|
154 | public Object getProxy() {
|
---|
155 | return proxy;
|
---|
156 | }
|
---|
157 |
|
---|
158 | }
|
---|