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"> | <antcall target="build-task"> | ||||
| <param name="taskset" value="file"/> | <param name="taskset" value="file"/> | ||||
| </antcall> | </antcall> | ||||
| <antcall target="build-task"> | |||||
| <param name="taskset" value="thread"/> | |||||
| </antcall> | |||||
| <copy todir="${build.lib}"> | <copy todir="${build.lib}"> | ||||
| <fileset dir="lib"/> | <fileset dir="lib"/> | ||||
| </copy> | </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 | * @author costin@dnt.ro | ||||
| */ | */ | ||||
| public class Echo extends ExecutionTask { | |||||
| public class Echo extends AbstractTask { | |||||
| protected String message = ""; // required | protected String message = ""; // required | ||||
| protected File file = null; | protected File file = null; | ||||
| protected boolean append = false; | protected boolean append = false; | ||||
| @@ -76,7 +76,6 @@ public class FileConverter implements AntConverter { | |||||
| try { | try { | ||||
| URL url = new URL(frame.getBaseURL(), value); | URL url = new URL(frame.getBaseURL(), value); | ||||
| if (url.getProtocol().equals("file")) { | if (url.getProtocol().equals("file")) { | ||||
| System.out.println("Converted URL to " + url); | |||||
| return new File(url.getFile()); | return new File(url.getFile()); | ||||
| } | } | ||||
| return new File(value); | 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 name; | ||||
| private String value; | private String value; | ||||
| private URL file; | private URL file; | ||||
| @@ -144,9 +144,8 @@ public class Property extends ExecutionTask { | |||||
| // | // | ||||
| public void execute() throws ExecutionException { | public void execute() throws ExecutionException { | ||||
| ExecutionFrame frame = getExecutionFrame(); | |||||
| if ((name != null) && (value != null)) { | if ((name != null) && (value != null)) { | ||||
| frame.setDataValue(name, value); | |||||
| getTaskContext().setDataValue(name, value); | |||||
| } | } | ||||
| if (file != null) { | if (file != null) { | ||||
| @@ -199,11 +198,11 @@ public class Property extends ExecutionTask { | |||||
| } | } | ||||
| protected void addProperties(Properties properties) throws ExecutionException { | protected void addProperties(Properties properties) throws ExecutionException { | ||||
| ExecutionFrame frame = getExecutionFrame(); | |||||
| for (Iterator i = properties.keySet().iterator(); i.hasNext();) { | for (Iterator i = properties.keySet().iterator(); i.hasNext();) { | ||||
| String propertyName = (String)i.next(); | String propertyName = (String)i.next(); | ||||
| String propertyValue = properties.getProperty(propertyName); | String propertyValue = properties.getProperty(propertyName); | ||||
| frame.setDataValue(propertyName, frame.replacePropertyRefs(propertyValue)); | |||||
| getTaskContext().setDataValue(propertyName, | |||||
| getTaskContext().replacePropertyRefs(propertyValue)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,8 +1,17 @@ | |||||
| <antlib> | <antlib> | ||||
| <!-- Tasks --> | |||||
| <taskdef name="property" classname="org.apache.ant.component.core.Property"/> | <taskdef name="property" classname="org.apache.ant.component.core.Property"/> | ||||
| <taskdef name="echo" classname="org.apache.ant.component.core.Echo"/> | <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.io.File" classname="org.apache.ant.component.core.FileConverter"/> | ||||
| <converter target="java.net.URL" classname="org.apache.ant.component.core.URLConverter"/> | <converter target="java.net.URL" classname="org.apache.ant.component.core.URLConverter"/> | ||||
| <converter target="org.apache.ant.core.types.EnumeratedAttribute" | <converter target="org.apache.ant.core.types.EnumeratedAttribute" | ||||
| classname="org.apache.ant.component.core.EnumeratedAttributeConverter"/> | classname="org.apache.ant.component.core.EnumeratedAttributeConverter"/> | ||||
| <!-- Aspect Handlers --> | |||||
| <aspect prefix="ant" classname="org.apache.ant.component.core.AntAspectHandler"/> | |||||
| </antlib> | </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; | package org.apache.ant.core.execution; | ||||
| import org.apache.ant.core.support.*; | |||||
| import java.util.*; | import java.util.*; | ||||
| import java.net.URL; | import java.net.URL; | ||||
| @@ -68,35 +69,51 @@ public class AntLibrary { | |||||
| /** | /** | ||||
| * The task definitions contained by this library | * The task definitions contained by this library | ||||
| */ | */ | ||||
| private List taskDefinitions = new ArrayList(); | |||||
| private Map taskDefinitions = new HashMap(); | |||||
| /** | /** | ||||
| * The converter definitions contained by this library | * 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 | * Add a task definition to this library | ||||
| */ | */ | ||||
| public void addTaskDefinition(TaskDefinition taskDefinition) { | 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 | * Get the task definitions | ||||
| * | * | ||||
| * @return an iterator which returns TaskDefinition objects. | * @return an iterator which returns TaskDefinition objects. | ||||
| */ | */ | ||||
| public Iterator getTaskDefinitions() { | 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 | * Get the converter definitions | ||||
| @@ -104,7 +121,17 @@ public class AntLibrary { | |||||
| * @return an iterator which returns ConverterDefinition objects. | * @return an iterator which returns ConverterDefinition objects. | ||||
| */ | */ | ||||
| public Iterator getConverterDefinitions() { | 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. | * @param cause Exception that might have caused this one. | ||||
| */ | */ | ||||
| public ClassIntrospectionException(Throwable cause) { | public ClassIntrospectionException(Throwable cause) { | ||||
| super(cause.toString()); | |||||
| super(cause.getMessage()); | |||||
| this.cause = cause; | this.cause = cause; | ||||
| } | } | ||||
| @@ -124,7 +124,7 @@ public class ConverterDefinition { | |||||
| */ | */ | ||||
| public synchronized Class getConverterClass() throws ClassNotFoundException { | public synchronized Class getConverterClass() throws ClassNotFoundException { | ||||
| if (converterClass == null) { | if (converterClass == null) { | ||||
| converterClass = converterClassLoader.loadClass(converterClassName); | |||||
| converterClass = Class.forName(converterClassName, true, converterClassLoader); | |||||
| } | } | ||||
| return converterClass; | return converterClass; | ||||
| } | } | ||||
| @@ -136,7 +136,7 @@ public class ConverterDefinition { | |||||
| */ | */ | ||||
| public synchronized Class getTargetClass() throws ClassNotFoundException { | public synchronized Class getTargetClass() throws ClassNotFoundException { | ||||
| if (targetClass == null) { | if (targetClass == null) { | ||||
| targetClass = converterClassLoader.loadClass(targetClassName); | |||||
| targetClass = Class.forName(targetClassName, true, converterClassLoader); | |||||
| } | } | ||||
| return targetClass; | return targetClass; | ||||
| } | } | ||||
| @@ -60,60 +60,22 @@ import java.util.*; | |||||
| import java.net.URL; | 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> | * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | ||||
| */ | */ | ||||
| public abstract class ExecutionTask { | |||||
| public class ExecutionContext { | |||||
| private ExecutionFrame frame = null; | private ExecutionFrame frame = null; | ||||
| private Location location = Location.UNKNOWN_LOCATION; | |||||
| private BuildEventSupport eventSupport; | private BuildEventSupport eventSupport; | ||||
| private BuildElement buildElement; | private BuildElement buildElement; | ||||
| void setExecutionFrame(ExecutionFrame frame) { | |||||
| public ExecutionContext(ExecutionFrame frame, BuildEventSupport eventSupport, | |||||
| BuildElement buildElement) { | |||||
| this.frame = frame; | 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; | this.eventSupport = eventSupport; | ||||
| } | |||||
| /** | |||||
| * Associate this ExecutionTask with a buildElement in the | |||||
| * project model | |||||
| */ | |||||
| void setBuildElement(BuildElement buildElement) { | |||||
| this.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. | * Log a mesage with the give priority. | ||||
| @@ -125,26 +87,22 @@ public abstract class ExecutionTask { | |||||
| eventSupport.fireMessageLogged(this, buildElement, msg, msgLevel); | 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.model.*; | ||||
| import org.apache.ant.core.support.*; | import org.apache.ant.core.support.*; | ||||
| import org.apache.ant.core.types.*; | |||||
| import java.util.*; | import java.util.*; | ||||
| import java.net.*; | import java.net.*; | ||||
| @@ -67,6 +68,13 @@ import java.net.*; | |||||
| * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | ||||
| */ | */ | ||||
| public class ExecutionFrame { | 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 */ | /** The Project that this execiton frame is processing */ | ||||
| private Project project = null; | private Project project = null; | ||||
| @@ -74,9 +82,6 @@ public class ExecutionFrame { | |||||
| Project's source URL and it's base attribute. */ | Project's source URL and it's base attribute. */ | ||||
| private URL baseURL = null; | 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 | /** The imported frames of this frame. For each project imported by this frame's | ||||
| project, a corresponding ExecutionFrame is created. */ | project, a corresponding ExecutionFrame is created. */ | ||||
| private Map importedFrames = new HashMap(); | private Map importedFrames = new HashMap(); | ||||
| @@ -88,22 +93,79 @@ public class ExecutionFrame { | |||||
| created by tasks that have been executed */ | created by tasks that have been executed */ | ||||
| private Map dataValues = new HashMap(); | 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(); | 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 | /** Type converters for this executionFrame. Converters are used when configuring | ||||
| Tasks to handle special type conversions. */ | Tasks to handle special type conversions. */ | ||||
| private Map converters = new HashMap(); | 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 | /** The namespace under which this execution frame lives in the hierarchical | ||||
| project namespace - null for the root namespace */ | project namespace - null for the root namespace */ | ||||
| private String 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; | 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 { | try { | ||||
| String base = project.getBase(); | String base = project.getBase(); | ||||
| @@ -123,74 +185,149 @@ public class ExecutionFrame { | |||||
| + "\" is not valid", e, project.getLocation()); | + "\" 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();) { | for (Iterator i = project.getImportedProjectNames(); i.hasNext();) { | ||||
| String importName = (String)i.next(); | String importName = (String)i.next(); | ||||
| Project importedProject = project.getImportedProject(importName); | Project importedProject = project.getImportedProject(importName); | ||||
| String importNamespace | String importNamespace | ||||
| = namespace == null ? importName : namespace + ":" + importName; | = namespace == null ? importName : namespace + ":" + importName; | ||||
| ExecutionFrame importedFrame | ExecutionFrame importedFrame | ||||
| = new ExecutionFrame(importedProject, taskDefs, converterDefs, importNamespace); | |||||
| = new ExecutionFrame(importedProject, libraries, importNamespace); | |||||
| importedFrames.put(importName, importedFrame); | 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() | + 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) { | public void addBuildListener(BuildListener listener) { | ||||
| for (Iterator i = getImportedFrames(); i.hasNext(); ) { | |||||
| ExecutionFrame subFrame = (ExecutionFrame)i.next(); | |||||
| subFrame.addBuildListener(listener); | |||||
| } | |||||
| eventSupport.addBuildListener(listener); | eventSupport.addBuildListener(listener); | ||||
| } | } | ||||
| public void removeBuildListener(BuildListener listener) { | public void removeBuildListener(BuildListener listener) { | ||||
| for (Iterator i = getImportedFrames(); i.hasNext(); ) { | |||||
| ExecutionFrame subFrame = (ExecutionFrame)i.next(); | |||||
| subFrame.removeBuildListener(listener); | |||||
| } | |||||
| eventSupport.removeBuildListener(listener); | eventSupport.removeBuildListener(listener); | ||||
| } | } | ||||
| @@ -257,26 +394,6 @@ public class ExecutionFrame { | |||||
| return namespace == null ? name : namespace + ":" + name; | 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 | * 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(); | Iterator taskIterator = project.getTasks(); | ||||
| executeTasks(taskIterator); | 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 { | throws ConfigException, ExecutionException { | ||||
| String taskType = model.getType(); | String taskType = model.getType(); | ||||
| TaskDefinition taskDefinition = (TaskDefinition)taskDefs.get(taskType); | TaskDefinition taskDefinition = (TaskDefinition)taskDefs.get(taskType); | ||||
| if (taskDefinition == null) { | 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()); | + taskType + ">", model.getLocation()); | ||||
| } | } | ||||
| try { | 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) { | catch (ClassNotFoundException e) { | ||||
| throw new ConfigException("Execution class " + taskDefinition.getTaskClassName() | throw new ConfigException("Execution class " + taskDefinition.getTaskClassName() | ||||
| @@ -339,43 +564,51 @@ public class ExecutionFrame { | |||||
| e, model.getLocation()); | 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 { | 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) | private void configureElement(Object element, TaskElement model) | ||||
| throws ExecutionException, ConfigException { | throws ExecutionException, ConfigException { | ||||
| @@ -401,11 +634,9 @@ public class ExecutionFrame { | |||||
| if (element instanceof TaskContainer && | if (element instanceof TaskContainer && | ||||
| !introspector.supportsNestedElement(nestedElementModel.getType())) { | !introspector.supportsNestedElement(nestedElementModel.getType())) { | ||||
| ExecutionTask nestedExecutionTask | |||||
| = getConfiguredExecutionTask(nestedElementModel); | |||||
| Task nestedTask = configureTask(nestedElementModel); | |||||
| TaskContainer container = (TaskContainer)element; | TaskContainer container = (TaskContainer)element; | ||||
| container.addExecutionTask(nestedExecutionTask); | |||||
| container.addTask(nestedTask); | |||||
| } | } | ||||
| else { | else { | ||||
| Object nestedElement | Object nestedElement | ||||
| @@ -413,6 +644,11 @@ public class ExecutionFrame { | |||||
| configureElement(nestedElement, nestedElementModel); | 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) { | catch (ClassIntrospectionException e) { | ||||
| throw new ExecutionException(e, model.getLocation()); | 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) { | private ClassIntrospector getIntrospector(Class c) { | ||||
| if (introspectors.containsKey(c)) { | if (introspectors.containsKey(c)) { | ||||
| return (ClassIntrospector)introspectors.get(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 | * Given a name of an object, get the frame relative from this frame that | ||||
| * contains that object. | * contains that object. | ||||
| */ | */ | ||||
| private ExecutionFrame getRelativeFrame(String name) throws ExecutionException { | |||||
| public ExecutionFrame getRelativeFrame(String name) throws ExecutionException { | |||||
| int index = name.lastIndexOf(":"); | int index = name.lastIndexOf(":"); | ||||
| if (index == -1) { | if (index == -1) { | ||||
| return this; | return this; | ||||
| @@ -534,7 +806,7 @@ public class ExecutionFrame { | |||||
| /** | /** | ||||
| * Get the name of an object in its frame | * Get the name of an object in its frame | ||||
| */ | */ | ||||
| private String getNameInFrame(String name) { | |||||
| public String getNameInFrame(String name) { | |||||
| int index = name.lastIndexOf(":"); | int index = name.lastIndexOf(":"); | ||||
| if (index == -1) { | if (index == -1) { | ||||
| return name; | return name; | ||||
| @@ -553,7 +825,7 @@ public class ExecutionFrame { | |||||
| /** | /** | ||||
| * Get a value from this frame or any imported frame | * 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); | ExecutionFrame frame = getRelativeFrame(name); | ||||
| return frame.getDirectDataValue(getNameInFrame(name)); | return frame.getDirectDataValue(getNameInFrame(name)); | ||||
| } | } | ||||
| @@ -586,5 +858,55 @@ public class ExecutionFrame { | |||||
| private boolean isDirectDataValueSet(String name) { | private boolean isDirectDataValueSet(String name) { | ||||
| return dataValues.containsKey(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 | * information on the Apache Software Foundation, please see | ||||
| * <http://www.apache.org/>. | * <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 org.apache.ant.core.support.*; | ||||
| import java.util.*; | 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> | * @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. | * 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 { | public synchronized Class getExecutionTaskClass() throws ClassNotFoundException { | ||||
| if (taskClass == null) { | if (taskClass == null) { | ||||
| taskClass = taskClassLoader.loadClass(taskClassName); | |||||
| taskClass = Class.forName(taskClassName, true, taskClassLoader); | |||||
| } | } | ||||
| return taskClass; | return taskClass; | ||||
| } | } | ||||
| @@ -63,20 +63,13 @@ import org.apache.ant.core.support.*; | |||||
| * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | ||||
| */ | */ | ||||
| public class BuildElement { | 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; | private Location location; | ||||
| /** | |||||
| * A comment associated with this element, if any | |||||
| * | |||||
| */ | |||||
| /** A comment associated with this element, if any */ | |||||
| private String comment; | private String comment; | ||||
| /** | /** | ||||
| @@ -121,7 +114,44 @@ public class BuildElement { | |||||
| * @param aspects a Map of apects that relate to this build element. | * @param aspects a Map of apects that relate to this build element. | ||||
| */ | */ | ||||
| public void setAspects(Map aspects) { | 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 | * @param task a task to be executed when an execution context | ||||
| * is associated with the Project (a non-target task) | * is associated with the Project (a non-target task) | ||||
| */ | */ | ||||
| public void addTask(Task task) { | |||||
| public void addTask(TaskElement task) { | |||||
| tasks.add(task); | tasks.add(task); | ||||
| } | } | ||||
| @@ -100,7 +100,7 @@ public class Target extends BuildElement { | |||||
| * | * | ||||
| * @param task the task to be added to the target. | * @param task the task to be added to the target. | ||||
| */ | */ | ||||
| public void addTask(Task task) { | |||||
| public void addTask(TaskElement task) { | |||||
| tasks.add(task); | tasks.add(task); | ||||
| } | } | ||||
| @@ -59,14 +59,17 @@ import java.net.*; | |||||
| import java.io.*; | 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 | * 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. | * loader only if the class does not exist in the URLs. | ||||
| * | * | ||||
| * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | ||||
| */ | */ | ||||
| public class AntClassLoader extends URLClassLoader { | public class AntClassLoader extends URLClassLoader { | ||||
| /** A Debug label to print when the Classloader finds or fails to find a class. */ | |||||
| private String debugLabel = null; | private String debugLabel = null; | ||||
| /** A flag whihc controls whether messages are logged by the loader */ | |||||
| private boolean debug = false; | private boolean debug = false; | ||||
| private void dumpURLs() { | private void dumpURLs() { | ||||
| @@ -110,7 +110,7 @@ public abstract class AntException extends Exception { | |||||
| * @param cause Exception that might have caused this one. | * @param cause Exception that might have caused this one. | ||||
| */ | */ | ||||
| public AntException(Throwable cause) { | public AntException(Throwable cause) { | ||||
| super(cause.toString()); | |||||
| super(cause.getMessage()); | |||||
| this.cause = cause; | 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 class AntLibParser { | ||||
| public static final String TASK_ELEMENT = "taskdef"; | public static final String TASK_ELEMENT = "taskdef"; | ||||
| public static final String CONVERTER_ELEMENT = "converter"; | public static final String CONVERTER_ELEMENT = "converter"; | ||||
| public static final String ASPECT_ELEMENT = "aspect"; | |||||
| /** | /** | ||||
| * The factory used to create SAX parsers. | * The factory used to create SAX parsers. | ||||
| @@ -191,6 +192,9 @@ public class AntLibParser { | |||||
| else if (qualifiedName.equals(CONVERTER_ELEMENT)) { | else if (qualifiedName.equals(CONVERTER_ELEMENT)) { | ||||
| createConverterDef(attributes); | createConverterDef(attributes); | ||||
| } | } | ||||
| else if (qualifiedName.equals(ASPECT_ELEMENT)) { | |||||
| createAspectHandler(attributes); | |||||
| } | |||||
| else { | else { | ||||
| throw new SAXParseException("Unrecognized element <" + | throw new SAXParseException("Unrecognized element <" + | ||||
| qualifiedName + "> in Ant library definition", getLocator()); | qualifiedName + "> in Ant library definition", getLocator()); | ||||
| @@ -219,7 +223,6 @@ public class AntLibParser { | |||||
| "<" + TASK_ELEMENT + "> element", getLocator()); | "<" + TASK_ELEMENT + "> element", getLocator()); | ||||
| } | } | ||||
| System.out.println("Adding taskdef for " + taskName); | |||||
| TaskDefinition taskdef = new TaskDefinition(getSourceURL(), taskName, className, componentLoader); | TaskDefinition taskdef = new TaskDefinition(getSourceURL(), taskName, className, componentLoader); | ||||
| library.addTaskDefinition(taskdef); | library.addTaskDefinition(taskdef); | ||||
| } | } | ||||
| @@ -229,7 +232,7 @@ public class AntLibParser { | |||||
| validAttributes.add("target"); | validAttributes.add("target"); | ||||
| validAttributes.add("classname"); | validAttributes.add("classname"); | ||||
| Map attributeValues | Map attributeValues | ||||
| = AttributeValidator.validateAttributes("convert", attributes, | |||||
| = AttributeValidator.validateAttributes(CONVERTER_ELEMENT, attributes, | |||||
| validAttributes, getLocator()); | validAttributes, getLocator()); | ||||
| String targetClassName = (String)attributeValues.get("target"); | String targetClassName = (String)attributeValues.get("target"); | ||||
| String className = (String)attributeValues.get("classname"); | String className = (String)attributeValues.get("classname"); | ||||
| @@ -248,6 +251,30 @@ public class AntLibParser { | |||||
| library.addConverterDefinition(converterDef); | 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) { | public void endElement(String namespaceURI, String localName, String qName) { | ||||
| if (state == STATE_ROOT_SEEN && qName.equals("antlib")) { | if (state == STATE_ROOT_SEEN && qName.equals("antlib")) { | ||||
| state = STATE_FINISHED; | state = STATE_FINISHED; | ||||
| @@ -373,10 +373,10 @@ public class XMLProjectParser { | |||||
| } | } | ||||
| else { | else { | ||||
| // everything else is a task | // everything else is a task | ||||
| TaskHandler taskHandler | |||||
| = new TaskHandler(getXMLReader(), this, getLocator(), | |||||
| TaskElementHandler taskElementHandler | |||||
| = new TaskElementHandler(getXMLReader(), this, getLocator(), | |||||
| attributes, qualifiedName); | 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, | public void startElement(String uri, String localName, String qualifiedName, | ||||
| Attributes attributes) throws SAXParseException { | Attributes attributes) throws SAXParseException { | ||||
| // everything is a task | // 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 { | private class TaskElementHandler extends ElementHandler { | ||||
| /** | /** | ||||
| @@ -839,7 +766,7 @@ public class XMLProjectParser { | |||||
| * @param elementTagName the name of the task element. | * @param elementTagName the name of the task element. | ||||
| */ | */ | ||||
| public TaskElementHandler(XMLReader xmlReader, ContentHandler parent, Locator locator, | public TaskElementHandler(XMLReader xmlReader, ContentHandler parent, Locator locator, | ||||
| Attributes attributes, String elementTagName) { | |||||
| Attributes attributes, String elementTagName) { | |||||
| super(xmlReader, parent, locator); | super(xmlReader, parent, locator); | ||||
| taskElement | taskElement | ||||
| = new TaskElement(getLocation(locator), elementTagName); | = new TaskElement(getLocation(locator), elementTagName); | ||||
| @@ -873,10 +800,10 @@ public class XMLProjectParser { | |||||
| public void startElement(String uri, String localName, String qualifiedName, | public void startElement(String uri, String localName, String qualifiedName, | ||||
| Attributes attributes) throws SAXParseException { | Attributes attributes) throws SAXParseException { | ||||
| // everything within a task element is also a task element | // everything within a task element is also a task element | ||||
| TaskElementHandler taskElementHandler | |||||
| TaskElementHandler nestedHandler | |||||
| = new TaskElementHandler(getXMLReader(), this, getLocator(), | = 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 { | public void characters(char[] buf, int start, int end) throws SAXParseException { | ||||
| @@ -111,7 +111,7 @@ public class Commandline { | |||||
| } | } | ||||
| public void runAnt(String[] args) { | public void runAnt(String[] args) { | ||||
| ExecutionManager executionManager = null; | |||||
| ExecutionFrame mainFrame = null; | |||||
| try { | try { | ||||
| parseArguments(args); | parseArguments(args); | ||||
| Project project = getProject(); | Project project = getProject(); | ||||
| @@ -121,10 +121,16 @@ public class Commandline { | |||||
| // Get the list of library components | // Get the list of library components | ||||
| AntLibrary[] libraries = ComponentManager.getComponents(); | 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) { | catch (AntException e) { | ||||
| Location location = e.getLocation(); | Location location = e.getLocation(); | ||||
| @@ -132,19 +138,17 @@ public class Commandline { | |||||
| if (location != null && location != Location.UNKNOWN_LOCATION) { | if (location != null && location != Location.UNKNOWN_LOCATION) { | ||||
| System.out.print(location); | System.out.print(location); | ||||
| } | } | ||||
| System.out.print(e.getMessage()); | |||||
| System.out.println(e.getMessage()); | |||||
| if (cause != null) { | 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); | System.exit(1); | ||||
| } | } | ||||
| try { | try { | ||||
| executionManager.runBuild(targets); | |||||
| mainFrame.runBuild(targets); | |||||
| System.exit(0); | System.exit(0); | ||||
| } | } | ||||
| catch (Exception e) { | catch (Exception e) { | ||||
| @@ -152,18 +156,18 @@ public class Commandline { | |||||
| } | } | ||||
| } | } | ||||
| protected void addBuildListeners(ExecutionManager executionManager) | |||||
| protected void addBuildListeners(ExecutionFrame frame) | |||||
| throws ConfigException { | throws ConfigException { | ||||
| // Add the default listener | // Add the default listener | ||||
| executionManager.addBuildListener(createLogger()); | |||||
| frame.addBuildListener(createLogger()); | |||||
| for (Iterator i = listeners.iterator(); i.hasNext(); ) { | for (Iterator i = listeners.iterator(); i.hasNext(); ) { | ||||
| String className = (String) i.next(); | String className = (String) i.next(); | ||||
| try { | try { | ||||
| BuildListener listener = | BuildListener listener = | ||||
| (BuildListener) Class.forName(className).newInstance(); | (BuildListener) Class.forName(className).newInstance(); | ||||
| executionManager.addBuildListener(listener); | |||||
| frame.addBuildListener(listener); | |||||
| } | } | ||||
| catch(Exception exc) { | catch(Exception exc) { | ||||
| throw new ConfigException("Unable to instantiate listener " + className, 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) { | if (location != null && location != Location.UNKNOWN_LOCATION) { | ||||
| out.print(location); | out.print(location); | ||||
| } | } | ||||
| out.print(e.getMessage()); | |||||
| out.println(e.getMessage()); | |||||
| if (cause != null) { | if (cause != null) { | ||||
| out.println(); | |||||
| out.print("Root cause: " + cause.getClass().getName() + ": " + cause.getMessage()); | |||||
| out.println("Root cause: " + cause.toString()); | |||||
| } | } | ||||
| out.println(); | |||||
| } | } | ||||
| else { | else { | ||||
| t.printStackTrace(err); | t.printStackTrace(err); | ||||
| @@ -183,9 +181,9 @@ public class DefaultLogger implements BuildLogger { | |||||
| // Print out the name of the task if we're in one | // Print out the name of the task if we're in one | ||||
| Object buildElement = event.getBuildElement(); | 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) { | if (!emacsMode) { | ||||
| String msg = "[" + name + "] "; | String msg = "[" + name + "] "; | ||||