|
|||||||||||||||||||
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
AntBuilder.java | 0% | 0% | 0% | 0% |
|
1 |
/*
|
|
2 |
$Id: AntBuilder.java,v 1.8 2004/07/13 12:17:45 jstrachan Exp $
|
|
3 |
|
|
4 |
Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
|
|
5 |
|
|
6 |
Redistribution and use of this software and associated documentation
|
|
7 |
("Software"), with or without modification, are permitted provided
|
|
8 |
that the following conditions are met:
|
|
9 |
|
|
10 |
1. Redistributions of source code must retain copyright
|
|
11 |
statements and notices. Redistributions must also contain a
|
|
12 |
copy of this document.
|
|
13 |
|
|
14 |
2. Redistributions in binary form must reproduce the
|
|
15 |
above copyright notice, this list of conditions and the
|
|
16 |
following disclaimer in the documentation and/or other
|
|
17 |
materials provided with the distribution.
|
|
18 |
|
|
19 |
3. The name "groovy" must not be used to endorse or promote
|
|
20 |
products derived from this Software without prior written
|
|
21 |
permission of The Codehaus. For written permission,
|
|
22 |
please contact info@codehaus.org.
|
|
23 |
|
|
24 |
4. Products derived from this Software may not be called "groovy"
|
|
25 |
nor may "groovy" appear in their names without prior written
|
|
26 |
permission of The Codehaus. "groovy" is a registered
|
|
27 |
trademark of The Codehaus.
|
|
28 |
|
|
29 |
5. Due credit should be given to The Codehaus -
|
|
30 |
http://groovy.codehaus.org/
|
|
31 |
|
|
32 |
THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
|
|
33 |
``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
|
|
34 |
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
35 |
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
36 |
THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
37 |
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
38 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
39 |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
40 |
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
41 |
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
42 |
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
43 |
OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
44 |
|
|
45 |
*/
|
|
46 |
package groovy.util;
|
|
47 |
|
|
48 |
|
|
49 |
import java.lang.reflect.Constructor;
|
|
50 |
import java.lang.reflect.InvocationTargetException;
|
|
51 |
import java.lang.reflect.Method;
|
|
52 |
import java.util.Collections;
|
|
53 |
import java.util.Iterator;
|
|
54 |
import java.util.Map;
|
|
55 |
import java.util.logging.Level;
|
|
56 |
import java.util.logging.Logger;
|
|
57 |
|
|
58 |
import org.apache.tools.ant.BuildException;
|
|
59 |
import org.apache.tools.ant.BuildLogger;
|
|
60 |
import org.apache.tools.ant.IntrospectionHelper;
|
|
61 |
import org.apache.tools.ant.NoBannerLogger;
|
|
62 |
import org.apache.tools.ant.Project;
|
|
63 |
import org.apache.tools.ant.Task;
|
|
64 |
import org.apache.tools.ant.TaskAdapter;
|
|
65 |
import org.apache.tools.ant.TaskContainer;
|
|
66 |
import org.apache.tools.ant.types.DataType;
|
|
67 |
import org.codehaus.groovy.ant.FileScanner;
|
|
68 |
import org.codehaus.groovy.runtime.InvokerHelper;
|
|
69 |
|
|
70 |
/**
|
|
71 |
* Allows Ant tasks to be used with GroovyMarkup
|
|
72 |
*
|
|
73 |
* @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
|
|
74 |
* @version $Revision: 1.8 $
|
|
75 |
*/
|
|
76 |
public class AntBuilder extends BuilderSupport { |
|
77 |
|
|
78 |
private static final Class[] addTaskParamTypes = { String.class }; |
|
79 |
|
|
80 |
private Logger log = Logger.getLogger(getClass().getName());
|
|
81 |
private Project project;
|
|
82 |
|
|
83 | 0 |
public AntBuilder() {
|
84 | 0 |
this.project = createProject();
|
85 |
} |
|
86 |
|
|
87 | 0 |
public AntBuilder(Project project) {
|
88 | 0 |
this.project = project;
|
89 |
} |
|
90 |
|
|
91 |
/**
|
|
92 |
* @return Factory method to create new Project instances
|
|
93 |
*/
|
|
94 | 0 |
protected Project createProject() {
|
95 | 0 |
Project project = new Project();
|
96 | 0 |
BuildLogger logger = new NoBannerLogger();
|
97 |
|
|
98 | 0 |
logger.setMessageOutputLevel(org.apache.tools.ant.Project.MSG_INFO); |
99 | 0 |
logger.setOutputPrintStream(System.out); |
100 | 0 |
logger.setErrorPrintStream(System.err); |
101 |
|
|
102 | 0 |
project.addBuildListener(logger); |
103 |
|
|
104 | 0 |
project.init(); |
105 | 0 |
project.getBaseDir(); |
106 | 0 |
return project;
|
107 |
} |
|
108 |
|
|
109 | 0 |
protected void setParent(Object parent, Object child) { |
110 |
} |
|
111 |
|
|
112 | 0 |
protected void nodeCompleted(Object parent, Object node) { |
113 | 0 |
if (node instanceof Task) { |
114 | 0 |
Task task = (Task) node; |
115 | 0 |
task.perform(); |
116 |
} |
|
117 |
} |
|
118 |
|
|
119 | 0 |
protected Object createNode(Object tagName) {
|
120 | 0 |
return createNode(tagName.toString(), Collections.EMPTY_MAP);
|
121 |
} |
|
122 |
|
|
123 | 0 |
protected Object createNode(Object name, Object value) {
|
124 | 0 |
Object task = createNode(name); |
125 | 0 |
setText(task, value.toString()); |
126 | 0 |
return task;
|
127 |
} |
|
128 |
|
|
129 | 0 |
protected Object createNode(Object name, Map attributes, Object value) {
|
130 | 0 |
Object task = createNode(name, attributes); |
131 | 0 |
setText(task, value.toString()); |
132 | 0 |
return task;
|
133 |
} |
|
134 |
|
|
135 | 0 |
protected Object createNode(Object name, Map attributes) {
|
136 |
|
|
137 | 0 |
if (name.equals("fileScanner")) { |
138 | 0 |
return new FileScanner(project); |
139 |
} |
|
140 |
|
|
141 | 0 |
String tagName = name.toString(); |
142 | 0 |
Object answer = null;
|
143 |
|
|
144 | 0 |
Object parentObject = getCurrent(); |
145 | 0 |
Object parentTask = getParentTask(); |
146 |
|
|
147 |
// lets assume that Task instances are not nested inside other Task instances
|
|
148 |
// for example <manifest> inside a <jar> should be a nested object, where as
|
|
149 |
// if the parent is not a Task the <manifest> should create a ManifestTask
|
|
150 |
//
|
|
151 |
// also its possible to have a root Ant tag which isn't a task, such as when
|
|
152 |
// defining <fileset id="...">...</fileset>
|
|
153 |
|
|
154 | 0 |
Object nested = null;
|
155 | 0 |
if (parentObject != null && !(parentTask instanceof TaskContainer)) { |
156 | 0 |
nested = createNestedObject(parentObject, tagName); |
157 |
} |
|
158 |
|
|
159 | 0 |
Task task = null;
|
160 | 0 |
if (nested == null) { |
161 | 0 |
task = createTask(tagName); |
162 | 0 |
if (task != null) { |
163 | 0 |
if (log.isLoggable(Level.FINE)) {
|
164 | 0 |
log.fine("Creating an ant Task for name: " + tagName);
|
165 |
} |
|
166 |
|
|
167 |
// the following algorithm follows the lifetime of a tag
|
|
168 |
// http://jakarta.apache.org/ant/manual/develop.html#writingowntask
|
|
169 |
// kindly recommended by Stefan Bodewig
|
|
170 |
|
|
171 |
// create and set its project reference
|
|
172 | 0 |
if (task instanceof TaskAdapter) { |
173 | 0 |
answer = ((TaskAdapter) task).getProxy(); |
174 |
} |
|
175 |
else {
|
|
176 | 0 |
answer = task; |
177 |
} |
|
178 |
|
|
179 |
// set the task ID if one is given
|
|
180 | 0 |
Object id = attributes.remove("id");
|
181 | 0 |
if (id != null) { |
182 | 0 |
project.addReference((String) id, task); |
183 |
} |
|
184 |
|
|
185 |
// now lets initialize
|
|
186 | 0 |
task.init(); |
187 |
|
|
188 |
// now lets set any attributes of this tag...
|
|
189 | 0 |
setBeanProperties(task, attributes); |
190 |
} |
|
191 |
} |
|
192 |
|
|
193 | 0 |
if (task == null) { |
194 | 0 |
if (nested == null) { |
195 | 0 |
if (log.isLoggable(Level.FINE)) {
|
196 | 0 |
log.fine("Trying to create a data type for tag: " + tagName);
|
197 |
} |
|
198 | 0 |
nested = createDataType(tagName); |
199 |
} |
|
200 |
else {
|
|
201 | 0 |
if (log.isLoggable(Level.FINE)) {
|
202 | 0 |
log.fine("Created nested property tag: " + tagName);
|
203 |
} |
|
204 |
} |
|
205 |
|
|
206 | 0 |
if (nested != null) { |
207 | 0 |
answer = nested; |
208 |
|
|
209 |
// set the task ID if one is given
|
|
210 | 0 |
Object id = attributes.remove("id");
|
211 | 0 |
if (id != null) { |
212 | 0 |
project.addReference((String) id, nested); |
213 |
} |
|
214 |
|
|
215 | 0 |
try {
|
216 | 0 |
InvokerHelper.setProperty(nested, "name", tagName);
|
217 |
} |
|
218 |
catch (Exception e) {
|
|
219 |
} |
|
220 |
|
|
221 |
// now lets set any attributes of this tag...
|
|
222 | 0 |
setBeanProperties(nested, attributes); |
223 |
|
|
224 |
// now lets add it to its parent
|
|
225 | 0 |
if (parentObject != null) { |
226 | 0 |
IntrospectionHelper ih = IntrospectionHelper.getHelper(parentObject.getClass()); |
227 | 0 |
try {
|
228 | 0 |
if (log.isLoggable(Level.FINE)) {
|
229 | 0 |
log.fine( |
230 |
"About to set the: "
|
|
231 |
+ tagName |
|
232 |
+ " property on: "
|
|
233 |
+ parentObject |
|
234 |
+ " to value: "
|
|
235 |
+ nested |
|
236 |
+ " with type: "
|
|
237 |
+ nested.getClass()); |
|
238 |
} |
|
239 |
|
|
240 | 0 |
ih.storeElement(project, parentObject, nested, tagName); |
241 |
} |
|
242 |
catch (Exception e) {
|
|
243 | 0 |
log.log(Level.WARNING, "Caught exception setting nested: " + tagName, e);
|
244 |
} |
|
245 |
|
|
246 |
// now try to set the property for good measure
|
|
247 |
// as the storeElement() method does not
|
|
248 |
// seem to call any setter methods of non-String types
|
|
249 | 0 |
try {
|
250 | 0 |
InvokerHelper.setProperty(parentObject, tagName, nested); |
251 |
} |
|
252 |
catch (Exception e) {
|
|
253 | 0 |
log.fine("Caught exception trying to set property: " + tagName + " on: " + parentObject); |
254 |
} |
|
255 |
} |
|
256 |
} |
|
257 |
else {
|
|
258 | 0 |
log.log(Level.WARNING, "Could not convert tag: " + tagName + " into an Ant task, data type or property. Maybe the task is not on the classpath?"); |
259 |
} |
|
260 |
} |
|
261 |
|
|
262 | 0 |
return answer;
|
263 |
} |
|
264 |
|
|
265 | 0 |
protected void setText(Object task, String text) { |
266 |
// now lets set the addText() of the body content, if its applicaable
|
|
267 | 0 |
Method method = getAccessibleMethod(task.getClass(), "addText", addTaskParamTypes);
|
268 | 0 |
if (method != null) { |
269 | 0 |
Object[] args = { text }; |
270 | 0 |
try {
|
271 | 0 |
method.invoke(task, args); |
272 |
} |
|
273 |
catch (Exception e) {
|
|
274 | 0 |
log.log(Level.WARNING, "Cannot call addText on: " + task + ". Reason: " + e, e); |
275 |
} |
|
276 |
} |
|
277 |
} |
|
278 |
|
|
279 | 0 |
protected Method getAccessibleMethod(Class theClass, String name, Class[] paramTypes) {
|
280 | 0 |
while (true) { |
281 | 0 |
try {
|
282 | 0 |
Method answer = theClass.getDeclaredMethod(name, paramTypes); |
283 | 0 |
if (answer != null) { |
284 | 0 |
return answer;
|
285 |
} |
|
286 |
} |
|
287 |
catch (Exception e) {
|
|
288 |
// ignore
|
|
289 |
} |
|
290 | 0 |
theClass = theClass.getSuperclass(); |
291 | 0 |
if (theClass == null) { |
292 | 0 |
return null; |
293 |
} |
|
294 |
} |
|
295 |
} |
|
296 |
|
|
297 | 0 |
public Project getAntProject() {
|
298 | 0 |
return project;
|
299 |
} |
|
300 |
|
|
301 |
// Implementation methods
|
|
302 |
//-------------------------------------------------------------------------
|
|
303 | 0 |
protected void setBeanProperties(Object object, Map map) { |
304 | 0 |
for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
|
305 | 0 |
Map.Entry entry = (Map.Entry) iter.next(); |
306 | 0 |
String name = (String) entry.getKey(); |
307 | 0 |
Object value = entry.getValue(); |
308 | 0 |
setBeanProperty(object, name, ((value == null) ? null : value.toString())); |
309 |
} |
|
310 |
} |
|
311 |
|
|
312 | 0 |
protected void setBeanProperty(Object object, String name, Object value) { |
313 | 0 |
if (log.isLoggable(Level.FINE)) {
|
314 | 0 |
log.fine("Setting bean property on: " + object + " name: " + name + " value: " + value); |
315 |
} |
|
316 |
|
|
317 | 0 |
IntrospectionHelper ih = IntrospectionHelper.getHelper(object.getClass()); |
318 |
|
|
319 | 0 |
if (value instanceof String) { |
320 | 0 |
try {
|
321 | 0 |
ih.setAttribute(getAntProject(), object, name.toLowerCase(), (String) value); |
322 | 0 |
return;
|
323 |
} |
|
324 |
catch (Exception e) {
|
|
325 |
// ignore: not a valid property
|
|
326 |
} |
|
327 |
} |
|
328 |
|
|
329 | 0 |
try {
|
330 |
|
|
331 | 0 |
ih.storeElement(getAntProject(), object, value, name); |
332 |
} |
|
333 |
catch (Exception e) {
|
|
334 |
|
|
335 | 0 |
InvokerHelper.setProperty(object, name, value); |
336 |
} |
|
337 |
} |
|
338 |
|
|
339 |
/**
|
|
340 |
* Creates a nested object of the given object with the specified name
|
|
341 |
*/
|
|
342 | 0 |
protected Object createNestedObject(Object object, String name) {
|
343 | 0 |
Object dataType = null;
|
344 | 0 |
if (object != null) { |
345 | 0 |
IntrospectionHelper ih = IntrospectionHelper.getHelper(object.getClass()); |
346 |
|
|
347 | 0 |
if (ih != null) { |
348 | 0 |
try {
|
349 | 0 |
dataType = ih.createElement(getAntProject(), object, name.toLowerCase()); |
350 |
} |
|
351 |
catch (BuildException be) {
|
|
352 | 0 |
log.log(Level.SEVERE, "Caught: " + be, be);
|
353 |
} |
|
354 |
} |
|
355 |
} |
|
356 | 0 |
if (dataType == null) { |
357 | 0 |
dataType = createDataType(name); |
358 |
} |
|
359 | 0 |
return dataType;
|
360 |
} |
|
361 |
|
|
362 | 0 |
protected Object createDataType(String name) {
|
363 | 0 |
Object dataType = null;
|
364 |
|
|
365 | 0 |
Class type = (Class) getAntProject().getDataTypeDefinitions().get(name); |
366 |
|
|
367 | 0 |
if (type != null) { |
368 |
|
|
369 | 0 |
Constructor ctor = null;
|
370 | 0 |
boolean noArg = false; |
371 |
|
|
372 |
// DataType can have a "no arg" constructor or take a single
|
|
373 |
// Project argument.
|
|
374 | 0 |
try {
|
375 | 0 |
ctor = type.getConstructor(new Class[0]);
|
376 | 0 |
noArg = true;
|
377 |
} |
|
378 |
catch (NoSuchMethodException nse) {
|
|
379 | 0 |
try {
|
380 | 0 |
ctor = type.getConstructor(new Class[] { Project.class }); |
381 | 0 |
noArg = false;
|
382 |
} |
|
383 |
catch (NoSuchMethodException nsme) {
|
|
384 | 0 |
log.log(Level.INFO, "datatype '" + name + "' didn't have a constructor with an Ant Project", nsme); |
385 |
} |
|
386 |
} |
|
387 |
|
|
388 | 0 |
if (noArg) {
|
389 | 0 |
dataType = createDataType(ctor, new Object[0], name, "no-arg constructor"); |
390 |
} |
|
391 |
else {
|
|
392 | 0 |
dataType = createDataType(ctor, new Object[] { getAntProject()}, name, "an Ant project"); |
393 |
} |
|
394 | 0 |
if (dataType != null) { |
395 | 0 |
((DataType) dataType).setProject(getAntProject()); |
396 |
} |
|
397 |
} |
|
398 |
|
|
399 | 0 |
return dataType;
|
400 |
} |
|
401 |
|
|
402 |
/**
|
|
403 |
* @return an object create with the given constructor and args.
|
|
404 |
* @param ctor a constructor to use creating the object
|
|
405 |
* @param args the arguments to pass to the constructor
|
|
406 |
* @param name the name of the data type being created
|
|
407 |
* @param argDescription a human readable description of the args passed
|
|
408 |
*/
|
|
409 | 0 |
protected Object createDataType(Constructor ctor, Object[] args, String name, String argDescription) {
|
410 | 0 |
try {
|
411 | 0 |
Object datatype = ctor.newInstance(args); |
412 | 0 |
return datatype;
|
413 |
} |
|
414 |
catch (InstantiationException ie) {
|
|
415 | 0 |
log.log(Level.SEVERE, "datatype '" + name + "' couldn't be created with " + argDescription, ie); |
416 |
} |
|
417 |
catch (IllegalAccessException iae) {
|
|
418 | 0 |
log.log(Level.SEVERE, "datatype '" + name + "' couldn't be created with " + argDescription, iae); |
419 |
} |
|
420 |
catch (InvocationTargetException ite) {
|
|
421 | 0 |
log.log(Level.SEVERE, "datatype '" + name + "' couldn't be created with " + argDescription, ite); |
422 |
} |
|
423 | 0 |
return null; |
424 |
} |
|
425 |
|
|
426 |
/**
|
|
427 |
* @param taskName the name of the task to create
|
|
428 |
* @return a newly created task
|
|
429 |
*/
|
|
430 | 0 |
protected Task createTask(String taskName) {
|
431 | 0 |
return createTask(taskName, (Class) getAntProject().getTaskDefinitions().get(taskName));
|
432 |
} |
|
433 |
|
|
434 | 0 |
protected Task createTask(String taskName, Class taskType) {
|
435 | 0 |
if (taskType == null) { |
436 | 0 |
return null; |
437 |
} |
|
438 | 0 |
try {
|
439 | 0 |
Object o = taskType.newInstance(); |
440 | 0 |
Task task = null;
|
441 | 0 |
if (o instanceof Task) { |
442 | 0 |
task = (Task) o; |
443 |
} |
|
444 |
else {
|
|
445 | 0 |
TaskAdapter taskA = new TaskAdapter();
|
446 | 0 |
taskA.setProxy(o); |
447 | 0 |
task = taskA; |
448 |
} |
|
449 |
|
|
450 | 0 |
task.setProject(getAntProject()); |
451 | 0 |
task.setTaskName(taskName); |
452 |
|
|
453 | 0 |
return task;
|
454 |
} |
|
455 |
catch (Exception e) {
|
|
456 | 0 |
log.log(Level.WARNING, "Could not create task: " + taskName + ". Reason: " + e, e); |
457 | 0 |
return null; |
458 |
} |
|
459 |
} |
|
460 |
|
|
461 | 0 |
protected Task getParentTask() {
|
462 | 0 |
Object current = getCurrent(); |
463 | 0 |
if (current instanceof Task) { |
464 | 0 |
return (Task) current;
|
465 |
} |
|
466 | 0 |
return null; |
467 |
} |
|
468 |
} |
|
469 |
|
|