Reorganization of classes to a fair extent Introduction of a non-functional parallel task Converted some data types over Initial experiments with apsects used to store data type values git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269031 13f79535-47bb-0310-9956-ffa450edef68master
@@ -55,6 +55,9 @@ | |||
<antcall target="build-task"> | |||
<param name="taskset" value="file"/> | |||
</antcall> | |||
<antcall target="build-task"> | |||
<param name="taskset" value="thread"/> | |||
</antcall> | |||
<copy todir="${build.lib}"> | |||
<fileset dir="lib"/> | |||
</copy> | |||
@@ -0,0 +1,75 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2000 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.component.core; | |||
import java.io.File; | |||
import java.net.*; | |||
import org.apache.ant.core.execution.*; | |||
/** | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public class AntAspectHandler extends AbstractAspectHandler { | |||
private String id; | |||
public void setId(String id) { | |||
this.id = id; | |||
} | |||
public void afterConfigElement(Object element) throws ExecutionException { | |||
getAspectContext().setDataValue(id, element); | |||
} | |||
} |
@@ -63,7 +63,7 @@ import java.io.*; | |||
* | |||
* @author costin@dnt.ro | |||
*/ | |||
public class Echo extends ExecutionTask { | |||
public class Echo extends AbstractTask { | |||
protected String message = ""; // required | |||
protected File file = null; | |||
protected boolean append = false; | |||
@@ -76,7 +76,6 @@ public class FileConverter implements AntConverter { | |||
try { | |||
URL url = new URL(frame.getBaseURL(), value); | |||
if (url.getProtocol().equals("file")) { | |||
System.out.println("Converted URL to " + url); | |||
return new File(url.getFile()); | |||
} | |||
return new File(value); | |||
@@ -62,7 +62,7 @@ import java.net.*; | |||
/** | |||
* | |||
*/ | |||
public class Property extends ExecutionTask { | |||
public class Property extends AbstractTask { | |||
private String name; | |||
private String value; | |||
private URL file; | |||
@@ -144,9 +144,8 @@ public class Property extends ExecutionTask { | |||
// | |||
public void execute() throws ExecutionException { | |||
ExecutionFrame frame = getExecutionFrame(); | |||
if ((name != null) && (value != null)) { | |||
frame.setDataValue(name, value); | |||
getTaskContext().setDataValue(name, value); | |||
} | |||
if (file != null) { | |||
@@ -199,11 +198,11 @@ public class Property extends ExecutionTask { | |||
} | |||
protected void addProperties(Properties properties) throws ExecutionException { | |||
ExecutionFrame frame = getExecutionFrame(); | |||
for (Iterator i = properties.keySet().iterator(); i.hasNext();) { | |||
String propertyName = (String)i.next(); | |||
String propertyValue = properties.getProperty(propertyName); | |||
frame.setDataValue(propertyName, frame.replacePropertyRefs(propertyValue)); | |||
getTaskContext().setDataValue(propertyName, | |||
getTaskContext().replacePropertyRefs(propertyValue)); | |||
} | |||
} | |||
@@ -1,8 +1,17 @@ | |||
<antlib> | |||
<!-- Tasks --> | |||
<taskdef name="property" classname="org.apache.ant.component.core.Property"/> | |||
<taskdef name="echo" classname="org.apache.ant.component.core.Echo"/> | |||
<!-- Data Types --> | |||
<taskdef name="patternset" classname="org.apache.ant.core.types.PatternSet"/> | |||
<!-- Converters --> | |||
<converter target="java.io.File" classname="org.apache.ant.component.core.FileConverter"/> | |||
<converter target="java.net.URL" classname="org.apache.ant.component.core.URLConverter"/> | |||
<converter target="org.apache.ant.core.types.EnumeratedAttribute" | |||
classname="org.apache.ant.component.core.EnumeratedAttributeConverter"/> | |||
<!-- Aspect Handlers --> | |||
<aspect prefix="ant" classname="org.apache.ant.component.core.AntAspectHandler"/> | |||
</antlib> |
@@ -0,0 +1,78 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.component.thread; | |||
import org.apache.ant.core.execution.*; | |||
import java.io.*; | |||
import java.util.*; | |||
/** | |||
* Parallel execution of contained tasks. | |||
* | |||
*/ | |||
public class Parallel extends AbstractTask implements TaskContainer { | |||
private List tasks = new ArrayList(); | |||
public void addTask(Task nestedTask) { | |||
tasks.add(nestedTask); | |||
} | |||
public void execute() throws ExecutionException { | |||
for (Iterator i = tasks.iterator(); i.hasNext(); ) { | |||
Task nestedTask = (Task)i.next(); | |||
nestedTask.execute(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,78 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.component.thread; | |||
import org.apache.ant.core.execution.*; | |||
import java.io.*; | |||
import java.util.*; | |||
/** | |||
* Sequential execution of contained tasks. | |||
* | |||
*/ | |||
public class Sequential extends AbstractTask implements TaskContainer { | |||
private List tasks = new ArrayList(); | |||
public void addTask(Task nestedTask) { | |||
tasks.add(nestedTask); | |||
} | |||
public void execute() throws ExecutionException { | |||
for (Iterator i = tasks.iterator(); i.hasNext(); ) { | |||
Task nestedTask = (Task)i.next(); | |||
nestedTask.execute(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,4 @@ | |||
<antlib> | |||
<taskdef name="parallel" classname="org.apache.ant.component.thread.Parallel"/> | |||
<taskdef name="sequential" classname="org.apache.ant.component.thread.Sequential"/> | |||
</antlib> |
@@ -0,0 +1,80 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.core.execution; | |||
import org.apache.ant.core.model.*; | |||
import org.apache.ant.core.support.*; | |||
import java.util.*; | |||
import java.net.URL; | |||
/** | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public abstract class AbstractAspectHandler implements AspectHandler { | |||
private ExecutionContext aspectContext; | |||
public void setAspectContext(ExecutionContext context) { | |||
this.aspectContext = context; | |||
} | |||
protected ExecutionContext getAspectContext() { | |||
return aspectContext; | |||
} | |||
public void afterConfigElement(Object element) throws ExecutionException { | |||
} | |||
} | |||
@@ -0,0 +1,96 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.core.execution; | |||
import org.apache.ant.core.model.*; | |||
import org.apache.ant.core.support.*; | |||
import java.util.*; | |||
import java.net.URL; | |||
/** | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public abstract class AbstractTask implements Task { | |||
private ExecutionContext taskContext; | |||
public void setTaskContext(ExecutionContext context) { | |||
this.taskContext = context; | |||
} | |||
protected ExecutionContext getTaskContext() { | |||
return taskContext; | |||
} | |||
/** | |||
* Log a message with the default (INFO) priority. | |||
* | |||
* @param msg the message to be logged. | |||
*/ | |||
public void log(String msg) { | |||
log(msg, BuildEvent.MSG_INFO); | |||
} | |||
/** | |||
* Log a mesage with the give priority. | |||
* | |||
* @param the message to be logged. | |||
* @param msgLevel the message priority at which this message is to be logged. | |||
*/ | |||
public void log(String msg, int msgLevel) { | |||
taskContext.log(msg, msgLevel); | |||
} | |||
} | |||
@@ -54,6 +54,7 @@ | |||
package org.apache.ant.core.execution; | |||
import org.apache.ant.core.support.*; | |||
import java.util.*; | |||
import java.net.URL; | |||
@@ -68,35 +69,51 @@ public class AntLibrary { | |||
/** | |||
* The task definitions contained by this library | |||
*/ | |||
private List taskDefinitions = new ArrayList(); | |||
private Map taskDefinitions = new HashMap(); | |||
/** | |||
* The converter definitions contained by this library | |||
*/ | |||
private List converterDefinitions = new ArrayList(); | |||
private Map converterDefinitions = new HashMap(); | |||
/** | |||
* The aspect handler definitions contained by this library | |||
*/ | |||
private Map aspectDefinitions = new HashMap(); | |||
/** | |||
* Add a task definition to this library | |||
*/ | |||
public void addTaskDefinition(TaskDefinition taskDefinition) { | |||
taskDefinitions.add(taskDefinition); | |||
String taskName = taskDefinition.getName(); | |||
taskDefinitions.put(taskName, taskDefinition); | |||
} | |||
/** | |||
* Add a converter definition to this library | |||
*/ | |||
public void addConverterDefinition(ConverterDefinition converterDef) { | |||
String targetClassname = converterDef.getTargetClassName(); | |||
converterDefinitions.put(targetClassname, converterDef); | |||
} | |||
/** | |||
* Add an aspect handler definition to this library | |||
*/ | |||
public void addAspectDefinition(AspectDefinition aspectDef) { | |||
String aspectPrefix = aspectDef.getAspectPrefix(); | |||
aspectDefinitions.put(aspectPrefix, aspectDef); | |||
} | |||
/** | |||
* Get the task definitions | |||
* | |||
* @return an iterator which returns TaskDefinition objects. | |||
*/ | |||
public Iterator getTaskDefinitions() { | |||
return taskDefinitions.iterator(); | |||
return taskDefinitions.values().iterator(); | |||
} | |||
/** | |||
* Add a converter definition to this library | |||
*/ | |||
public void addConverterDefinition(ConverterDefinition converterDefinition) { | |||
converterDefinitions.add(converterDefinition); | |||
} | |||
/** | |||
* Get the converter definitions | |||
@@ -104,7 +121,17 @@ public class AntLibrary { | |||
* @return an iterator which returns ConverterDefinition objects. | |||
*/ | |||
public Iterator getConverterDefinitions() { | |||
return converterDefinitions.iterator(); | |||
return converterDefinitions.values().iterator(); | |||
} | |||
/** | |||
* Get the aspect handler definitions | |||
* | |||
* @return an iterator which returns AspectDefinition objects. | |||
*/ | |||
public Iterator getAspectDefinitions() { | |||
return aspectDefinitions.values().iterator(); | |||
} | |||
} | |||
@@ -0,0 +1,124 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.core.execution; | |||
import java.util.*; | |||
import java.net.URL; | |||
/** | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public class AspectDefinition { | |||
/** The URL of the library which defines this aspect handler */ | |||
private URL aspectLibraryURL; | |||
/** The aspect's tag */ | |||
private String aspectPrefix; | |||
/** The aspect handler's classname */ | |||
private String aspectClassName; | |||
/** The aspect handler's class loader. */ | |||
private ClassLoader aspectClassLoader; | |||
/** The class to which this converter converts. */ | |||
private Class aspectHandlerClass = null; | |||
public AspectDefinition(URL aspectLibraryURL, String aspectPrefix, | |||
String aspectClassName, ClassLoader aspectClassLoader) { | |||
this.aspectLibraryURL = aspectLibraryURL; | |||
this.aspectPrefix = aspectPrefix; | |||
this.aspectClassName = aspectClassName; | |||
this.aspectClassLoader = aspectClassLoader; | |||
} | |||
/** | |||
* Get the URL where this aspect handler was defined. | |||
* | |||
* @returns a URL of the lib defintion file | |||
*/ | |||
public URL getLibraryURL() { | |||
return aspectLibraryURL; | |||
} | |||
/** | |||
* Get the Aspect's Prefix | |||
*/ | |||
public String getAspectPrefix() { | |||
return aspectPrefix; | |||
} | |||
/** | |||
* Get the aspect handler class | |||
* | |||
* @return a class object for this aspect handler's class | |||
*/ | |||
public synchronized Class getAspectHandlerClass() throws ClassNotFoundException { | |||
if (aspectHandlerClass == null) { | |||
aspectHandlerClass = Class.forName(aspectClassName, true, aspectClassLoader); | |||
} | |||
return aspectHandlerClass; | |||
} | |||
/** | |||
* Get the classname of the aspect handler that is being defined. | |||
*/ | |||
public String getAspectHandlerClassName() { | |||
return aspectClassName; | |||
} | |||
} | |||
@@ -0,0 +1,74 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.core.execution; | |||
import org.apache.ant.core.model.*; | |||
import org.apache.ant.core.support.*; | |||
import java.util.*; | |||
import java.net.URL; | |||
/** | |||
* An AspectHandler is used to handle a set of aspects which may occur in a number | |||
* of elements in the build model. | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public interface AspectHandler { | |||
void setAspectContext(ExecutionContext context); | |||
void afterConfigElement(Object element) throws ExecutionException ; | |||
} | |||
@@ -90,7 +90,7 @@ public class ClassIntrospectionException extends Exception { | |||
* @param cause Exception that might have caused this one. | |||
*/ | |||
public ClassIntrospectionException(Throwable cause) { | |||
super(cause.toString()); | |||
super(cause.getMessage()); | |||
this.cause = cause; | |||
} | |||
@@ -124,7 +124,7 @@ public class ConverterDefinition { | |||
*/ | |||
public synchronized Class getConverterClass() throws ClassNotFoundException { | |||
if (converterClass == null) { | |||
converterClass = converterClassLoader.loadClass(converterClassName); | |||
converterClass = Class.forName(converterClassName, true, converterClassLoader); | |||
} | |||
return converterClass; | |||
} | |||
@@ -136,7 +136,7 @@ public class ConverterDefinition { | |||
*/ | |||
public synchronized Class getTargetClass() throws ClassNotFoundException { | |||
if (targetClass == null) { | |||
targetClass = converterClassLoader.loadClass(targetClassName); | |||
targetClass = Class.forName(targetClassName, true, converterClassLoader); | |||
} | |||
return targetClass; | |||
} | |||
@@ -60,60 +60,22 @@ import java.util.*; | |||
import java.net.URL; | |||
/** | |||
* An ExecutionTask is the execution time equivalent of the Task | |||
* object in the Ant project model. Subclasses of ExecutionTask are | |||
* created by Task writers to implement particular, desired | |||
* functionality | |||
* | |||
* An ExecutionTask subclass is created for a particular task type. | |||
* The data from the task model is introspected into the ExecutionTask | |||
* which is then executed. | |||
* The ExecutionContext interface provides a task or apsect instance with access to the | |||
* container-provided services. This is the only way to access the container. | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public abstract class ExecutionTask { | |||
public class ExecutionContext { | |||
private ExecutionFrame frame = null; | |||
private Location location = Location.UNKNOWN_LOCATION; | |||
private BuildEventSupport eventSupport; | |||
private BuildElement buildElement; | |||
void setExecutionFrame(ExecutionFrame frame) { | |||
public ExecutionContext(ExecutionFrame frame, BuildEventSupport eventSupport, | |||
BuildElement buildElement) { | |||
this.frame = frame; | |||
} | |||
/** | |||
* Get the ExecutionFrame in which this ExecutionTask is being executed. | |||
* to which this task belongs | |||
* | |||
* @return the execution task's ExecutionFrame. | |||
*/ | |||
public ExecutionFrame getExecutionFrame() { | |||
return frame; | |||
} | |||
/** | |||
* Configure the event support to be used to fire events | |||
*/ | |||
void setBuildEventSupport(BuildEventSupport eventSupport) { | |||
this.eventSupport = eventSupport; | |||
} | |||
/** | |||
* Associate this ExecutionTask with a buildElement in the | |||
* project model | |||
*/ | |||
void setBuildElement(BuildElement buildElement) { | |||
this.buildElement = buildElement; | |||
} | |||
/** | |||
* Log a message with the default (INFO) priority. | |||
* | |||
* @param msg the message to be logged. | |||
*/ | |||
public void log(String msg) { | |||
log(msg, BuildEvent.MSG_INFO); | |||
} | |||
/** | |||
* Log a mesage with the give priority. | |||
@@ -125,26 +87,22 @@ public abstract class ExecutionTask { | |||
eventSupport.fireMessageLogged(this, buildElement, msg, msgLevel); | |||
} | |||
/** | |||
* Called by the project to let the task initialize properly. | |||
* | |||
* @throws ExecutionException if someting goes wrong with the build | |||
*/ | |||
public void init() throws ExecutionException {} | |||
public void setDataValue(String name, Object value) throws ExecutionException { | |||
frame.setDataValue(name, value); | |||
} | |||
/** | |||
* Called by the frame to let the task do it's work. | |||
* | |||
* @throws ExecutionException if someting goes wrong with the build | |||
*/ | |||
abstract public void execute() throws ExecutionException; | |||
public Object getDataValue(String name) throws ExecutionException { | |||
return frame.getDataValue(name); | |||
} | |||
/** | |||
* Returns the file location where this task was defined. | |||
* Replace ${} style constructions in the given value with the string value of | |||
* the corresponding data types. | |||
* | |||
* @param value the string to be scanned for property references. | |||
*/ | |||
public Location getLocation() { | |||
return buildElement.getLocation(); | |||
public String replacePropertyRefs(String value) throws ExecutionException { | |||
return frame.replacePropertyRefs(value); | |||
} | |||
} | |||
@@ -55,6 +55,7 @@ package org.apache.ant.core.execution; | |||
import org.apache.ant.core.model.*; | |||
import org.apache.ant.core.support.*; | |||
import org.apache.ant.core.types.*; | |||
import java.util.*; | |||
import java.net.*; | |||
@@ -67,6 +68,13 @@ import java.net.*; | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public class ExecutionFrame { | |||
/** State used in dependency analysis when a target's dependencies are being | |||
examined. */ | |||
private static final String VISITING = "VISITING"; | |||
/** State used in dependency analysis to indicate a target has been examined */ | |||
private static final String VISITED = "VISITED"; | |||
/** The Project that this execiton frame is processing */ | |||
private Project project = null; | |||
@@ -74,9 +82,6 @@ public class ExecutionFrame { | |||
Project's source URL and it's base attribute. */ | |||
private URL baseURL = null; | |||
/** The task defs that this frame will use to process tasks */ | |||
private Map taskDefs = new HashMap(); | |||
/** The imported frames of this frame. For each project imported by this frame's | |||
project, a corresponding ExecutionFrame is created. */ | |||
private Map importedFrames = new HashMap(); | |||
@@ -88,22 +93,79 @@ public class ExecutionFrame { | |||
created by tasks that have been executed */ | |||
private Map dataValues = new HashMap(); | |||
/** Introspector objects used to configure ExecutionTasks from the Task models.*/ | |||
/** Introspector objects used to configure Tasks from the Task models.*/ | |||
private Map introspectors = new HashMap(); | |||
/** The task defs that this frame will use to process tasks */ | |||
private Map taskDefs = new HashMap(); | |||
/** Type converters for this executionFrame. Converters are used when configuring | |||
Tasks to handle special type conversions. */ | |||
private Map converters = new HashMap(); | |||
/** The aspect handler active in this frame */ | |||
private Map aspectHandlers = new HashMap(); | |||
/** The namespace under which this execution frame lives in the hierarchical | |||
project namespace - null for the root namespace */ | |||
private String namespace; | |||
public ExecutionFrame(Project project, Map taskDefs, Map converterDefs, | |||
String namespace) throws ConfigException { | |||
this.project = project; | |||
this.taskDefs = taskDefs; | |||
/** | |||
* Construct an execution frame to process the given project model with | |||
* the configuration represented by the libraries. | |||
* | |||
* @param project the model of the project to be built. | |||
* @param libraries an Array of AntLibrary objects containing the | |||
* configuration of Ant for this build. | |||
* | |||
* @throws ConfigException when the project cannot be setup with the | |||
* given configuration | |||
*/ | |||
public ExecutionFrame(Project project, AntLibrary[] libraries) | |||
throws ConfigException { | |||
this.namespace = null; | |||
setupFrame(project, libraries); | |||
} | |||
/** | |||
* Construct a subframe for managing a project imported into the main project. | |||
* @param project the model of the project to be built. | |||
* @param libraries an Array of AntLibrary objects containing the | |||
* configuration of Ant for this build. | |||
* @param namespace the location of this project within the overall import | |||
* namespace. | |||
* | |||
* @throws ConfigException when the project cannot be setup with the | |||
* given configuration | |||
*/ | |||
private ExecutionFrame(Project project, AntLibrary[] libraries, String namespace) | |||
throws ConfigException { | |||
this.namespace = namespace; | |||
setupFrame(project, libraries); | |||
} | |||
/** | |||
* Set up the execution frame. | |||
* | |||
* This method examines the project model and constructs the required | |||
* subframes to handle imported projects. | |||
* @param project the model of the project to be built. | |||
* @param libraries an Array of AntLibrary objects containing the | |||
* configuration of Ant for this build. | |||
* | |||
* @throws ConfigException when the project cannot be setup with the | |||
* given configuration | |||
*/ | |||
private void setupFrame(Project project, AntLibrary[] libraries) | |||
throws ConfigException { | |||
this.project = project; | |||
for (int i = 0; i < libraries.length; ++i) { | |||
addLibrary(libraries[i]); | |||
} | |||
try { | |||
String base = project.getBase(); | |||
@@ -123,74 +185,149 @@ public class ExecutionFrame { | |||
+ "\" is not valid", e, project.getLocation()); | |||
} | |||
// We create a set of converters from the converter definitions we | |||
// have been given and initialise them. They should be AntConverters | |||
setupConverters(converterDefs); | |||
for (Iterator i = project.getImportedProjectNames(); i.hasNext();) { | |||
String importName = (String)i.next(); | |||
Project importedProject = project.getImportedProject(importName); | |||
String importNamespace | |||
= namespace == null ? importName : namespace + ":" + importName; | |||
ExecutionFrame importedFrame | |||
= new ExecutionFrame(importedProject, taskDefs, converterDefs, importNamespace); | |||
= new ExecutionFrame(importedProject, libraries, importNamespace); | |||
importedFrames.put(importName, importedFrame); | |||
} | |||
} | |||
public URL getBaseURL() { | |||
return baseURL; | |||
/** | |||
* Add a configuration library to this execution frame. The library | |||
* will contain task definitions, converters, apsect handler definitions, | |||
* etc. | |||
* | |||
* @param library the configuration library to add to this frame. | |||
* | |||
* @throws ConfigException if the items in the library cannot be configured. | |||
*/ | |||
public void addLibrary(AntLibrary library) throws ConfigException { | |||
for (Iterator i = library.getTaskDefinitions(); i.hasNext(); ) { | |||
TaskDefinition taskDefinition = (TaskDefinition)i.next(); | |||
addTaskDefinition(taskDefinition); | |||
} | |||
for (Iterator i = library.getConverterDefinitions(); i.hasNext(); ) { | |||
ConverterDefinition converterDef = (ConverterDefinition)i.next(); | |||
addConverterDefinition(converterDef); | |||
} | |||
for (Iterator i = library.getAspectDefinitions(); i.hasNext(); ) { | |||
AspectDefinition aspectDef = (AspectDefinition)i.next(); | |||
addAspectHandler(aspectDef); | |||
} | |||
} | |||
private void setupConverters(Map converterDefs) throws ConfigException { | |||
converters = new HashMap(); | |||
for (Iterator i = converterDefs.values().iterator(); i.hasNext(); ) { | |||
ConverterDefinition converterDef = (ConverterDefinition)i.next(); | |||
boolean targetLoaded = false; | |||
try { | |||
Class targetClass = converterDef.getTargetClass(); | |||
targetLoaded = false; | |||
Class converterClass = converterDef.getConverterClass(); | |||
Converter converter = (AntConverter)converterClass.newInstance(); | |||
if (converter instanceof AntConverter) { | |||
((AntConverter)converter).init(this); | |||
} | |||
converters.put(targetClass, converter); | |||
} | |||
catch (ClassNotFoundException e) { | |||
if (targetLoaded) { | |||
throw new ConfigException("Unable to load converter class for " | |||
+ converterDef.getConverterClassName() | |||
+ " in converter from " + converterDef.getLibraryURL() | |||
, e); | |||
} | |||
else { | |||
throw new ConfigException("Unable to load target class " | |||
+ converterDef.getTargetClassName() | |||
+ " in converter from " + converterDef.getLibraryURL() | |||
, e); | |||
} | |||
/** | |||
* Add a task definition to this execution frame | |||
* | |||
* @param taskDefinition the TaskDefinition to be added to the project. | |||
*/ | |||
public void addTaskDefinition(TaskDefinition taskDefinition) { | |||
String taskName = taskDefinition.getName(); | |||
taskDefs.put(taskName, taskDefinition); | |||
} | |||
/** | |||
* Add a aspect handler definition to this execution frame | |||
* | |||
* @param taskDefinition the TaskDefinition to be added to the project. | |||
* | |||
* @throws ConfigException if the aspect handler cannot be created or configured. | |||
*/ | |||
public void addAspectHandler(AspectDefinition aspectDefinition) | |||
throws ConfigException { | |||
String aspectPrefix = aspectDefinition.getAspectPrefix(); | |||
try { | |||
Class aspectHandlerClass = aspectDefinition.getAspectHandlerClass(); | |||
aspectHandlers.put(aspectPrefix, aspectHandlerClass); | |||
} | |||
catch (ClassNotFoundException e) { | |||
throw new ConfigException("Unable to load aspect handler class for " | |||
+ aspectDefinition.getAspectHandlerClassName() | |||
+ " in converter from " + aspectDefinition.getLibraryURL(), | |||
e); | |||
} | |||
} | |||
/** | |||
* Add a converter definition to this library. | |||
* | |||
* The converter is created immediately to handle conversions | |||
* when items are being configured. If the converter is an instance of | |||
* an AntConverter, the converter is configured with this execution | |||
* frame giving it the context it needs to resolve items relative to the | |||
* project's base, etc. | |||
* | |||
* @param converterDef the converter definition to load | |||
* | |||
* @throws ConfigException if the converter cannot be created or configured. | |||
*/ | |||
public void addConverterDefinition(ConverterDefinition converterDef) throws ConfigException { | |||
boolean targetLoaded = false; | |||
try { | |||
Class targetClass = converterDef.getTargetClass(); | |||
targetLoaded = false; | |||
Class converterClass = converterDef.getConverterClass(); | |||
Converter converter = (AntConverter)converterClass.newInstance(); | |||
if (converter instanceof AntConverter) { | |||
((AntConverter)converter).init(this); | |||
} | |||
catch (InstantiationException e) { | |||
throw new ConfigException("Unable to instantiate converter class " | |||
+ converterDef.getTargetClassName() | |||
+ " in converter from " + converterDef.getLibraryURL() | |||
, e); | |||
converters.put(targetClass, converter); | |||
} | |||
catch (ClassNotFoundException e) { | |||
if (targetLoaded) { | |||
throw new ConfigException("Unable to load converter class for " | |||
+ converterDef.getConverterClassName() | |||
+ " in converter from " + converterDef.getLibraryURL(), | |||
e); | |||
} | |||
catch (IllegalAccessException e) { | |||
throw new ConfigException("Unable to access converter class " | |||
else { | |||
throw new ConfigException("Unable to load target class " | |||
+ converterDef.getTargetClassName() | |||
+ " in converter from " + converterDef.getLibraryURL() | |||
, e); | |||
+ " in converter from " + converterDef.getLibraryURL(), | |||
e); | |||
} | |||
} | |||
catch (InstantiationException e) { | |||
throw new ConfigException("Unable to instantiate converter class " | |||
+ converterDef.getTargetClassName() | |||
+ " in converter from " + converterDef.getLibraryURL(), | |||
e); | |||
} | |||
catch (IllegalAccessException e) { | |||
throw new ConfigException("Unable to access converter class " | |||
+ converterDef.getTargetClassName() | |||
+ " in converter from " + converterDef.getLibraryURL(), | |||
e); | |||
} | |||
} | |||
/** | |||
* Get the bae URL of this frame. This will either be specified by the project's | |||
* base attribute or be derived implicitly from the project's location. | |||
*/ | |||
public URL getBaseURL() { | |||
return baseURL; | |||
} | |||
public void addBuildListener(BuildListener listener) { | |||
for (Iterator i = getImportedFrames(); i.hasNext(); ) { | |||
ExecutionFrame subFrame = (ExecutionFrame)i.next(); | |||
subFrame.addBuildListener(listener); | |||
} | |||
eventSupport.addBuildListener(listener); | |||
} | |||
public void removeBuildListener(BuildListener listener) { | |||
for (Iterator i = getImportedFrames(); i.hasNext(); ) { | |||
ExecutionFrame subFrame = (ExecutionFrame)i.next(); | |||
subFrame.removeBuildListener(listener); | |||
} | |||
eventSupport.removeBuildListener(listener); | |||
} | |||
@@ -257,26 +394,6 @@ public class ExecutionFrame { | |||
return namespace == null ? name : namespace + ":" + name; | |||
} | |||
/** | |||
* Get the relative name of something with respect to this | |||
* execution frame. | |||
* | |||
* @param fullname the fully qualified name. | |||
* | |||
* @return the relative version of the given name | |||
*/ | |||
public String getRelativeName(String fullname) { | |||
if (namespace == null) { | |||
return fullname; | |||
} | |||
int index = fullname.indexOf(namespace); | |||
if (index != 0) { | |||
return fullname; | |||
} | |||
return fullname.substring(namespace.length() + 1); | |||
} | |||
/** | |||
* Execute the given target's tasks | |||
* | |||
@@ -297,32 +414,140 @@ public class ExecutionFrame { | |||
} | |||
/** | |||
* Initialise the frame by executing the project level tasks if any | |||
* Initialize the frame by executing the project level tasks if any | |||
*/ | |||
public void initialise() throws ExecutionException, ConfigException { | |||
public void initialize() throws ExecutionException, ConfigException { | |||
for (Iterator i = getImportedFrames(); i.hasNext(); ) { | |||
ExecutionFrame subFrame = (ExecutionFrame)i.next(); | |||
subFrame.initialize(); | |||
} | |||
Iterator taskIterator = project.getTasks(); | |||
executeTasks(taskIterator); | |||
} | |||
public void fillinDependencyOrder(String targetName, List dependencyOrder, | |||
Map state, Stack visiting) throws ConfigException { | |||
String fullTargetName = getQualifiedName(targetName); | |||
if (state.get(fullTargetName) == VISITED) { | |||
return; | |||
} | |||
Target target = getProject().getTarget(targetName); | |||
if (target == null) { | |||
StringBuffer sb = new StringBuffer("Target `"); | |||
sb.append(targetName); | |||
sb.append("' does not exist in this project. "); | |||
if (!visiting.empty()) { | |||
String parent = (String)visiting.peek(); | |||
sb.append("It is used from target `"); | |||
sb.append(parent); | |||
sb.append("'."); | |||
} | |||
throw new ConfigException(new String(sb), getProject().getLocation()); | |||
} | |||
state.put(fullTargetName, VISITING); | |||
visiting.push(fullTargetName); | |||
for (Iterator i = target.getDependencies(); i.hasNext(); ) { | |||
String dependency = (String)i.next(); | |||
try { | |||
ExecutionFrame dependencyFrame = getRelativeFrame(dependency); | |||
if (dependencyFrame == null) { | |||
StringBuffer sb = new StringBuffer("Target `"); | |||
sb.append(dependency); | |||
sb.append("' does not exist in this project. "); | |||
throw new ConfigException(new String(sb), target.getLocation()); | |||
} | |||
String fullyQualifiedName = getQualifiedName(dependency); | |||
String dependencyState = (String)state.get(fullyQualifiedName); | |||
if (dependencyState == null) { | |||
dependencyFrame.fillinDependencyOrder(getNameInFrame(dependency), dependencyOrder, | |||
state, visiting); | |||
} | |||
else if (dependencyState == VISITING) { | |||
String circleDescription | |||
= getCircularDesc(dependency, visiting); | |||
throw new ConfigException(circleDescription, target.getLocation()); | |||
} | |||
} | |||
catch (ExecutionException e) { | |||
throw new ConfigException(e.getMessage(), e, target.getLocation()); | |||
} | |||
} | |||
state.put(fullTargetName, VISITED); | |||
String poppedNode = (String)visiting.pop(); | |||
if (poppedNode != fullTargetName) { | |||
throw new ConfigException("Problem determining dependencies " + | |||
" - expecting '" + fullTargetName + | |||
"' but got '" + poppedNode + "'"); | |||
} | |||
dependencyOrder.add(fullTargetName); | |||
} | |||
private String getCircularDesc(String end, Stack visitingNodes) { | |||
StringBuffer sb = new StringBuffer("Circular dependency: "); | |||
sb.append(end); | |||
String c; | |||
do { | |||
c = (String)visitingNodes.pop(); | |||
sb.append(" <- "); | |||
sb.append(c); | |||
} while(!c.equals(end)); | |||
return new String(sb); | |||
} | |||
/** | |||
* Check whether the targets in this frame and its subframes are OK | |||
*/ | |||
public void checkTargets(List dependencyOrder, Map state, Stack visiting) | |||
throws ConfigException { | |||
// get the targets and just iterate through them. | |||
for (Iterator i = getProject().getTargets(); i.hasNext();) { | |||
Target target = (Target)i.next(); | |||
fillinDependencyOrder(target.getName(), | |||
dependencyOrder, state, visiting); | |||
} | |||
// Now do the subframes. | |||
for (Iterator i = getImportedFrames(); i.hasNext();) { | |||
ExecutionFrame importedFrame = (ExecutionFrame)i.next(); | |||
importedFrame.checkTargets(dependencyOrder, state, visiting); | |||
} | |||
} | |||
private ExecutionTask getConfiguredExecutionTask(TaskElement model) | |||
/** | |||
* Create a Task and configure it according to the given model. | |||
*/ | |||
private Task configureTask(TaskElement model) | |||
throws ConfigException, ExecutionException { | |||
String taskType = model.getType(); | |||
TaskDefinition taskDefinition = (TaskDefinition)taskDefs.get(taskType); | |||
if (taskDefinition == null) { | |||
throw new ConfigException("There is no task defintion for tasks of type <" | |||
throw new ConfigException("There is no defintion for tasks of type <" | |||
+ taskType + ">", model.getLocation()); | |||
} | |||
try { | |||
Class executionTaskClass = taskDefinition.getExecutionTaskClass(); | |||
ExecutionTask executionTask = (ExecutionTask)executionTaskClass.newInstance(); | |||
executionTask.setExecutionFrame(this); | |||
executionTask.setBuildEventSupport(eventSupport); | |||
executionTask.setBuildElement(model); | |||
configureElement(executionTask, model); | |||
return executionTask; | |||
Class elementClass = taskDefinition.getExecutionTaskClass(); | |||
Object element = elementClass.newInstance(); | |||
Task task = null; | |||
if (element instanceof Task) { | |||
// create a Task context for the Task | |||
task = (Task)element; | |||
} | |||
else { | |||
task = new TaskAdapter(taskType, element); | |||
} | |||
ExecutionContext context = new ExecutionContext(this, eventSupport, model); | |||
task.setTaskContext(context); | |||
configureElement(element, model); | |||
return task; | |||
} | |||
catch (ClassNotFoundException e) { | |||
throw new ConfigException("Execution class " + taskDefinition.getTaskClassName() | |||
@@ -339,43 +564,51 @@ public class ExecutionFrame { | |||
e, model.getLocation()); | |||
} | |||
} | |||
/** | |||
* Run the tasks returned by the give iterator | |||
* | |||
* @param taskIterator the iterator giving the tasks to execute | |||
*/ | |||
public void executeTasks(Iterator taskIterator) throws ExecutionException, ConfigException { | |||
Task task = null; | |||
try { | |||
while (taskIterator.hasNext()) { | |||
task = (Task)taskIterator.next(); | |||
private List getActiveAspects(BuildElement model) | |||
throws ConfigException, ExecutionException, | |||
ClassIntrospectionException, ConversionException { | |||
List activeAspects = new ArrayList(); | |||
for (Iterator i = model.getAspectNames(); i.hasNext();) { | |||
String aspectPrefix = (String)i.next(); | |||
Class aspectHandlerClass = (Class)aspectHandlers.get(aspectPrefix); | |||
if (aspectHandlerClass != null) { | |||
try { | |||
ExecutionTask executionTask = getConfiguredExecutionTask(task); | |||
eventSupport.fireTaskStarted(this, task); | |||
executionTask.execute(); | |||
} | |||
catch (ExecutionException e) { | |||
if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) { | |||
e.setLocation(task.getLocation()); | |||
AspectHandler aspectHandler | |||
= (AspectHandler)aspectHandlerClass.newInstance(); | |||
ClassIntrospector introspector = getIntrospector(aspectHandlerClass); | |||
ExecutionContext context = new ExecutionContext(this, eventSupport, model); | |||
aspectHandler.setAspectContext(context); | |||
Map aspectAttributes = model.getAspectAttributes(aspectPrefix); | |||
for (Iterator j = aspectAttributes.keySet().iterator(); j.hasNext();) { | |||
String attributeName = (String)j.next(); | |||
String attributeValue = (String)aspectAttributes.get(attributeName); | |||
introspector.setAttribute(aspectHandler, attributeName, | |||
replacePropertyRefs(attributeValue)); | |||
} | |||
throw e; | |||
activeAspects.add(aspectHandler); | |||
} | |||
catch (ConfigException e) { | |||
if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) { | |||
e.setLocation(task.getLocation()); | |||
} | |||
throw e; | |||
catch (InstantiationException e) { | |||
throw new ConfigException("Unable to instantiate aspect handler class " | |||
+ aspectHandlerClass, | |||
e); | |||
} | |||
catch (IllegalAccessException e) { | |||
throw new ConfigException("Unable to access aspect handler class " | |||
+ aspectHandlerClass, | |||
e); | |||
} | |||
eventSupport.fireTaskFinished(this, task, null); | |||
} | |||
} | |||
catch (RuntimeException e) { | |||
eventSupport.fireTaskFinished(this, task, e); | |||
throw e; | |||
} | |||
} | |||
} | |||
return activeAspects; | |||
} | |||
/** | |||
* Configure an element according to the given model. | |||
*/ | |||
private void configureElement(Object element, TaskElement model) | |||
throws ExecutionException, ConfigException { | |||
@@ -401,11 +634,9 @@ public class ExecutionFrame { | |||
if (element instanceof TaskContainer && | |||
!introspector.supportsNestedElement(nestedElementModel.getType())) { | |||
ExecutionTask nestedExecutionTask | |||
= getConfiguredExecutionTask(nestedElementModel); | |||
Task nestedTask = configureTask(nestedElementModel); | |||
TaskContainer container = (TaskContainer)element; | |||
container.addExecutionTask(nestedExecutionTask); | |||
container.addTask(nestedTask); | |||
} | |||
else { | |||
Object nestedElement | |||
@@ -413,6 +644,11 @@ public class ExecutionFrame { | |||
configureElement(nestedElement, nestedElementModel); | |||
} | |||
} | |||
List aspects = getActiveAspects(model); | |||
for (Iterator i = aspects.iterator(); i.hasNext(); ) { | |||
AspectHandler aspectHandler = (AspectHandler)i.next(); | |||
aspectHandler.afterConfigElement(element); | |||
} | |||
} | |||
catch (ClassIntrospectionException e) { | |||
throw new ExecutionException(e, model.getLocation()); | |||
@@ -422,6 +658,42 @@ public class ExecutionFrame { | |||
} | |||
} | |||
/** | |||
* Run the tasks returned by the give iterator | |||
* | |||
* @param taskIterator the iterator giving the tasks to execute | |||
*/ | |||
public void executeTasks(Iterator taskIterator) throws ExecutionException, ConfigException { | |||
TaskElement task = null; | |||
try { | |||
while (taskIterator.hasNext()) { | |||
task = (TaskElement)taskIterator.next(); | |||
try { | |||
Task configuredTask = configureTask(task); | |||
eventSupport.fireTaskStarted(this, task); | |||
configuredTask.execute(); | |||
} | |||
catch (ExecutionException e) { | |||
if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) { | |||
e.setLocation(task.getLocation()); | |||
} | |||
throw e; | |||
} | |||
catch (ConfigException e) { | |||
if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) { | |||
e.setLocation(task.getLocation()); | |||
} | |||
throw e; | |||
} | |||
eventSupport.fireTaskFinished(this, task, null); | |||
} | |||
} | |||
catch (RuntimeException e) { | |||
eventSupport.fireTaskFinished(this, task, e); | |||
throw e; | |||
} | |||
} | |||
private ClassIntrospector getIntrospector(Class c) { | |||
if (introspectors.containsKey(c)) { | |||
return (ClassIntrospector)introspectors.get(c); | |||
@@ -510,7 +782,7 @@ public class ExecutionFrame { | |||
* Given a name of an object, get the frame relative from this frame that | |||
* contains that object. | |||
*/ | |||
private ExecutionFrame getRelativeFrame(String name) throws ExecutionException { | |||
public ExecutionFrame getRelativeFrame(String name) throws ExecutionException { | |||
int index = name.lastIndexOf(":"); | |||
if (index == -1) { | |||
return this; | |||
@@ -534,7 +806,7 @@ public class ExecutionFrame { | |||
/** | |||
* Get the name of an object in its frame | |||
*/ | |||
private String getNameInFrame(String name) { | |||
public String getNameInFrame(String name) { | |||
int index = name.lastIndexOf(":"); | |||
if (index == -1) { | |||
return name; | |||
@@ -553,7 +825,7 @@ public class ExecutionFrame { | |||
/** | |||
* Get a value from this frame or any imported frame | |||
*/ | |||
private Object getDataValue(String name) throws ExecutionException { | |||
public Object getDataValue(String name) throws ExecutionException { | |||
ExecutionFrame frame = getRelativeFrame(name); | |||
return frame.getDirectDataValue(getNameInFrame(name)); | |||
} | |||
@@ -586,5 +858,55 @@ public class ExecutionFrame { | |||
private boolean isDirectDataValueSet(String name) { | |||
return dataValues.containsKey(name); | |||
} | |||
public void runBuild(List targetNames) throws AntException { | |||
Throwable buildFailureCause = null; | |||
try { | |||
eventSupport.fireBuildStarted(this, project); | |||
initialize(); | |||
if (targetNames.isEmpty()) { | |||
// we just execute the default target if any | |||
String defaultTarget = project.getDefaultTarget(); | |||
if (defaultTarget != null) { | |||
executeTarget(defaultTarget); | |||
} | |||
} | |||
else { | |||
for (Iterator i = targetNames.iterator(); i.hasNext();) { | |||
executeTarget((String)i.next()); | |||
} | |||
} | |||
eventSupport.fireBuildFinished(this, project, null); | |||
} | |||
catch (RuntimeException e) { | |||
buildFailureCause = e; | |||
throw e; | |||
} | |||
catch (AntException e) { | |||
buildFailureCause = e; | |||
throw e; | |||
} | |||
finally { | |||
eventSupport.fireBuildFinished(this, project, buildFailureCause); | |||
} | |||
} | |||
public void executeTarget(String targetName) throws ExecutionException, ConfigException { | |||
// to execute a target we must determine its dependencies and | |||
// execute them in order. | |||
Map state = new HashMap(); | |||
Stack visiting = new Stack(); | |||
List dependencyOrder = new ArrayList(); | |||
ExecutionFrame startingFrame = getRelativeFrame(targetName); | |||
startingFrame.fillinDependencyOrder(getNameInFrame(targetName), | |||
dependencyOrder, state, visiting); | |||
// Now tell each frame to execute the targets required | |||
for (Iterator i = dependencyOrder.iterator(); i.hasNext();) { | |||
String fullTargetName = (String)i.next(); | |||
ExecutionFrame frame = getRelativeFrame(fullTargetName); | |||
frame.executeTargetTasks(getNameInFrame(fullTargetName)); | |||
} | |||
} | |||
} |
@@ -1,317 +0,0 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.core.execution; | |||
import org.apache.ant.core.model.*; | |||
import org.apache.ant.core.support.*; | |||
import java.util.*; | |||
/** | |||
* The ExecutionManager manages the execution of Ant. It will create | |||
* ExecutionFrames to handle the various imported projects, the | |||
* data values associated with those projects. Before the ExecutionManager | |||
* can be used, it must be initialised with a set of Ant libraries. These | |||
* will contain task definitions, aspect definitions, etc. | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public class ExecutionManager implements BuildListener { | |||
private static final String VISITING = "VISITING"; | |||
private static final String VISITED = "VISITED"; | |||
private HashMap taskDefs = new HashMap(); | |||
private HashMap converterDefs = new HashMap(); | |||
private Project project; | |||
private ExecutionFrame mainFrame; | |||
private Map namespaceMap = null; | |||
private List frameInitOrder = null; | |||
private BuildEventSupport eventSupport = new BuildEventSupport(); | |||
public void addBuildListener(BuildListener listener) { | |||
eventSupport.addBuildListener(listener); | |||
} | |||
public void removeBuildListener(BuildListener listener) { | |||
eventSupport.removeBuildListener(listener); | |||
} | |||
/** | |||
* Forward any events to our listeners. | |||
*/ | |||
public void processBuildEvent(BuildEvent event) { | |||
eventSupport.forwardEvent(event); | |||
} | |||
public void addLibraries(AntLibrary[] libraries) throws ConfigException { | |||
for (int i = 0; i < libraries.length; ++i) { | |||
addLibrary(libraries[i]); | |||
} | |||
} | |||
public void addLibrary(AntLibrary library) throws ConfigException { | |||
for (Iterator i = library.getTaskDefinitions(); i.hasNext(); ) { | |||
TaskDefinition taskDefinition = (TaskDefinition)i.next(); | |||
addTaskDefinition(taskDefinition); | |||
} | |||
for (Iterator i = library.getConverterDefinitions(); i.hasNext(); ) { | |||
ConverterDefinition converterDef = (ConverterDefinition)i.next(); | |||
addConverterDefinition(converterDef); | |||
} | |||
} | |||
public void addTaskDefinition(TaskDefinition taskDefinition) throws ConfigException { | |||
String taskName = taskDefinition.getName(); | |||
if (taskDefs.containsKey(taskName)) { | |||
String message = "Task " + taskName + " is defined twice" + | |||
", in " + ((TaskDefinition)taskDefs.get(taskName)).getLibraryURL() + | |||
" and " + taskDefinition.getLibraryURL(); | |||
throw new ConfigException(message, new Location(taskDefinition.getLibraryURL().toString())); | |||
} | |||
taskDefs.put(taskName, taskDefinition); | |||
} | |||
public void addConverterDefinition(ConverterDefinition converterDef) throws ConfigException { | |||
String targetClassname = converterDef.getTargetClassName(); | |||
if (converterDefs.containsKey(targetClassname)) { | |||
String message = "Converter for " + targetClassname + " is defined twice" + | |||
", in " + ((ConverterDefinition)converterDefs.get(targetClassname)).getLibraryURL() + | |||
" and " + converterDef.getLibraryURL(); | |||
throw new ConfigException(message, new Location(converterDef.getLibraryURL().toString())); | |||
} | |||
converterDefs.put(targetClassname, converterDef); | |||
} | |||
public void setProject(Project project) throws ConfigException { | |||
this.project = project; | |||
mainFrame = new ExecutionFrame(project, (Map)taskDefs.clone(), | |||
(Map)converterDefs.clone(), null); | |||
namespaceMap = new HashMap(); | |||
frameInitOrder = new ArrayList(); | |||
setupFrame(mainFrame); | |||
// We iterate through all nodes of all projects and make sure every node is OK | |||
Map state = new HashMap(); | |||
Stack visiting = new Stack(); | |||
List dependencyOrder = new ArrayList(); | |||
checkFrameTargets(mainFrame, dependencyOrder, state, visiting); | |||
} | |||
/** | |||
* Check whether the targets in the given execution frame and its subframes are OK | |||
*/ | |||
private void checkFrameTargets(ExecutionFrame frame, List dependencyOrder, | |||
Map state, Stack visiting) | |||
throws ConfigException { | |||
// get the targets and just iterate through them. | |||
for (Iterator i = frame.getProject().getTargets(); i.hasNext();) { | |||
Target target = (Target)i.next(); | |||
fillinDependencyOrder(frame, target.getName(), | |||
dependencyOrder, state, visiting); | |||
} | |||
// Now do the subframes. | |||
for (Iterator i = frame.getImportedFrames(); i.hasNext();) { | |||
ExecutionFrame importedFrame = (ExecutionFrame)i.next(); | |||
checkFrameTargets(importedFrame, dependencyOrder, state, visiting); | |||
} | |||
} | |||
private void setupFrame(ExecutionFrame frame) { | |||
frame.addBuildListener(this); | |||
String namespace = frame.getNamespace(); | |||
if (namespace != null) { | |||
namespaceMap.put(namespace, frame); | |||
} | |||
for (Iterator i = frame.getImportedFrameNames(); i.hasNext();) { | |||
String importName = (String)i.next(); | |||
setupFrame(frame.getImportedFrame(importName)); | |||
} | |||
frameInitOrder.add(frame); | |||
} | |||
public void runBuild(List targetNames) throws AntException { | |||
Throwable buildFailureCause = null; | |||
try { | |||
eventSupport.fireBuildStarted(this, project); | |||
// we initialise each execution frame | |||
for (Iterator i = frameInitOrder.iterator(); i.hasNext();) { | |||
ExecutionFrame frame = (ExecutionFrame)i.next(); | |||
frame.initialise(); | |||
} | |||
if (targetNames.isEmpty()) { | |||
// we just execute the default target if any | |||
String defaultTarget = project.getDefaultTarget(); | |||
if (defaultTarget != null) { | |||
executeTarget(defaultTarget); | |||
} | |||
} | |||
else { | |||
for (Iterator i = targetNames.iterator(); i.hasNext();) { | |||
executeTarget((String)i.next()); | |||
} | |||
} | |||
eventSupport.fireBuildFinished(this, project, null); | |||
} | |||
catch (RuntimeException e) { | |||
buildFailureCause = e; | |||
throw e; | |||
} | |||
catch (AntException e) { | |||
buildFailureCause = e; | |||
throw e; | |||
} | |||
finally { | |||
eventSupport.fireBuildFinished(this, project, buildFailureCause); | |||
} | |||
} | |||
private ExecutionFrame getFrame(String name) { | |||
int namespaceIndex = name.lastIndexOf(":"); | |||
if (namespaceIndex == -1) { | |||
return mainFrame; | |||
} | |||
return (ExecutionFrame)namespaceMap.get(name.substring(0, namespaceIndex)); | |||
} | |||
public void executeTarget(String targetName) throws ExecutionException, ConfigException { | |||
// to execute a target we must determine its dependencies and | |||
// execute them in order. | |||
Map state = new HashMap(); | |||
Stack visiting = new Stack(); | |||
List dependencyOrder = new ArrayList(); | |||
ExecutionFrame startingFrame = getFrame(targetName); | |||
fillinDependencyOrder(startingFrame, startingFrame.getRelativeName(targetName), | |||
dependencyOrder, state, visiting); | |||
// Now tell each frame to execute the target | |||
for (Iterator i = dependencyOrder.iterator(); i.hasNext();) { | |||
String fullTargetName = (String)i.next(); | |||
ExecutionFrame frame = getFrame(fullTargetName); | |||
frame.executeTargetTasks(frame.getRelativeName(fullTargetName)); | |||
} | |||
} | |||
private void fillinDependencyOrder(ExecutionFrame frame, String targetName, | |||
List dependencyOrder, Map state, | |||
Stack visiting) throws ConfigException { | |||
String fullTargetName = frame.getQualifiedName(targetName); | |||
if (state.get(fullTargetName) == VISITED) { | |||
return; | |||
} | |||
Target target = frame.getProject().getTarget(targetName); | |||
if (target == null) { | |||
StringBuffer sb = new StringBuffer("Target `"); | |||
sb.append(targetName); | |||
sb.append("' does not exist in this project. "); | |||
if (!visiting.empty()) { | |||
String parent = (String)visiting.peek(); | |||
sb.append("It is used from target `"); | |||
sb.append(parent); | |||
sb.append("'."); | |||
} | |||
throw new ConfigException(new String(sb), frame.getProject().getLocation()); | |||
} | |||
state.put(fullTargetName, VISITING); | |||
visiting.push(fullTargetName); | |||
for (Iterator i = target.getDependencies(); i.hasNext(); ) { | |||
String dependency = (String)i.next(); | |||
String fullyQualifiedName = frame.getQualifiedName(dependency); | |||
ExecutionFrame dependencyFrame = getFrame(fullyQualifiedName); | |||
if (dependencyFrame == null) { | |||
StringBuffer sb = new StringBuffer("Target `"); | |||
sb.append(dependency); | |||
sb.append("' does not exist in this project. "); | |||
throw new ConfigException(new String(sb), target.getLocation()); | |||
} | |||
String dependencyState = (String)state.get(fullyQualifiedName); | |||
if (dependencyState == null) { | |||
fillinDependencyOrder(dependencyFrame, dependencyFrame.getRelativeName(fullyQualifiedName), | |||
dependencyOrder, state, visiting); | |||
} | |||
else if (dependencyState == VISITING) { | |||
String circleDescription | |||
= getCircularDesc(dependency, visiting); | |||
throw new ConfigException(circleDescription, target.getLocation()); | |||
} | |||
} | |||
state.put(fullTargetName, VISITED); | |||
String poppedNode = (String)visiting.pop(); | |||
if (poppedNode != fullTargetName) { | |||
throw new ConfigException("Problem determining dependencies " + | |||
" - expecting '" + fullTargetName + | |||
"' but got '" + poppedNode + "'"); | |||
} | |||
dependencyOrder.add(fullTargetName); | |||
} | |||
private String getCircularDesc(String end, Stack visitingNodes) { | |||
StringBuffer sb = new StringBuffer("Circular dependency: "); | |||
sb.append(end); | |||
String c; | |||
do { | |||
c = (String)visitingNodes.pop(); | |||
sb.append(" <- "); | |||
sb.append(c); | |||
} while(!c.equals(end)); | |||
return new String(sb); | |||
} | |||
} |
@@ -51,25 +51,23 @@ | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.core.model; | |||
package org.apache.ant.core.execution; | |||
import org.apache.ant.core.model.*; | |||
import org.apache.ant.core.support.*; | |||
import java.util.*; | |||
import java.net.URL; | |||
/** | |||
* A Task is a holder for Task information (attributes and elements) | |||
* A task is a top level element in the buidl which will be processed. Ant | |||
* currently handles two types of tasks - DataType tasks and execution tasks. | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public class Task extends TaskElement { | |||
/** | |||
* Create a Task of the given type | |||
* | |||
* @param location the location of the element | |||
* @param type the task's type | |||
*/ | |||
public Task(Location location, String type) { | |||
super(location, type); | |||
} | |||
public interface Task { | |||
void setTaskContext(ExecutionContext context); | |||
void execute() throws ExecutionException; | |||
} | |||
@@ -0,0 +1,100 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 1999 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.core.execution; | |||
import java.lang.reflect.*; | |||
import java.util.*; | |||
/** | |||
* Use introspection to "adapt" an arbitrary Bean ( not extending Task, but with similar | |||
* patterns). | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public class TaskAdapter extends AbstractTask { | |||
/** | |||
* The real object that is performing the work | |||
*/ | |||
private Object worker; | |||
private Method executeMethod = null; | |||
public TaskAdapter(String taskType, Object worker) | |||
throws ExecutionException { | |||
this.worker = worker; | |||
try { | |||
Class workerClass = worker.getClass(); | |||
executeMethod = workerClass.getMethod("execute", new Class[0]); | |||
if (executeMethod == null) { | |||
throw new ExecutionException("No execute method in the class for the <" | |||
+ taskType + "> task."); | |||
} | |||
} | |||
catch (NoSuchMethodException e) { | |||
throw new ExecutionException(e); | |||
} | |||
} | |||
public void execute() throws ExecutionException { | |||
try { | |||
executeMethod.invoke(worker, null); | |||
} | |||
catch( Exception ex ) { | |||
throw new ExecutionException(ex); | |||
} | |||
} | |||
} |
@@ -67,6 +67,6 @@ public interface TaskContainer { | |||
/** | |||
* Add a task to the container. | |||
*/ | |||
void addExecutionTask(ExecutionTask executionTask) throws ExecutionException; | |||
void addTask(Task task) throws ExecutionException; | |||
} | |||
@@ -117,7 +117,7 @@ public class TaskDefinition { | |||
*/ | |||
public synchronized Class getExecutionTaskClass() throws ClassNotFoundException { | |||
if (taskClass == null) { | |||
taskClass = taskClassLoader.loadClass(taskClassName); | |||
taskClass = Class.forName(taskClassName, true, taskClassLoader); | |||
} | |||
return taskClass; | |||
} | |||
@@ -63,20 +63,13 @@ import org.apache.ant.core.support.*; | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public class BuildElement { | |||
/** | |||
* The aspects defined for this element. | |||
*/ | |||
private Map aspects; | |||
/** The aspects defined for this element. */ | |||
private Map aspectMaps; | |||
/** | |||
* The location of this element | |||
*/ | |||
/** The location of this element */ | |||
private Location location; | |||
/** | |||
* A comment associated with this element, if any | |||
* | |||
*/ | |||
/** A comment associated with this element, if any */ | |||
private String comment; | |||
/** | |||
@@ -121,7 +114,44 @@ public class BuildElement { | |||
* @param aspects a Map of apects that relate to this build element. | |||
*/ | |||
public void setAspects(Map aspects) { | |||
this.aspects = aspects; | |||
aspectMaps = new HashMap(); | |||
for (Iterator i = aspects.keySet().iterator(); i.hasNext(); ) { | |||
String aspectName = (String)i.next(); | |||
int separator = aspectName.indexOf(":"); | |||
if (separator != -1) { | |||
String prefix = aspectName.substring(0, separator); | |||
String name = aspectName.substring(separator + 1); | |||
if (prefix.length() != 0 && name.length() != 0) { | |||
Map prefixMap = (Map)aspectMaps.get(prefix); | |||
if (prefixMap == null) { | |||
prefixMap = new HashMap(); | |||
aspectMaps.put(prefix, prefixMap); | |||
} | |||
prefixMap.put(name, aspects.get(aspectName)); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Get an iterator on the aspects which have been given values on this element | |||
* | |||
* @return an iterator of Strings , being the aspects which have been given values on | |||
* this element. | |||
*/ | |||
public Iterator getAspectNames() { | |||
return aspectMaps.keySet().iterator(); | |||
} | |||
/** | |||
* Get the set of attribute values related to the given aspect | |||
* | |||
* @param apsectPrefix the prefix used to identify the prefix. | |||
* | |||
* @return a map of the attribute values for the given aspect. | |||
*/ | |||
public Map getAspectAttributes(String aspectPrefix) { | |||
return (Map)aspectMaps.get(aspectPrefix); | |||
} | |||
} | |||
@@ -191,7 +191,7 @@ public class Project extends BuildElement { | |||
* @param task a task to be executed when an execution context | |||
* is associated with the Project (a non-target task) | |||
*/ | |||
public void addTask(Task task) { | |||
public void addTask(TaskElement task) { | |||
tasks.add(task); | |||
} | |||
@@ -100,7 +100,7 @@ public class Target extends BuildElement { | |||
* | |||
* @param task the task to be added to the target. | |||
*/ | |||
public void addTask(Task task) { | |||
public void addTask(TaskElement task) { | |||
tasks.add(task); | |||
} | |||
@@ -59,14 +59,17 @@ import java.net.*; | |||
import java.io.*; | |||
/** | |||
* A ReverseURLclassLoader is a type of URL classloader which reverse the standard | |||
* The AntClassLoader is a type of URL classloader which reverse the standard | |||
* lookup order to load things from the URLs first and then to use the parent class | |||
* loader only if the class does not exist in the URLs. | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public class AntClassLoader extends URLClassLoader { | |||
/** A Debug label to print when the Classloader finds or fails to find a class. */ | |||
private String debugLabel = null; | |||
/** A flag whihc controls whether messages are logged by the loader */ | |||
private boolean debug = false; | |||
private void dumpURLs() { | |||
@@ -110,7 +110,7 @@ public abstract class AntException extends Exception { | |||
* @param cause Exception that might have caused this one. | |||
*/ | |||
public AntException(Throwable cause) { | |||
super(cause.toString()); | |||
super(cause.getMessage()); | |||
this.cause = cause; | |||
} | |||
@@ -0,0 +1,131 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.core.types; | |||
import org.apache.ant.core.execution.*; | |||
import java.io.*; | |||
/** | |||
* A DataType is an element which can register a named value in the | |||
* ExecutionFrame's context. | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
*/ | |||
public abstract class DataType extends AbstractTask { | |||
private String reference = null; | |||
final public void execute() throws ExecutionException { | |||
} | |||
/** | |||
* Creates an exception that indicates that refid has to be the | |||
* only attribute if it is set. | |||
*/ | |||
protected ExecutionException tooManyAttributes() { | |||
return new ExecutionException("You must not specify more than one attribute" + | |||
" when using refid" ); | |||
} | |||
/** | |||
* Creates an exception that indicates that this XML element must | |||
* not have child elements if the refid attribute is set. | |||
*/ | |||
protected ExecutionException noChildrenAllowed() { | |||
return new ExecutionException("You must not specify nested elements when using refid"); | |||
} | |||
/** | |||
* Creates an exception that indicates the user has generated a | |||
* loop of data types referencing each other. | |||
*/ | |||
protected ExecutionException circularReference() { | |||
return new ExecutionException("This data type contains a circular reference."); | |||
} | |||
/** | |||
* Makes this instance in effect a reference to another DataType | |||
* instance. | |||
*/ | |||
public void setRefid(String reference) throws ExecutionException { | |||
this.reference = reference; | |||
// check the reference now | |||
getReferencedObject(); | |||
} | |||
/** | |||
* Has the refid attribute of this element been set? | |||
*/ | |||
public boolean isReference() { | |||
return reference != null; | |||
} | |||
protected Object getReferencedObject() throws ExecutionException { | |||
if (!isReference()) { | |||
throw new ExecutionException("You cannot get a referenced value from a data type " + | |||
"which does not have the refid attribute"); | |||
} | |||
Object referencedObject = getTaskContext().getDataValue(reference); | |||
if (referencedObject == null) { | |||
throw new ExecutionException("Unable to locate the reference specified by refid '" + | |||
getReference() + "'"); | |||
} | |||
return referencedObject; | |||
} | |||
protected String getReference() { | |||
return reference; | |||
} | |||
} |
@@ -0,0 +1,369 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2000 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.core.types; | |||
import java.io.*; | |||
import java.util.*; | |||
import org.apache.ant.core.execution.*; | |||
/** | |||
* Named collection of include/exclude tags. | |||
* | |||
* <p>Moved out of MatchingTask to make it a standalone object that | |||
* could be referenced (by scripts for example). | |||
* | |||
* @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a> | |||
* @author Stefano Mazzocchi <a href="mailto:stefano@apache.org">stefano@apache.org</a> | |||
* @author Sam Ruby <a href="mailto:rubys@us.ibm.com">rubys@us.ibm.com</a> | |||
* @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</a> | |||
* @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a> | |||
*/ | |||
public class PatternSet extends DataType { | |||
private List includeList = new ArrayList(); | |||
private List excludeList = new ArrayList(); | |||
// private File incl = null; | |||
// private File excl = null; | |||
// | |||
/** | |||
* inner class to hold a name on list. "If" and "Unless" attributes | |||
* may be used to invalidate the entry based on the existence of a | |||
* property (typically set thru the use of the Available task). | |||
*/ | |||
public class NameEntry { | |||
private String name; | |||
// private String ifCond; | |||
// private String unlessCond; | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
// public void setIf(String cond) { | |||
// ifCond = cond; | |||
// } | |||
// | |||
// public void setUnless(String cond) { | |||
// unlessCond = cond; | |||
// } | |||
// | |||
public String getName() { | |||
return name; | |||
} | |||
// public String evalName(Project p) { | |||
// return valid(p) ? name : null; | |||
// } | |||
// private boolean valid(Project p) { | |||
// if (ifCond != null && p.getProperty(ifCond) == null) { | |||
// return false; | |||
// } else if (unlessCond != null && p.getProperty(unlessCond) != null) { | |||
// return false; | |||
// } | |||
// return true; | |||
// } | |||
} | |||
public PatternSet() { | |||
} | |||
/** | |||
* Makes this instance in effect a reference to another PatternSet | |||
* instance. | |||
* | |||
* <p>You must not set another attribute or nest elements inside | |||
* this element if you make it a reference.</p> | |||
*/ | |||
public void setRefid(String reference) throws ExecutionException { | |||
if (!includeList.isEmpty() || !excludeList.isEmpty()) { | |||
throw tooManyAttributes(); | |||
} | |||
super.setRefid(reference); | |||
} | |||
/** | |||
* add a name entry on the include list | |||
*/ | |||
public NameEntry createInclude() throws ExecutionException { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
return addPatternToList(includeList); | |||
} | |||
/** | |||
* add a name entry on the exclude list | |||
*/ | |||
public NameEntry createExclude() throws ExecutionException { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
return addPatternToList(excludeList); | |||
} | |||
/** | |||
* Sets the set of include patterns. Patterns may be separated by a comma | |||
* or a space. | |||
* | |||
* @param includes the string containing the include patterns | |||
*/ | |||
public void setIncludes(String includes) throws ExecutionException { | |||
if (isReference()) { | |||
throw tooManyAttributes(); | |||
} | |||
if (includes != null && includes.length() > 0) { | |||
StringTokenizer tok = new StringTokenizer(includes, ", ", false); | |||
while (tok.hasMoreTokens()) { | |||
createInclude().setName(tok.nextToken()); | |||
} | |||
} | |||
} | |||
/** | |||
* Sets the set of exclude patterns. Patterns may be separated by a comma | |||
* or a space. | |||
* | |||
* @param excludes the string containing the exclude patterns | |||
*/ | |||
public void setExcludes(String excludes) throws ExecutionException { | |||
if (isReference()) { | |||
throw tooManyAttributes(); | |||
} | |||
if (excludes != null && excludes.length() > 0) { | |||
StringTokenizer tok = new StringTokenizer(excludes, ", ", false); | |||
while (tok.hasMoreTokens()) { | |||
createExclude().setName(tok.nextToken()); | |||
} | |||
} | |||
} | |||
/** | |||
* add a name entry to the given list | |||
*/ | |||
private NameEntry addPatternToList(List list) { | |||
NameEntry result = new NameEntry(); | |||
list.add(result); | |||
return result; | |||
} | |||
// /** | |||
// * Sets the name of the file containing the includes patterns. | |||
// * | |||
// * @param incl The file to fetch the include patterns from. | |||
// */ | |||
// public void setIncludesfile(File incl) throws BuildException { | |||
// if (isReference()) { | |||
// throw tooManyAttributes(); | |||
// } | |||
// if (!incl.exists()) { | |||
// throw new BuildException("Includesfile "+incl.getAbsolutePath() | |||
// +" not found."); | |||
// } | |||
// this.incl = incl; | |||
// } | |||
// | |||
// /** | |||
// * Sets the name of the file containing the excludes patterns. | |||
// * | |||
// * @param excl The file to fetch the exclude patterns from. | |||
// */ | |||
// public void setExcludesfile(File excl) throws BuildException { | |||
// if (isReference()) { | |||
// throw tooManyAttributes(); | |||
// } | |||
// if (!excl.exists()) { | |||
// throw new BuildException("Excludesfile "+excl.getAbsolutePath() | |||
// +" not found."); | |||
// } | |||
// this.excl = excl; | |||
// } | |||
// | |||
// /** | |||
// * Reads path matching patterns from a file and adds them to the | |||
// * includes or excludes list (as appropriate). | |||
// */ | |||
// private void readPatterns(File patternfile, Vector patternlist, Project p) | |||
// throws BuildException { | |||
// | |||
// try { | |||
// // Get a FileReader | |||
// BufferedReader patternReader = | |||
// new BufferedReader(new FileReader(patternfile)); | |||
// | |||
// // Create one NameEntry in the appropriate pattern list for each | |||
// // line in the file. | |||
// String line = patternReader.readLine(); | |||
// while (line != null) { | |||
// if (line.length() > 0) { | |||
// line = ProjectHelper.replaceProperties(p, line, | |||
// p.getProperties()); | |||
// addPatternToList(patternlist).setName(line); | |||
// } | |||
// line = patternReader.readLine(); | |||
// } | |||
// } catch(IOException ioe) { | |||
// String msg = "An error occured while reading from pattern file: " | |||
// + patternfile; | |||
// throw new BuildException(msg, ioe); | |||
// } | |||
// } | |||
// | |||
/** | |||
* Adds the patterns of the other instance to this set. | |||
*/ | |||
public void append(PatternSet other) throws ExecutionException { | |||
if (isReference()) { | |||
throw new ExecutionException("Cannot append to a reference"); | |||
} | |||
String[] incl = other.getIncludePatterns(); | |||
if (incl != null) { | |||
for (int i=0; i<incl.length; i++) { | |||
createInclude().setName(incl[i]); | |||
} | |||
} | |||
String[] excl = other.getExcludePatterns(); | |||
if (excl != null) { | |||
for (int i=0; i<excl.length; i++) { | |||
createExclude().setName(excl[i]); | |||
} | |||
} | |||
} | |||
/** | |||
* Returns the filtered include patterns. | |||
*/ | |||
public String[] getIncludePatterns() throws ExecutionException { | |||
if (isReference()) { | |||
return getReferencedPatternSet().getIncludePatterns(); | |||
} else { | |||
// readFiles(p); | |||
return makeArray(includeList); | |||
} | |||
} | |||
/** | |||
* Returns the filtered include patterns. | |||
*/ | |||
public String[] getExcludePatterns() throws ExecutionException { | |||
if (isReference()) { | |||
return getReferencedPatternSet().getExcludePatterns(); | |||
} else { | |||
// readFiles(p); | |||
return makeArray(excludeList); | |||
} | |||
} | |||
// /** | |||
// * helper for FileSet. | |||
// */ | |||
// boolean hasPatterns() { | |||
// return incl != null || excl != null | |||
// || includeList.size() > 0 || excludeList.size() > 0; | |||
// } | |||
// | |||
/** | |||
* Performs the check for circular references and returns the | |||
* referenced PatternSet. | |||
*/ | |||
private PatternSet getReferencedPatternSet() throws ExecutionException { | |||
Object o = getReferencedObject(); | |||
if (!(o instanceof PatternSet)) { | |||
throw new ExecutionException(getReference() + " doesn\'t denote a patternset");; | |||
} else { | |||
return (PatternSet) o; | |||
} | |||
} | |||
/** | |||
* Convert a list of NameEntry elements into an array of Strings. | |||
*/ | |||
private String[] makeArray(List list) { | |||
if (list.size() == 0) { | |||
return null; | |||
} | |||
List tmpNames = new Vector(); | |||
for (Iterator i = list.iterator() ; i.hasNext() ;) { | |||
NameEntry ne = (NameEntry)i.next(); | |||
String pattern = ne.getName(); | |||
if (pattern != null && pattern.length() > 0) { | |||
tmpNames.add(pattern); | |||
} | |||
} | |||
String[] result = (String[])tmpNames.toArray(new String[0]); | |||
return result; | |||
} | |||
// /** | |||
// * Read includefile ot excludefile if not already done so. | |||
// */ | |||
// private void readFiles(Project p) { | |||
// if (incl != null) { | |||
// readPatterns(incl, includeList, p); | |||
// incl = null; | |||
// } | |||
// if (excl != null) { | |||
// readPatterns(excl, excludeList, p); | |||
// excl = null; | |||
// } | |||
// } | |||
// | |||
} |
@@ -72,6 +72,7 @@ import org.xml.sax.helpers.DefaultHandler; | |||
public class AntLibParser { | |||
public static final String TASK_ELEMENT = "taskdef"; | |||
public static final String CONVERTER_ELEMENT = "converter"; | |||
public static final String ASPECT_ELEMENT = "aspect"; | |||
/** | |||
* The factory used to create SAX parsers. | |||
@@ -191,6 +192,9 @@ public class AntLibParser { | |||
else if (qualifiedName.equals(CONVERTER_ELEMENT)) { | |||
createConverterDef(attributes); | |||
} | |||
else if (qualifiedName.equals(ASPECT_ELEMENT)) { | |||
createAspectHandler(attributes); | |||
} | |||
else { | |||
throw new SAXParseException("Unrecognized element <" + | |||
qualifiedName + "> in Ant library definition", getLocator()); | |||
@@ -219,7 +223,6 @@ public class AntLibParser { | |||
"<" + TASK_ELEMENT + "> element", getLocator()); | |||
} | |||
System.out.println("Adding taskdef for " + taskName); | |||
TaskDefinition taskdef = new TaskDefinition(getSourceURL(), taskName, className, componentLoader); | |||
library.addTaskDefinition(taskdef); | |||
} | |||
@@ -229,7 +232,7 @@ public class AntLibParser { | |||
validAttributes.add("target"); | |||
validAttributes.add("classname"); | |||
Map attributeValues | |||
= AttributeValidator.validateAttributes("convert", attributes, | |||
= AttributeValidator.validateAttributes(CONVERTER_ELEMENT, attributes, | |||
validAttributes, getLocator()); | |||
String targetClassName = (String)attributeValues.get("target"); | |||
String className = (String)attributeValues.get("classname"); | |||
@@ -248,6 +251,30 @@ public class AntLibParser { | |||
library.addConverterDefinition(converterDef); | |||
} | |||
public void createAspectHandler(Attributes attributes) throws SAXParseException { | |||
Set validAttributes = new HashSet(); | |||
validAttributes.add("prefix"); | |||
validAttributes.add("classname"); | |||
Map attributeValues | |||
= AttributeValidator.validateAttributes(ASPECT_ELEMENT, attributes, | |||
validAttributes, getLocator()); | |||
String aspectPrefix = (String)attributeValues.get("prefix"); | |||
String aspectClassname = (String)attributeValues.get("classname"); | |||
if (aspectPrefix == null) { | |||
throw new SAXParseException("'prefix' attribute is required in a <" | |||
+ ASPECT_ELEMENT + "> element", | |||
getLocator()); | |||
} | |||
if (aspectClassname == null) { | |||
throw new SAXParseException("'classname' attribute is required in a " + | |||
"<" + ASPECT_ELEMENT + "> element", getLocator()); | |||
} | |||
AspectDefinition aspectDef | |||
= new AspectDefinition(getSourceURL(), aspectPrefix, aspectClassname, componentLoader); | |||
library.addAspectDefinition(aspectDef); | |||
} | |||
public void endElement(String namespaceURI, String localName, String qName) { | |||
if (state == STATE_ROOT_SEEN && qName.equals("antlib")) { | |||
state = STATE_FINISHED; | |||
@@ -373,10 +373,10 @@ public class XMLProjectParser { | |||
} | |||
else { | |||
// everything else is a task | |||
TaskHandler taskHandler | |||
= new TaskHandler(getXMLReader(), this, getLocator(), | |||
TaskElementHandler taskElementHandler | |||
= new TaskElementHandler(getXMLReader(), this, getLocator(), | |||
attributes, qualifiedName); | |||
project.addTask(taskHandler.getTask()); | |||
project.addTask(taskElementHandler.getTaskElement()); | |||
} | |||
} | |||
@@ -730,10 +730,10 @@ public class XMLProjectParser { | |||
public void startElement(String uri, String localName, String qualifiedName, | |||
Attributes attributes) throws SAXParseException { | |||
// everything is a task | |||
TaskHandler taskHandler | |||
= new TaskHandler(getXMLReader(), this, getLocator(), | |||
attributes, qualifiedName); | |||
target.addTask(taskHandler.getTask()); | |||
TaskElementHandler taskHandler | |||
= new TaskElementHandler(getXMLReader(), this, getLocator(), | |||
attributes, qualifiedName); | |||
target.addTask(taskHandler.getTaskElement()); | |||
} | |||
/** | |||
@@ -747,80 +747,7 @@ public class XMLProjectParser { | |||
} | |||
/** | |||
* A Task Handler is used to parse tasks. | |||
*/ | |||
private class TaskHandler extends ElementHandler { | |||
/** | |||
* The task being parsed by this handler. | |||
*/ | |||
private Task task; | |||
/** | |||
* Create a task handler to parse the Task element | |||
* | |||
* @param xmlReader the XML parser being used to parse the task element. | |||
* @param parent the parent element handler. | |||
* @param locator the SAX locator object used to associate elements with source | |||
* locations. | |||
* @param attributes attributes of the task | |||
* @param taskTagName the name of the task. | |||
*/ | |||
public TaskHandler(XMLReader xmlReader, ContentHandler parent, Locator locator, | |||
Attributes attributes, String taskTagName) { | |||
super(xmlReader, parent, locator); | |||
task = new Task(getLocation(locator), taskTagName); | |||
Map aspects = new HashMap(); | |||
for (int i = 0; i < attributes.getLength(); ++i) { | |||
String attributeName = attributes.getQName(i); | |||
String attributeValue = attributes.getValue(i); | |||
if (attributeName.indexOf(":") != -1) { | |||
// potential aspect attribute | |||
aspects.put(attributeName, attributeValue); | |||
} | |||
else { | |||
task.addAttribute(attributeName, attributeValue); | |||
} | |||
} | |||
task.setAspects(aspects); | |||
} | |||
/* | |||
* Process a nested element within this task. All nested elements within | |||
* the task are treated as taskelements. | |||
* | |||
* @param uri The Namespace URI. | |||
* @param localName The local name (without prefix). | |||
* @param qualifiedName The qualified name (with prefix) | |||
* @param attributes The attributes attached to the element. | |||
* | |||
* @throws SAXParseException if there is a parsing problem. | |||
*/ | |||
public void startElement(String uri, String localName, String qualifiedName, | |||
Attributes attributes) throws SAXParseException { | |||
// everything within a task is a task element | |||
TaskElementHandler taskElementHandler | |||
= new TaskElementHandler(getXMLReader(), this, getLocator(), | |||
attributes, qualifiedName); | |||
task.addTaskElement(taskElementHandler.getTaskElement()); | |||
} | |||
public void characters(char[] buf, int start, int end) throws SAXParseException { | |||
task.addText(new String(buf, start, end)); | |||
} | |||
/** | |||
* Get the task that is being parsed | |||
* | |||
* @return the task being parsed by this task handler. | |||
*/ | |||
public Task getTask() { | |||
return task; | |||
} | |||
} | |||
/** | |||
* A Task Element Handler parses the nested elements of tasks. | |||
* A TaskElementHandler parses the task elements of a build | |||
*/ | |||
private class TaskElementHandler extends ElementHandler { | |||
/** | |||
@@ -839,7 +766,7 @@ public class XMLProjectParser { | |||
* @param elementTagName the name of the task element. | |||
*/ | |||
public TaskElementHandler(XMLReader xmlReader, ContentHandler parent, Locator locator, | |||
Attributes attributes, String elementTagName) { | |||
Attributes attributes, String elementTagName) { | |||
super(xmlReader, parent, locator); | |||
taskElement | |||
= new TaskElement(getLocation(locator), elementTagName); | |||
@@ -873,10 +800,10 @@ public class XMLProjectParser { | |||
public void startElement(String uri, String localName, String qualifiedName, | |||
Attributes attributes) throws SAXParseException { | |||
// everything within a task element is also a task element | |||
TaskElementHandler taskElementHandler | |||
TaskElementHandler nestedHandler | |||
= new TaskElementHandler(getXMLReader(), this, getLocator(), | |||
attributes, qualifiedName); | |||
taskElement.addTaskElement(taskElementHandler.getTaskElement()); | |||
attributes, qualifiedName); | |||
taskElement.addTaskElement(nestedHandler.getTaskElement()); | |||
} | |||
public void characters(char[] buf, int start, int end) throws SAXParseException { | |||
@@ -111,7 +111,7 @@ public class Commandline { | |||
} | |||
public void runAnt(String[] args) { | |||
ExecutionManager executionManager = null; | |||
ExecutionFrame mainFrame = null; | |||
try { | |||
parseArguments(args); | |||
Project project = getProject(); | |||
@@ -121,10 +121,16 @@ public class Commandline { | |||
// Get the list of library components | |||
AntLibrary[] libraries = ComponentManager.getComponents(); | |||
executionManager = new ExecutionManager(); | |||
executionManager.addLibraries(libraries); | |||
executionManager.setProject(project); | |||
addBuildListeners(executionManager); | |||
mainFrame = new ExecutionFrame(project, libraries); | |||
// We iterate through all nodes of all projects and make sure every node is OK | |||
Map state = new HashMap(); | |||
Stack visiting = new Stack(); | |||
List dependencyOrder = new ArrayList(); | |||
mainFrame.checkTargets(dependencyOrder, state, visiting); | |||
addBuildListeners(mainFrame); | |||
} | |||
catch (AntException e) { | |||
Location location = e.getLocation(); | |||
@@ -132,19 +138,17 @@ public class Commandline { | |||
if (location != null && location != Location.UNKNOWN_LOCATION) { | |||
System.out.print(location); | |||
} | |||
System.out.print(e.getMessage()); | |||
System.out.println(e.getMessage()); | |||
if (cause != null) { | |||
System.out.println(); | |||
System.out.print("Root cause: " + cause.getClass().getName() + ": " + cause.getMessage()); | |||
System.out.println("Root cause: " + cause.getClass().getName() + ": " + cause.getMessage()); | |||
} | |||
System.out.println(); | |||
System.exit(1); | |||
} | |||
try { | |||
executionManager.runBuild(targets); | |||
mainFrame.runBuild(targets); | |||
System.exit(0); | |||
} | |||
catch (Exception e) { | |||
@@ -152,18 +156,18 @@ public class Commandline { | |||
} | |||
} | |||
protected void addBuildListeners(ExecutionManager executionManager) | |||
protected void addBuildListeners(ExecutionFrame frame) | |||
throws ConfigException { | |||
// Add the default listener | |||
executionManager.addBuildListener(createLogger()); | |||
frame.addBuildListener(createLogger()); | |||
for (Iterator i = listeners.iterator(); i.hasNext(); ) { | |||
String className = (String) i.next(); | |||
try { | |||
BuildListener listener = | |||
(BuildListener) Class.forName(className).newInstance(); | |||
executionManager.addBuildListener(listener); | |||
frame.addBuildListener(listener); | |||
} | |||
catch(Exception exc) { | |||
throw new ConfigException("Unable to instantiate listener " + className, exc); | |||
@@ -131,13 +131,11 @@ public class DefaultLogger implements BuildLogger { | |||
if (location != null && location != Location.UNKNOWN_LOCATION) { | |||
out.print(location); | |||
} | |||
out.print(e.getMessage()); | |||
out.println(e.getMessage()); | |||
if (cause != null) { | |||
out.println(); | |||
out.print("Root cause: " + cause.getClass().getName() + ": " + cause.getMessage()); | |||
out.println("Root cause: " + cause.toString()); | |||
} | |||
out.println(); | |||
} | |||
else { | |||
t.printStackTrace(err); | |||
@@ -183,9 +181,9 @@ public class DefaultLogger implements BuildLogger { | |||
// Print out the name of the task if we're in one | |||
Object buildElement = event.getBuildElement(); | |||
if (buildElement instanceof Task) { | |||
Task task = (Task)buildElement; | |||
String name = task.getType(); | |||
if (buildElement instanceof TaskElement) { | |||
TaskElement taskElement = (TaskElement)buildElement; | |||
String name = taskElement.getType(); | |||
if (!emacsMode) { | |||
String msg = "[" + name + "] "; | |||