git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271453 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -25,4 +25,4 @@ java -classpath bin/init:bin/bootstrap org.apache.ant.bootstrap.Bootstrap | |||
| java -classpath bootstrap/lib/start.jar:bootstrap/lib/init.jar org.apache.ant.start.Main $* | |||
| # Use the full build as the build used by the build script | |||
| cp -r dist/* bootstrap | |||
| cp -r dist/lib bootstrap | |||
| @@ -1,6 +1,6 @@ | |||
| #!/bin/sh | |||
| #!/bin/sh -x | |||
| # Copyright (c) 2000-2001 The Apache Software Foundation. All rights | |||
| # reserved. | |||
| java -classpath bootstrap/lib/start.jar:bootstrap/lib/init.jar org.apache.ant.start.Main $* | |||
| java -classpath bootstrap/lib/start.jar:bootstrap/lib/init.jar org.apache.ant.start.Main $@ | |||
| @@ -28,8 +28,8 @@ | |||
| <exclude name="org/apache/tools/ant/taskdefs/RecorderEntry.java"/> | |||
| <exclude name="org/apache/tools/ant/taskdefs/optional/Native2Ascii.java"/> | |||
| <exclude name="org/apache/tools/ant/taskdefs/optional/Javah.java"/> | |||
| <exclude name="org/apache/tools/ant/taskdefs/Parallel.java"/> | |||
| <exclude name="org/apache/tools/ant/taskdefs/Sequential.java"/> | |||
| <!-- <exclude name="org/apache/tools/ant/taskdefs/Parallel.java"/> --> | |||
| <!-- <exclude name="org/apache/tools/ant/taskdefs/Sequential.java"/> --> | |||
| <exclude name="org/apache/tools/ant/taskdefs/optional/jdepend/*.java"/> | |||
| </patternset> | |||
| @@ -1,49 +0,0 @@ | |||
| <project name="build-site" default="docs" basedir="."> | |||
| <!-- Initialization properties --> | |||
| <property name="project.name" value="mutant"/> | |||
| <property name="docs.src" location="xdocs"/> | |||
| <property name="docs.dest" location="docs"/> | |||
| <property name="project.file" value="stylesheets/project.xml" /> | |||
| <property name="site.dir" location="../../../jakarta-site2" /> | |||
| <property name="templ.path" location="xdocs/stylesheets" /> | |||
| <property name="velocity.props" location="${docs.src}/velocity.properties" /> | |||
| <path id="anakia.classpath"> | |||
| <fileset dir="${site.dir}/lib"> | |||
| <include name="*.jar"/> | |||
| </fileset> | |||
| </path> | |||
| <target name="prepare"> | |||
| <available classname="org.apache.velocity.anakia.AnakiaTask" | |||
| property="AnakiaTask.present"> | |||
| <classpath refid="anakia.classpath"/> | |||
| </available> | |||
| </target> | |||
| <target depends="prepare" name="prepare-error" unless="AnakiaTask.present"> | |||
| <echo> | |||
| AnakiaTask is not present! Please check to make sure that | |||
| velocity.jar is in your classpath. | |||
| </echo> | |||
| </target> | |||
| <target name="docs" depends="prepare-error" if="AnakiaTask.present"> | |||
| <taskdef name="anakia" classname="org.apache.velocity.anakia.AnakiaTask"> | |||
| <classpath refid="anakia.classpath"/> | |||
| </taskdef> | |||
| <anakia basedir="${docs.src}" destdir="${docs.dest}/" | |||
| extension=".html" style="./site.vsl" | |||
| projectFile="${project.file}" | |||
| excludes="**/stylesheets/** faq.xml" | |||
| includes="**/*.xml" | |||
| lastModifiedCheck="true" | |||
| templatePath="${templ.path}" | |||
| velocityPropertiesFile="${velocity.props}"> | |||
| </anakia> | |||
| </target> | |||
| <target name="all" depends="docs"/> | |||
| </project> | |||
| @@ -59,6 +59,7 @@ import java.util.List; | |||
| import org.apache.ant.common.model.ModelElement; | |||
| import org.apache.ant.common.event.BuildListener; | |||
| import org.apache.ant.common.event.BuildEvent; | |||
| import org.apache.ant.common.antlib.Task; | |||
| /** | |||
| * BuildEventSupport is used by classes which which to send build events to | |||
| @@ -162,10 +163,10 @@ public class BuildEventSupport { | |||
| /** | |||
| * fire a task started event | |||
| * | |||
| * @param element the build element with which the event is associated | |||
| * @param task the task with which the event is associated | |||
| */ | |||
| public void fireTaskStarted(ModelElement element) { | |||
| BuildEvent event = new BuildEvent(element, BuildEvent.TASK_STARTED); | |||
| public void fireTaskStarted(Task task) { | |||
| BuildEvent event = new BuildEvent(task, BuildEvent.TASK_STARTED); | |||
| for (Iterator i = listeners.iterator(); i.hasNext(); ) { | |||
| BuildListener listener = (BuildListener)i.next(); | |||
| listener.taskStarted(event); | |||
| @@ -175,12 +176,12 @@ public class BuildEventSupport { | |||
| /** | |||
| * fire a task finished event | |||
| * | |||
| * @param element the build element with which the event is associated | |||
| * @param task the task with which the event is associated | |||
| * @param cause an exception if there was a failure in the task | |||
| */ | |||
| public void fireTaskFinished(ModelElement element, | |||
| public void fireTaskFinished(Task task, | |||
| Throwable cause) { | |||
| BuildEvent event = new BuildEvent(element, BuildEvent.TASK_FINISHED, | |||
| BuildEvent event = new BuildEvent(task, BuildEvent.TASK_FINISHED, | |||
| cause); | |||
| for (Iterator i = listeners.iterator(); i.hasNext(); ) { | |||
| BuildListener listener = (BuildListener)i.next(); | |||
| @@ -68,10 +68,17 @@ import org.apache.ant.antcore.antlib.ComponentLibrary; | |||
| import org.apache.ant.antcore.antlib.DynamicLibrary; | |||
| import org.apache.ant.common.antlib.AntLibFactory; | |||
| import org.apache.ant.common.antlib.Converter; | |||
| import org.apache.ant.common.antlib.DeferredTask; | |||
| import org.apache.ant.common.antlib.ExecutionComponent; | |||
| import org.apache.ant.common.antlib.StandardLibFactory; | |||
| import org.apache.ant.common.antlib.Task; | |||
| import org.apache.ant.common.antlib.TaskContainer; | |||
| import org.apache.ant.common.event.MessageLevel; | |||
| import org.apache.ant.common.model.BuildElement; | |||
| import org.apache.ant.common.service.ComponentService; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| import org.apache.ant.common.util.Location; | |||
| import org.apache.ant.init.LoaderUtils; | |||
| /** | |||
| * The instance of the ComponentServices made available by the core to the | |||
| @@ -81,9 +88,6 @@ import org.apache.ant.common.util.ExecutionException; | |||
| * @created 27 January 2002 | |||
| */ | |||
| public class ComponentManager implements ComponentService { | |||
| /** The prefix for library ids that are automatically imported */ | |||
| public static final String ANT_LIB_PREFIX = "ant."; | |||
| /** | |||
| * Type converters for this frame. Converters are used when configuring | |||
| * Tasks to handle special type conversions. | |||
| @@ -120,6 +124,10 @@ public class ComponentManager implements ComponentService { | |||
| */ | |||
| private Map libPathsMap; | |||
| /** Reflector objects used to configure Tasks from the Task models. */ | |||
| private Map setters = new HashMap(); | |||
| /** | |||
| * Constructor | |||
| * | |||
| @@ -279,26 +287,41 @@ public class ComponentManager implements ComponentService { | |||
| */ | |||
| public void importFrameComponent(String relativeName, String alias) | |||
| throws ExecutionException { | |||
| ImportInfo definition | |||
| = frame.getReferencedDefinition(relativeName); | |||
| ImportInfo definition | |||
| = frame.getReferencedDefinition(relativeName); | |||
| if (definition == null) { | |||
| throw new ExecutionException("The reference \"relativeName\" does" | |||
| + " not refer to a defined component"); | |||
| throw new ExecutionException("The reference \"relativeName\" does" | |||
| + " not refer to a defined component"); | |||
| } | |||
| String label = alias; | |||
| if (label == null) { | |||
| label = frame.getNameInFrame(relativeName); | |||
| } | |||
| frame.log("Adding referenced component <" + definition.getLocalName() | |||
| + "> as <" + label + "> from library \"" | |||
| frame.log("Adding referenced component <" + definition.getLocalName() | |||
| + "> as <" + label + "> from library \"" | |||
| + definition.getComponentLibrary().getLibraryId() + "\", class: " | |||
| + definition.getClassName(), MessageLevel.MSG_DEBUG); | |||
| definitions.put(label, definition); | |||
| } | |||
| /** | |||
| * Create a component. The component will have a context but will not be | |||
| * configured. It should be configured using the appropriate set methods | |||
| * and then validated before being used. | |||
| * | |||
| * @param componentName the name of the component | |||
| * @return the created component. The return type of this method depends | |||
| * on the component type. | |||
| * @exception ExecutionException if the component cannot be created | |||
| */ | |||
| public Object createComponent(String componentName) | |||
| throws ExecutionException { | |||
| return createComponent(componentName, null); | |||
| } | |||
| /** | |||
| * Set the standard libraries (i.e. those which are independent of the | |||
| * build files) to be used in this component manager | |||
| @@ -316,7 +339,7 @@ public class ComponentManager implements ComponentService { | |||
| // go through the libraries and import all standard ant libraries | |||
| for (Iterator i = antLibraries.keySet().iterator(); i.hasNext(); ) { | |||
| String libraryId = (String)i.next(); | |||
| if (libraryId.startsWith(ANT_LIB_PREFIX)) { | |||
| if (libraryId.startsWith(Constants.ANT_LIB_PREFIX)) { | |||
| // standard library - import whole library | |||
| importLibrary(libraryId); | |||
| } | |||
| @@ -348,8 +371,9 @@ public class ComponentManager implements ComponentService { | |||
| if (libFactories.containsKey(libraryId)) { | |||
| return (AntLibFactory)libFactories.get(libraryId); | |||
| } | |||
| AntLibFactory libFactory | |||
| = componentLibrary.getFactory(new ExecutionContext(frame)); | |||
| ExecutionContext context | |||
| = new ExecutionContext(frame, null, Location.UNKNOWN_LOCATION); | |||
| AntLibFactory libFactory = componentLibrary.getFactory(context); | |||
| if (libFactory == null) { | |||
| libFactory = new StandardLibFactory(); | |||
| } | |||
| @@ -368,6 +392,109 @@ public class ComponentManager implements ComponentService { | |||
| return (ImportInfo)definitions.get(name); | |||
| } | |||
| /** | |||
| * Create a component from a build model | |||
| * | |||
| * @param model the build model representing the component and its | |||
| * configuration | |||
| * @return the configured component | |||
| * @exception ExecutionException if there is a problem creating or | |||
| * configuring the component | |||
| */ | |||
| protected Object createComponent(BuildElement model) | |||
| throws ExecutionException { | |||
| String componentName = model.getType(); | |||
| return createComponent(componentName, model); | |||
| } | |||
| /** | |||
| * Create a component. | |||
| * | |||
| * @param componentName the name of the component which is used to | |||
| * select the object type to be created | |||
| * @param model the build model of the component. If this is null, the | |||
| * component is created but not configured. | |||
| * @return the configured component | |||
| * @exception ExecutionException if there is a problem creating or | |||
| * configuring the component | |||
| */ | |||
| protected Object createComponent(String componentName, BuildElement model) | |||
| throws ExecutionException { | |||
| ImportInfo definition = getDefinition(componentName); | |||
| String className = definition.getClassName(); | |||
| ComponentLibrary componentLibrary | |||
| = definition.getComponentLibrary(); | |||
| String localName = definition.getLocalName(); | |||
| try { | |||
| ClassLoader componentLoader = componentLibrary.getClassLoader(); | |||
| Class componentClass | |||
| = Class.forName(className, true, componentLoader); | |||
| AntLibFactory libFactory = getLibFactory(componentLibrary); | |||
| Location location = Location.UNKNOWN_LOCATION; | |||
| if (model != null) { | |||
| location = model.getLocation(); | |||
| } | |||
| Object component | |||
| = libFactory.createComponent(componentClass, localName); | |||
| ExecutionComponent execComponent = null; | |||
| if (definition.getDefinitionType() == AntLibrary.TASKDEF) { | |||
| if (component instanceof Task) { | |||
| execComponent = (Task)component; | |||
| } else { | |||
| execComponent = new TaskAdapter(componentName, component); | |||
| } | |||
| } else if (component instanceof ExecutionComponent) { | |||
| execComponent = (ExecutionComponent)component; | |||
| } | |||
| ExecutionContext context | |||
| = new ExecutionContext(frame, execComponent, location); | |||
| context.setClassLoader(componentLoader); | |||
| ClassLoader currentLoader | |||
| = LoaderUtils.setContextLoader(componentLoader); | |||
| if (execComponent != null) { | |||
| execComponent.init(context, componentName); | |||
| } | |||
| if (model != null) { | |||
| configureElement(libFactory, component, model); | |||
| if (execComponent != null) { | |||
| execComponent.validateComponent(); | |||
| } | |||
| } | |||
| LoaderUtils.setContextLoader(currentLoader); | |||
| if (execComponent != null) { | |||
| return execComponent; | |||
| } | |||
| return component; | |||
| } catch (ClassNotFoundException e) { | |||
| throw new ExecutionException("Class " + className | |||
| + " for component <" + componentName + "> was not found", e, | |||
| model.getLocation()); | |||
| } catch (NoClassDefFoundError e) { | |||
| throw new ExecutionException("Could not load a dependent class (" | |||
| + e.getMessage() + ") for component " + componentName, | |||
| e, model.getLocation()); | |||
| } catch (InstantiationException e) { | |||
| throw new ExecutionException("Unable to instantiate component " | |||
| + "class " + className + " for component <" + componentName | |||
| + ">", e, model.getLocation()); | |||
| } catch (IllegalAccessException e) { | |||
| throw new ExecutionException("Unable to access task class " | |||
| + className + " for component <" + componentName + ">", | |||
| e, model.getLocation()); | |||
| } catch (ExecutionException e) { | |||
| e.setLocation(model.getLocation(), false); | |||
| throw e; | |||
| } catch (RuntimeException e) { | |||
| throw new ExecutionException(e.getClass().getName() + ": " | |||
| + e.getMessage(), e, model.getLocation()); | |||
| } | |||
| } | |||
| /** | |||
| * Import a single component from the given library | |||
| * | |||
| @@ -390,6 +517,268 @@ public class ComponentManager implements ComponentService { | |||
| definitions.put(label, new ImportInfo(library, libDef)); | |||
| } | |||
| /** | |||
| * Gets the setter for the given class | |||
| * | |||
| * @param c the class for which the reflector is desired | |||
| * @return the reflector | |||
| */ | |||
| private Setter getSetter(Class c) { | |||
| if (setters.containsKey(c)) { | |||
| return (Setter)setters.get(c); | |||
| } | |||
| Setter setter = null; | |||
| if (DeferredTask.class.isAssignableFrom(c)) { | |||
| setter = new DeferredSetter(); | |||
| } else { | |||
| ClassIntrospector introspector | |||
| = new ClassIntrospector(c, getConverters()); | |||
| setter = introspector.getReflector(); | |||
| } | |||
| setters.put(c, setter); | |||
| return setter; | |||
| } | |||
| /** | |||
| * Create an instance of a type given its required class | |||
| * | |||
| * @param typeClass the class from which the instance should be created | |||
| * @param model the model describing the required configuration of the | |||
| * instance | |||
| * @param libFactory the factory object of the typeClass's Ant library | |||
| * @param localName the name of the type within its Ant library | |||
| * @return an instance of the given class appropriately configured | |||
| * @exception ExecutionException if there is a problem creating the type | |||
| * instance | |||
| */ | |||
| private Object createTypeInstance(Class typeClass, AntLibFactory libFactory, | |||
| BuildElement model, String localName) | |||
| throws ExecutionException { | |||
| try { | |||
| Object typeInstance | |||
| = libFactory.createComponent(typeClass, localName); | |||
| if (typeInstance instanceof ExecutionComponent) { | |||
| ExecutionComponent component = (ExecutionComponent)typeInstance; | |||
| ExecutionContext context = new ExecutionContext(frame, | |||
| component, model.getLocation()); | |||
| component.init(context, localName); | |||
| configureElement(libFactory, typeInstance, model); | |||
| component.validateComponent(); | |||
| } else { | |||
| configureElement(libFactory, typeInstance, model); | |||
| } | |||
| return typeInstance; | |||
| } catch (InstantiationException e) { | |||
| throw new ExecutionException("Unable to instantiate type class " | |||
| + typeClass.getName() + " for type <" + model.getType() + ">", | |||
| e, model.getLocation()); | |||
| } catch (IllegalAccessException e) { | |||
| throw new ExecutionException("Unable to access type class " | |||
| + typeClass.getName() + " for type <" + model.getType() + ">", | |||
| e, model.getLocation()); | |||
| } catch (ExecutionException e) { | |||
| e.setLocation(model.getLocation(), false); | |||
| throw e; | |||
| } catch (RuntimeException e) { | |||
| throw new ExecutionException(e.getClass().getName() + ": " | |||
| + e.getMessage(), e, model.getLocation()); | |||
| } | |||
| } | |||
| /** | |||
| * Create and add a nested element | |||
| * | |||
| * @param setter The Setter instance for the container element | |||
| * @param element the container element in which the nested element will | |||
| * be created | |||
| * @param model the model of the nested element | |||
| * @param factory Ant Library factory associated with the element to | |||
| * which the attribute is to be added. | |||
| * @exception ExecutionException if the nested element cannot be created | |||
| */ | |||
| private void addNestedElement(AntLibFactory factory, Setter setter, | |||
| Object element, BuildElement model) | |||
| throws ExecutionException { | |||
| String nestedElementName = model.getType(); | |||
| Class nestedType = setter.getType(nestedElementName); | |||
| // is there a polymorph indicator - look in Ant aspects | |||
| String typeName = model.getAspectValue(Constants.ANT_ASPECT, "type"); | |||
| String refId = model.getAspectValue(Constants.ANT_ASPECT, "refid"); | |||
| if (refId != null && typeName != null) { | |||
| throw new ExecutionException("Only one of " + Constants.ANT_ASPECT | |||
| + ":type and " + Constants.ANT_ASPECT | |||
| + ":refid may be specified at a time", model.getLocation()); | |||
| } | |||
| Object typeInstance = null; | |||
| if (typeName != null) { | |||
| // the build file has specified the actual type of the element. | |||
| // we need to look up that type and use it | |||
| typeInstance = createComponent(typeName, model); | |||
| } else if (refId != null) { | |||
| // We have a reference to an existing instance. Need to check if | |||
| // it is compatible with the type expected by the nested element's | |||
| // adder method | |||
| typeInstance = frame.getDataValue(refId); | |||
| if (model.getAttributeNames().hasNext() || | |||
| model.getNestedElements().hasNext() || | |||
| model.getText().length() != 0) { | |||
| throw new ExecutionException("Element <" + nestedElementName | |||
| + "> is defined by reference and hence may not specify " | |||
| + "any attributes, nested elements or content", | |||
| model.getLocation()); | |||
| } | |||
| if (typeInstance == null) { | |||
| throw new ExecutionException("The given ant:refid value '" | |||
| + refId + "' is not defined", model.getLocation()); | |||
| } | |||
| } else if (nestedType != null) { | |||
| // We need to create an instance of the class expected by the nested | |||
| // element's adder method if that is possible | |||
| if (nestedType.isInterface()) { | |||
| throw new ExecutionException("No element can be created for " | |||
| + "nested element <" + nestedElementName + ">. Please " | |||
| + "provide a value by reference or specify the value type", | |||
| model.getLocation()); | |||
| } | |||
| typeInstance = createTypeInstance(nestedType, factory, model, null); | |||
| } else { | |||
| throw new ExecutionException("The type of the <" | |||
| + nestedElementName + "> nested element is not known. " | |||
| + "Please specify by the type using the \"ant:type\" " | |||
| + "attribute or provide a reference to an instance with " | |||
| + "the \"ant:id\" attribute"); | |||
| } | |||
| // is the typeInstance compatible with the type expected | |||
| // by the element's add method | |||
| if (!nestedType.isInstance(typeInstance)) { | |||
| if (refId != null) { | |||
| throw new ExecutionException("The value specified by refId " | |||
| + refId + " is not compatible with the <" | |||
| + nestedElementName + "> nested element", | |||
| model.getLocation()); | |||
| } else if (typeName != null) { | |||
| throw new ExecutionException("The type " | |||
| + typeName + " is not compatible with the <" | |||
| + nestedElementName + "> nested element", | |||
| model.getLocation()); | |||
| } | |||
| } | |||
| setter.addElement(element, nestedElementName, typeInstance); | |||
| } | |||
| /** | |||
| * Create a nested element for the given object according to the model. | |||
| * | |||
| * @param setter the Setter instance of the container object | |||
| * @param element the container object for which a nested element is | |||
| * required. | |||
| * @param model the build model for the nestd element | |||
| * @param factory Ant Library factory associated with the element | |||
| * creating the nested element | |||
| * @exception ExecutionException if the nested element cannot be | |||
| * created. | |||
| */ | |||
| private void createNestedElement(AntLibFactory factory, Setter setter, | |||
| Object element, BuildElement model) | |||
| throws ExecutionException { | |||
| String nestedElementName = model.getType(); | |||
| try { | |||
| Object nestedElement | |||
| = setter.createElement(element, nestedElementName); | |||
| factory.registerCreatedElement(nestedElement); | |||
| if (nestedElement instanceof ExecutionComponent) { | |||
| ExecutionComponent component | |||
| = (ExecutionComponent)nestedElement; | |||
| ExecutionContext context = new ExecutionContext(frame, | |||
| component, model.getLocation()); | |||
| component.init(context, nestedElementName); | |||
| configureElement(factory, nestedElement, model); | |||
| component.validateComponent(); | |||
| } else { | |||
| configureElement(factory, nestedElement, model); | |||
| } | |||
| } catch (ExecutionException e) { | |||
| e.setLocation(model.getLocation(), false); | |||
| throw e; | |||
| } catch (RuntimeException e) { | |||
| throw new ExecutionException(e.getClass().getName() + ": " | |||
| + e.getMessage(), e, model.getLocation()); | |||
| } | |||
| } | |||
| /** | |||
| * Configure an element according to the given model. | |||
| * | |||
| * @param element the object to be configured | |||
| * @param model the BuildElement describing the object in the build file | |||
| * @param factory Ant Library factory associated with the element being | |||
| * configured | |||
| * @exception ExecutionException if the element cannot be configured | |||
| */ | |||
| private void configureElement(AntLibFactory factory, Object element, | |||
| BuildElement model) | |||
| throws ExecutionException { | |||
| Setter setter = getSetter(element.getClass()); | |||
| // start by setting the attributes of this element | |||
| for (Iterator i = model.getAttributeNames(); i.hasNext(); ) { | |||
| String attributeName = (String)i.next(); | |||
| String attributeValue = model.getAttributeValue(attributeName); | |||
| if (!setter.supportsAttribute(attributeName)) { | |||
| throw new ExecutionException(model.getType() | |||
| + " does not support the \"" + attributeName | |||
| + "\" attribute", model.getLocation()); | |||
| } | |||
| setter.setAttribute(element, attributeName, | |||
| frame.replacePropertyRefs(attributeValue)); | |||
| } | |||
| String modelText = model.getText().trim(); | |||
| if (modelText.length() != 0) { | |||
| if (!setter.supportsText()) { | |||
| throw new ExecutionException(model.getType() | |||
| + " does not support content", model.getLocation()); | |||
| } | |||
| setter.addText(element, | |||
| frame.replacePropertyRefs(modelText)); | |||
| } | |||
| // now do the nested elements | |||
| for (Iterator i = model.getNestedElements(); i.hasNext(); ) { | |||
| BuildElement nestedElementModel = (BuildElement)i.next(); | |||
| String nestedElementName = nestedElementModel.getType(); | |||
| ImportInfo info = getDefinition(nestedElementName); | |||
| if (element instanceof TaskContainer | |||
| && info != null | |||
| && info.getDefinitionType() == AntLibrary.TASKDEF | |||
| && !setter.supportsNestedElement(nestedElementName)) { | |||
| // it is a nested task | |||
| Task nestedTask | |||
| = (Task)createComponent(nestedElementModel); | |||
| TaskContainer container = (TaskContainer)element; | |||
| container.addTask(nestedTask); | |||
| } else { | |||
| if (setter.supportsNestedAdder(nestedElementName)) { | |||
| addNestedElement(factory, setter, element, | |||
| nestedElementModel); | |||
| } else if (setter.supportsNestedCreator(nestedElementName)) { | |||
| createNestedElement(factory, setter, element, | |||
| nestedElementModel); | |||
| } else { | |||
| throw new ExecutionException(model.getType() | |||
| + " does not support the \"" + nestedElementName | |||
| + "\" nested element", | |||
| nestedElementModel.getLocation()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Define a new component | |||
| * | |||
| @@ -445,8 +834,8 @@ public class ComponentManager implements ComponentService { | |||
| } | |||
| Converter converter | |||
| = libFactory.createConverter(converterClass); | |||
| ExecutionContext context | |||
| = new ExecutionContext(frame); | |||
| ExecutionContext context = new ExecutionContext(frame, | |||
| null, Location.UNKNOWN_LOCATION); | |||
| converter.init(context); | |||
| Class[] converterTypes = converter.getTypes(); | |||
| for (int j = 0; j < converterTypes.length; ++j) { | |||
| @@ -475,6 +864,5 @@ public class ComponentManager implements ComponentService { | |||
| + className, e); | |||
| } | |||
| } | |||
| } | |||
| @@ -52,88 +52,19 @@ | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.ant.antcore.execution; | |||
| import org.apache.ant.common.antlib.Task; | |||
| import org.apache.ant.common.model.ModelElement; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| /** | |||
| * This is the core's implementation of the AntContext for Tasks. | |||
| * Core constants | |||
| * | |||
| * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
| * @created 17 January 2002 | |||
| * @created 20 February 2002 | |||
| */ | |||
| public class TaskContext extends ExecutionContext { | |||
| /** The task being managed by this context */ | |||
| private Task task; | |||
| /** | |||
| * the loader used to load this task. Note that this is not necessarily | |||
| * the loader which is used to load the Task class as loading may have | |||
| * been delegated to a parent loader. | |||
| */ | |||
| private ClassLoader loader; | |||
| /** | |||
| * Initilaise this context's environment | |||
| * | |||
| * @param frame the frame containing this context | |||
| */ | |||
| public TaskContext(Frame frame) { | |||
| super(frame); | |||
| } | |||
| /** | |||
| * Get the task associated with this context | |||
| * | |||
| * @return the task instance | |||
| */ | |||
| protected Task getTask() { | |||
| return task; | |||
| } | |||
| /** | |||
| * Gets the loader for this task | |||
| * | |||
| * @return the task's loader | |||
| */ | |||
| protected ClassLoader getLoader() { | |||
| return loader; | |||
| } | |||
| /** | |||
| * Associate a task with this context | |||
| * | |||
| * @param task the task to be manager | |||
| * @param loader the classloader | |||
| * @param modelElement the model element associated with this context | |||
| * @exception ExecutionException if the task cannot be initialized | |||
| */ | |||
| protected void init(ClassLoader loader, Task task, | |||
| ModelElement modelElement) throws ExecutionException { | |||
| this.task = task; | |||
| this.loader = loader; | |||
| setModelElement(modelElement); | |||
| task.init(this); | |||
| } | |||
| public abstract class Constants { | |||
| /** The prefix for library ids that are automatically imported */ | |||
| public static final String ANT_LIB_PREFIX = "ant."; | |||
| /** | |||
| * execute this context's task | |||
| * | |||
| * @exception ExecutionException if there is a problem executing the | |||
| * task | |||
| */ | |||
| protected void execute() throws ExecutionException { | |||
| task.execute(); | |||
| } | |||
| /** The Ant aspect used to identify Ant metadata */ | |||
| public static final String ANT_ASPECT = "ant"; | |||
| /** | |||
| * Destroy this context. The context can be reused for another task | |||
| * after this one | |||
| */ | |||
| protected void destroy() { | |||
| task.destroy(); | |||
| task = null; | |||
| loader = null; | |||
| } | |||
| } | |||
| @@ -58,13 +58,16 @@ import java.util.List; | |||
| import java.util.Map; | |||
| import org.apache.ant.antcore.modelparser.XMLProjectParser; | |||
| import org.apache.ant.antcore.xml.XMLParseException; | |||
| import org.apache.ant.common.antlib.AntContext; | |||
| import org.apache.ant.common.antlib.Task; | |||
| import org.apache.ant.common.model.Project; | |||
| import org.apache.ant.common.service.ExecService; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| import org.apache.ant.init.InitUtils; | |||
| import org.apache.ant.init.LoaderUtils; | |||
| /** | |||
| *This is the core's implementation of the Execution Service. | |||
| * This is the core's implementation of the Execution Service. | |||
| * | |||
| * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
| * @created 8 February 2002 | |||
| @@ -132,5 +135,37 @@ public class CoreExecService implements ExecService { | |||
| runBuild(frame.getProject(), properties, targets); | |||
| } | |||
| /** | |||
| * Execute a task. The task should have already been initialised by | |||
| * the core. This is checked | |||
| * | |||
| * @param task the task to be executed | |||
| * @exception ExecutionException if there is an execution problem | |||
| */ | |||
| public void executeTask(Task task) throws ExecutionException { | |||
| AntContext context = task.getAntContext(); | |||
| if (!(context instanceof ExecutionContext)) { | |||
| throw new ExecutionException("The Task was not configured with an" | |||
| + " appropriate context"); | |||
| } | |||
| ExecutionContext execContext = (ExecutionContext)context; | |||
| frame.getEventSupport().fireTaskStarted(task); | |||
| Throwable failureCause = null; | |||
| try { | |||
| ClassLoader currentLoader | |||
| = LoaderUtils.setContextLoader(execContext.getLoader()); | |||
| task.execute(); | |||
| LoaderUtils.setContextLoader(currentLoader); | |||
| } catch (Throwable e) { | |||
| ExecutionException ee = | |||
| new ExecutionException(e.getClass().getName() + ": " | |||
| + e.getMessage(), e); | |||
| failureCause = ee; | |||
| throw ee; | |||
| } finally { | |||
| frame.getEventSupport().fireTaskFinished(task, failureCause); | |||
| } | |||
| } | |||
| } | |||
| @@ -54,8 +54,9 @@ | |||
| package org.apache.ant.antcore.execution; | |||
| import java.io.File; | |||
| import org.apache.ant.common.antlib.AntContext; | |||
| import org.apache.ant.common.model.ModelElement; | |||
| import org.apache.ant.common.antlib.ExecutionComponent; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| import org.apache.ant.common.util.Location; | |||
| /** | |||
| * This is the core's implementation of the AntContext for all core objects. | |||
| @@ -71,26 +72,32 @@ public class ExecutionContext implements AntContext { | |||
| /** the event support instance used to manage build events */ | |||
| private BuildEventSupport eventSupport; | |||
| /** the model in the build model with which this context is associated */ | |||
| private ModelElement modelElement; | |||
| /** The location of the object associated with this context */ | |||
| private Location location; | |||
| /** the execution component associated with the context, if any */ | |||
| private ExecutionComponent component; | |||
| /** | |||
| * the loader used to load this context. Note that this is not | |||
| * necessarily the loader which is used to load the component as loading | |||
| * may have been delegated to a parent loader. | |||
| */ | |||
| private ClassLoader loader; | |||
| /** | |||
| * Initilaise this context's environment | |||
| * | |||
| * @param frame the frame containing this context | |||
| * @param component the component associated with this context - may be null | |||
| * @param location the location associated with the component | |||
| */ | |||
| protected ExecutionContext(Frame frame) { | |||
| protected ExecutionContext(Frame frame, ExecutionComponent component, | |||
| Location location) { | |||
| this.frame = frame; | |||
| this.eventSupport = frame.getEventSupport(); | |||
| } | |||
| /** | |||
| * Set the model element associated with this context | |||
| * | |||
| * @param modelElement the model element associated with this context | |||
| */ | |||
| protected void setModelElement(ModelElement modelElement) { | |||
| this.modelElement = modelElement; | |||
| this.location = location; | |||
| this.component = component; | |||
| } | |||
| /** | |||
| @@ -107,19 +114,6 @@ public class ExecutionContext implements AntContext { | |||
| return frame.getCoreService(serviceInterfaceClass); | |||
| } | |||
| /** | |||
| * Get the model element associated with this context. If the context is | |||
| * not associated with any particular model element, the project model | |||
| * is returned. | |||
| * | |||
| * @return the model element. | |||
| */ | |||
| public ModelElement getModelElement() { | |||
| if (modelElement == null) { | |||
| return frame.getProject(); | |||
| } | |||
| return modelElement; | |||
| } | |||
| /** | |||
| * Get the base directory for this execution of this frame | |||
| @@ -130,6 +124,15 @@ public class ExecutionContext implements AntContext { | |||
| return frame.getBaseDir(); | |||
| } | |||
| /** | |||
| * Gets the location associated with the ExecutionContext | |||
| * | |||
| * @return the location in the build model associated with this context. | |||
| */ | |||
| public Location getLocation() { | |||
| return location; | |||
| } | |||
| /** | |||
| * Log a message as a build event | |||
| * | |||
| @@ -137,7 +140,7 @@ public class ExecutionContext implements AntContext { | |||
| * @param level the priority level of the message | |||
| */ | |||
| public void log(String message, int level) { | |||
| Object source = modelElement; | |||
| Object source = component; | |||
| if (source == null) { | |||
| source = frame.getProject(); | |||
| if (source == null) { | |||
| @@ -146,5 +149,32 @@ public class ExecutionContext implements AntContext { | |||
| } | |||
| eventSupport.fireMessageLogged(source, message, level); | |||
| } | |||
| /** | |||
| * Sets the classLoader of the ExecutionContext | |||
| * | |||
| * @param loader the new classLoader value | |||
| */ | |||
| protected void setClassLoader(ClassLoader loader) { | |||
| this.loader = loader; | |||
| } | |||
| /** | |||
| * Gets the loader for this task | |||
| * | |||
| * @return the task's loader | |||
| */ | |||
| protected ClassLoader getLoader() { | |||
| return loader; | |||
| } | |||
| /** | |||
| * Gets the executionComponent of the ExecutionContext | |||
| * | |||
| * @return the executionComponent value | |||
| */ | |||
| protected ExecutionComponent getExecutionComponent() { | |||
| return component; | |||
| } | |||
| } | |||
| @@ -59,14 +59,8 @@ import java.util.Iterator; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.StringTokenizer; | |||
| import org.apache.ant.antcore.antlib.AntLibrary; | |||
| import org.apache.ant.antcore.antlib.ComponentLibrary; | |||
| import org.apache.ant.antcore.config.AntConfig; | |||
| import org.apache.ant.common.antlib.AntLibFactory; | |||
| import org.apache.ant.common.antlib.DeferredTask; | |||
| import org.apache.ant.common.antlib.ExecutionComponent; | |||
| import org.apache.ant.common.antlib.Task; | |||
| import org.apache.ant.common.antlib.TaskContainer; | |||
| import org.apache.ant.common.event.BuildListener; | |||
| import org.apache.ant.common.event.MessageLevel; | |||
| import org.apache.ant.common.model.BuildElement; | |||
| @@ -93,9 +87,6 @@ import org.apache.ant.init.InitConfig; | |||
| * @created 14 January 2002 | |||
| */ | |||
| public class Frame { | |||
| /** The Ant aspect used to identify Ant metadata */ | |||
| public static final String ANT_ASPECT = "ant"; | |||
| /** the base dir of the project */ | |||
| private File baseDir; | |||
| @@ -105,9 +96,6 @@ public class Frame { | |||
| /** The referenced frames corresponding to the referenced projects */ | |||
| private Map referencedFrames = new HashMap(); | |||
| /** Reflector objects used to configure Tasks from the Task models. */ | |||
| private Map setters = new HashMap(); | |||
| /** | |||
| * The context of this execution. This contains all data object's | |||
| * created by tasks that have been executed | |||
| @@ -155,6 +143,11 @@ public class Frame { | |||
| */ | |||
| private ComponentManager componentManager; | |||
| /** | |||
| * The core's execution Service | |||
| */ | |||
| private CoreExecService execService; | |||
| /** | |||
| * Create an Execution Frame for the given project | |||
| * | |||
| @@ -172,20 +165,6 @@ public class Frame { | |||
| this.initConfig = initConfig; | |||
| } | |||
| /** | |||
| * Set the context loader of the current thread and returns the existing | |||
| * classloader | |||
| * | |||
| * @param newLoader the new context loader | |||
| * @return the old context loader | |||
| */ | |||
| private static ClassLoader setContextLoader(ClassLoader newLoader) { | |||
| Thread thread = Thread.currentThread(); | |||
| ClassLoader currentLoader = thread.getContextClassLoader(); | |||
| thread.setContextClassLoader(newLoader); | |||
| return currentLoader; | |||
| } | |||
| /** | |||
| * Sets the Project of the Frame | |||
| * | |||
| @@ -210,6 +189,18 @@ public class Frame { | |||
| setMagicProperties(); | |||
| } | |||
| /** | |||
| * Replace ${} style constructions in the given value with the string | |||
| * value of the corresponding data values in the frame | |||
| * | |||
| * @param value the string to be scanned for property references. | |||
| * @return the string with all property references replaced | |||
| * @exception ExecutionException if any of the properties do not exist | |||
| */ | |||
| public String replacePropertyRefs(String value) throws ExecutionException { | |||
| return dataService.replacePropertyRefs(value); | |||
| } | |||
| /** | |||
| * Set a value in this frame or any of its imported frames. | |||
| * | |||
| @@ -625,48 +616,29 @@ public class Frame { | |||
| protected void executeTasks(Iterator taskIterator) | |||
| throws ExecutionException { | |||
| while (taskIterator.hasNext()) { | |||
| Throwable failureCause = null; | |||
| BuildElement model = (BuildElement)taskIterator.next(); | |||
| // what sort of element is this. | |||
| ImportInfo importInfo | |||
| = componentManager.getDefinition(model.getType()); | |||
| if (importInfo == null) { | |||
| throw new ExecutionException("There is no definition for the <" | |||
| + model.getType() + "> element", model.getLocation()); | |||
| } | |||
| try { | |||
| if (importInfo.getDefinitionType() == AntLibrary.TASKDEF) { | |||
| TaskContext taskContext = configureTask(model); | |||
| eventSupport.fireTaskStarted(model); | |||
| ClassLoader currentLoader | |||
| = setContextLoader(taskContext.getLoader()); | |||
| taskContext.execute(); | |||
| setContextLoader(currentLoader); | |||
| taskContext.destroy(); | |||
| Object component = componentManager.createComponent(model); | |||
| if (component instanceof Task) { | |||
| execService.executeTask((Task)component); | |||
| } else { | |||
| // typedef | |||
| String typeId = model.getAspectValue(ANT_ASPECT, "id"); | |||
| Object typeInstance = configureType(model.getType(), model); | |||
| String typeId | |||
| = model.getAspectValue(Constants.ANT_ASPECT, "id"); | |||
| if (typeId != null) { | |||
| setDataValue(typeId, typeInstance, true); | |||
| setDataValue(typeId, component, true); | |||
| } | |||
| } | |||
| } catch (AntException te) { | |||
| ExecutionException e | |||
| = new ExecutionException(te, te.getLocation()); | |||
| e.setLocation(model.getLocation(), false); | |||
| failureCause = e; | |||
| throw e; | |||
| } catch (RuntimeException e) { | |||
| ExecutionException ee = | |||
| new ExecutionException(e.getClass().getName() + ": " | |||
| + e.getMessage(), e, model.getLocation()); | |||
| failureCause = ee; | |||
| throw ee; | |||
| } finally { | |||
| eventSupport.fireTaskFinished(model, failureCause); | |||
| } | |||
| } | |||
| @@ -737,30 +709,6 @@ public class Frame { | |||
| executeTasks(taskIterator); | |||
| } | |||
| /** | |||
| * Gets the setter for the given class | |||
| * | |||
| * @param c the class for which the reflector is desired | |||
| * @return the reflector | |||
| */ | |||
| private Setter getSetter(Class c) { | |||
| if (setters.containsKey(c)) { | |||
| return (Setter)setters.get(c); | |||
| } | |||
| Setter setter = null; | |||
| if (DeferredTask.class.isAssignableFrom(c)) { | |||
| setter = new DeferredSetter(); | |||
| } else { | |||
| ClassIntrospector introspector | |||
| = new ClassIntrospector(c, componentManager.getConverters()); | |||
| setter = introspector.getReflector(); | |||
| } | |||
| setters.put(c, setter); | |||
| return setter; | |||
| } | |||
| /** | |||
| * Determine the base directory for each frame in the frame hierarchy | |||
| * | |||
| @@ -806,383 +754,13 @@ public class Frame { | |||
| config.isRemoteLibAllowed(), config.getLibraryPathsMap()); | |||
| dataService = new CoreDataService(this, | |||
| config.isUnsetPropertiesAllowed()); | |||
| execService = new CoreExecService(this); | |||
| services.put(FileService.class, fileService); | |||
| services.put(ComponentService.class, componentManager); | |||
| services.put(DataService.class, dataService); | |||
| services.put(EventService.class, new CoreEventService(this)); | |||
| services.put(ExecService.class, new CoreExecService(this)); | |||
| } | |||
| /** | |||
| * Configure an element according to the given model. | |||
| * | |||
| * @param element the object to be configured | |||
| * @param model the BuildElement describing the object in the build file | |||
| * @param factory Ant Library factory associated with the element being | |||
| * configured | |||
| * @exception ExecutionException if the element cannot be configured | |||
| */ | |||
| private void configureElement(AntLibFactory factory, Object element, | |||
| BuildElement model) | |||
| throws ExecutionException { | |||
| Setter setter = getSetter(element.getClass()); | |||
| // start by setting the attributes of this element | |||
| for (Iterator i = model.getAttributeNames(); i.hasNext(); ) { | |||
| String attributeName = (String)i.next(); | |||
| String attributeValue = model.getAttributeValue(attributeName); | |||
| if (!setter.supportsAttribute(attributeName)) { | |||
| throw new ExecutionException(model.getType() | |||
| + " does not support the \"" + attributeName | |||
| + "\" attribute", model.getLocation()); | |||
| } | |||
| setter.setAttribute(element, attributeName, | |||
| dataService.replacePropertyRefs(attributeValue)); | |||
| } | |||
| String modelText = model.getText().trim(); | |||
| if (modelText.length() != 0) { | |||
| if (!setter.supportsText()) { | |||
| throw new ExecutionException(model.getType() | |||
| + " does not support content", model.getLocation()); | |||
| } | |||
| setter.addText(element, | |||
| dataService.replacePropertyRefs(modelText)); | |||
| } | |||
| // now do the nested elements | |||
| for (Iterator i = model.getNestedElements(); i.hasNext(); ) { | |||
| BuildElement nestedElementModel = (BuildElement)i.next(); | |||
| String nestedElementName = nestedElementModel.getType(); | |||
| ImportInfo info = componentManager.getDefinition(nestedElementName); | |||
| if (element instanceof TaskContainer | |||
| && info != null | |||
| && info.getDefinitionType() == AntLibrary.TASKDEF | |||
| && !setter.supportsNestedElement(nestedElementName)) { | |||
| // it is a nested task | |||
| TaskContext nestedContext | |||
| = configureTask(nestedElementModel); | |||
| TaskContainer container = (TaskContainer)element; | |||
| // XXX what should we be adding - need to understand container | |||
| // method of executing tasks | |||
| container.addTask(nestedContext.getTask()); | |||
| } else { | |||
| if (setter.supportsNestedAdder(nestedElementName)) { | |||
| addNestedElement(factory, setter, element, | |||
| nestedElementModel); | |||
| } else if (setter.supportsNestedCreator(nestedElementName)) { | |||
| createNestedElement(factory, setter, element, | |||
| nestedElementModel); | |||
| } else { | |||
| throw new ExecutionException(model.getType() | |||
| + " does not support the \"" + nestedElementName | |||
| + "\" nested element", | |||
| nestedElementModel.getLocation()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Create a nested element for the given object according to the model. | |||
| * | |||
| * @param setter the Setter instance of the container object | |||
| * @param element the container object for which a nested element is | |||
| * required. | |||
| * @param model the build model for the nestd element | |||
| * @param factory Ant Library factory associated with the element | |||
| * creating the nested element | |||
| * @exception ExecutionException if the nested element cannot be | |||
| * created. | |||
| */ | |||
| private void createNestedElement(AntLibFactory factory, Setter setter, | |||
| Object element, BuildElement model) | |||
| throws ExecutionException { | |||
| String nestedElementName = model.getType(); | |||
| try { | |||
| Object nestedElement | |||
| = setter.createElement(element, nestedElementName); | |||
| factory.registerCreatedElement(nestedElement); | |||
| if (nestedElement instanceof ExecutionComponent) { | |||
| ExecutionComponent component | |||
| = (ExecutionComponent)nestedElement; | |||
| ExecutionContext context | |||
| = new ExecutionContext(this); | |||
| context.setModelElement(model); | |||
| component.init(context); | |||
| configureElement(factory, nestedElement, model); | |||
| component.validateComponent(); | |||
| } else { | |||
| configureElement(factory, nestedElement, model); | |||
| } | |||
| } catch (ExecutionException e) { | |||
| e.setLocation(model.getLocation(), false); | |||
| throw e; | |||
| } catch (RuntimeException e) { | |||
| throw new ExecutionException(e.getClass().getName() + ": " | |||
| + e.getMessage(), e, model.getLocation()); | |||
| } | |||
| } | |||
| /** | |||
| * Create and add a nested element | |||
| * | |||
| * @param setter The Setter instance for the container element | |||
| * @param element the container element in which the nested element will | |||
| * be created | |||
| * @param model the model of the nested element | |||
| * @param factory Ant Library factory associated with the element to | |||
| * which the attribute is to be added. | |||
| * @exception ExecutionException if the nested element cannot be created | |||
| */ | |||
| private void addNestedElement(AntLibFactory factory, Setter setter, | |||
| Object element, BuildElement model) | |||
| throws ExecutionException { | |||
| String nestedElementName = model.getType(); | |||
| Class nestedType = setter.getType(nestedElementName); | |||
| // is there a polymorph indicator - look in Ant aspects | |||
| String typeName = model.getAspectValue(ANT_ASPECT, "type"); | |||
| String refId = model.getAspectValue(ANT_ASPECT, "refid"); | |||
| if (refId != null && typeName != null) { | |||
| throw new ExecutionException("Only one of " + ANT_ASPECT | |||
| + ":type and " + ANT_ASPECT | |||
| + ":refid may be specified at a time", model.getLocation()); | |||
| } | |||
| Object typeInstance = null; | |||
| if (typeName != null) { | |||
| // the build file has specified the actual type of the element. | |||
| // we need to look up that type and use it | |||
| typeInstance = configureType(typeName, model); | |||
| } else if (refId != null) { | |||
| // We have a reference to an existing instance. Need to check if | |||
| // it is compatible with the type expected by the nested element's | |||
| // adder method | |||
| typeInstance = getDataValue(refId); | |||
| if (model.getAttributeNames().hasNext() || | |||
| model.getNestedElements().hasNext() || | |||
| model.getText().length() != 0) { | |||
| throw new ExecutionException("Element <" + nestedElementName | |||
| + "> is defined by reference and hence may not specify " | |||
| + "any attributes, nested elements or content", | |||
| model.getLocation()); | |||
| } | |||
| if (typeInstance == null) { | |||
| throw new ExecutionException("The given ant:refid value '" | |||
| + refId + "' is not defined", model.getLocation()); | |||
| } | |||
| } else if (nestedType != null) { | |||
| // We need to create an instance of the class expected by the nested | |||
| // element's adder method if that is possible | |||
| if (nestedType.isInterface()) { | |||
| throw new ExecutionException("No element can be created for " | |||
| + "nested element <" + nestedElementName + ">. Please " | |||
| + "provide a value by reference or specify the value type", | |||
| model.getLocation()); | |||
| } | |||
| typeInstance = createTypeInstance(nestedType, factory, model, null); | |||
| } else { | |||
| throw new ExecutionException("The type of the <" | |||
| + nestedElementName + "> nested element is not known. " | |||
| + "Please specify by the type using the \"ant:type\" " | |||
| + "attribute or provide a reference to an instance with " | |||
| + "the \"ant:id\" attribute"); | |||
| } | |||
| // is the typeInstance compatible with the type expected | |||
| // by the element's add method | |||
| if (!nestedType.isInstance(typeInstance)) { | |||
| if (refId != null) { | |||
| throw new ExecutionException("The value specified by refId " | |||
| + refId + " is not compatible with the <" | |||
| + nestedElementName + "> nested element", | |||
| model.getLocation()); | |||
| } else if (typeName != null) { | |||
| throw new ExecutionException("The type " | |||
| + typeName + " is not compatible with the <" | |||
| + nestedElementName + "> nested element", | |||
| model.getLocation()); | |||
| } | |||
| } | |||
| setter.addElement(element, nestedElementName, typeInstance); | |||
| } | |||
| /** | |||
| * Create a Task and configure it according to the given model. | |||
| * | |||
| * @param model the model for the task from the build file | |||
| * @return an execution context for managing the task | |||
| * @exception ExecutionException if there is a problem configuring the | |||
| * task | |||
| */ | |||
| private TaskContext configureTask(BuildElement model) | |||
| throws ExecutionException { | |||
| String taskType = model.getType(); | |||
| ImportInfo taskDefInfo = componentManager.getDefinition(taskType); | |||
| if (taskDefInfo == null | |||
| || taskDefInfo.getDefinitionType() != AntLibrary.TASKDEF) { | |||
| throw new ExecutionException("There is no defintion for a " | |||
| + "task of type <" + taskType + ">", model.getLocation()); | |||
| } | |||
| String className = taskDefInfo.getClassName(); | |||
| ComponentLibrary componentLibrary | |||
| = taskDefInfo.getComponentLibrary(); | |||
| String localName = taskDefInfo.getLocalName(); | |||
| try { | |||
| ClassLoader taskClassLoader = componentLibrary.getClassLoader(); | |||
| Class elementClass | |||
| = Class.forName(className, true, taskClassLoader); | |||
| AntLibFactory libFactory | |||
| = componentManager.getLibFactory(componentLibrary); | |||
| Object element | |||
| = libFactory.createTaskInstance(elementClass, localName); | |||
| Task task = null; | |||
| if (element instanceof Task) { | |||
| // create a Task context for the Task | |||
| task = (Task)element; | |||
| } else { | |||
| task = new TaskAdapter(taskType, element); | |||
| } | |||
| // set the context loader while configuring the element | |||
| ClassLoader currentLoader = setContextLoader(taskClassLoader); | |||
| TaskContext taskContext = new TaskContext(this); | |||
| taskContext.init(taskClassLoader, task, model); | |||
| configureElement(libFactory, element, model); | |||
| task.validateComponent(); | |||
| setContextLoader(currentLoader); | |||
| return taskContext; | |||
| } catch (ClassNotFoundException e) { | |||
| throw new ExecutionException("Class " + className | |||
| + " for task <" + taskType + "> was not found", e, | |||
| model.getLocation()); | |||
| } catch (NoClassDefFoundError e) { | |||
| throw new ExecutionException("Could not load a dependent class (" | |||
| + e.getMessage() + ") for task " + taskType, | |||
| e, model.getLocation()); | |||
| } catch (InstantiationException e) { | |||
| throw new ExecutionException("Unable to instantiate task class " | |||
| + className + " for task <" + taskType + ">", | |||
| e, model.getLocation()); | |||
| } catch (IllegalAccessException e) { | |||
| throw new ExecutionException("Unable to access task class " | |||
| + className + " for task <" + taskType + ">", | |||
| e, model.getLocation()); | |||
| } catch (ExecutionException e) { | |||
| e.setLocation(model.getLocation(), false); | |||
| throw e; | |||
| } catch (RuntimeException e) { | |||
| throw new ExecutionException(e.getClass().getName() + ": " | |||
| + e.getMessage(), e, model.getLocation()); | |||
| } | |||
| } | |||
| /** | |||
| * Configure a type instance from the given build model. The name given | |||
| * may not match the name in the model type value. This allows the | |||
| * caller to provide a polymorphic type for the type model | |||
| * | |||
| * @param typeName the name of the type which should be created | |||
| * @param model the model describing the type | |||
| * @return an instance of the type, configured from the model | |||
| * @exception ExecutionException if the type could not be created | |||
| */ | |||
| private Object configureType(String typeName, BuildElement model) | |||
| throws ExecutionException { | |||
| ImportInfo typeDefInfo = componentManager.getDefinition(typeName); | |||
| if (typeDefInfo == null | |||
| || typeDefInfo.getDefinitionType() != AntLibrary.TYPEDEF) { | |||
| throw new ExecutionException("There is no defintion for a " | |||
| + "type <" + typeName + ">", model.getLocation()); | |||
| } | |||
| String className = typeDefInfo.getClassName(); | |||
| ComponentLibrary componentLibrary | |||
| = typeDefInfo.getComponentLibrary(); | |||
| String localName = typeDefInfo.getLocalName(); | |||
| try { | |||
| ClassLoader typeClassLoader = componentLibrary.getClassLoader(); | |||
| Class typeClass | |||
| = Class.forName(className, true, typeClassLoader); | |||
| ClassLoader currentLoader = setContextLoader(typeClassLoader); | |||
| AntLibFactory libFactory | |||
| = componentManager.getLibFactory(componentLibrary); | |||
| Object typeInstance | |||
| = createTypeInstance(typeClass, libFactory, model, localName); | |||
| setContextLoader(currentLoader); | |||
| return typeInstance; | |||
| } catch (ClassNotFoundException e) { | |||
| throw new ExecutionException("Class " + className | |||
| + " for type <" + typeName + "> was not found", e, | |||
| model.getLocation()); | |||
| } catch (NoClassDefFoundError e) { | |||
| throw new ExecutionException("Could not load a dependent class (" | |||
| + e.getMessage() + ") for type " + typeName); | |||
| } | |||
| } | |||
| /** | |||
| * Create an instance of a type given its required class | |||
| * | |||
| * @param typeClass the class from which the instance should be created | |||
| * @param model the model describing the required configuration of the | |||
| * instance | |||
| * @param libFactory the factory object of the typeClass's Ant library | |||
| * @param localName the name of the type within its Ant library | |||
| * @return an instance of the given class appropriately configured | |||
| * @exception ExecutionException if there is a problem creating the type | |||
| * instance | |||
| */ | |||
| private Object createTypeInstance(Class typeClass, AntLibFactory libFactory, | |||
| BuildElement model, String localName) | |||
| throws ExecutionException { | |||
| try { | |||
| Object typeInstance | |||
| = libFactory.createTypeInstance(typeClass, localName); | |||
| if (typeInstance instanceof ExecutionComponent) { | |||
| ExecutionComponent component = (ExecutionComponent)typeInstance; | |||
| ExecutionContext context | |||
| = new ExecutionContext(this); | |||
| context.setModelElement(model); | |||
| component.init(context); | |||
| configureElement(libFactory, typeInstance, model); | |||
| component.validateComponent(); | |||
| } else { | |||
| configureElement(libFactory, typeInstance, model); | |||
| } | |||
| return typeInstance; | |||
| } catch (InstantiationException e) { | |||
| throw new ExecutionException("Unable to instantiate type class " | |||
| + typeClass.getName() + " for type <" + model.getType() + ">", | |||
| e, model.getLocation()); | |||
| } catch (IllegalAccessException e) { | |||
| throw new ExecutionException("Unable to access type class " | |||
| + typeClass.getName() + " for type <" + model.getType() + ">", | |||
| e, model.getLocation()); | |||
| } catch (ExecutionException e) { | |||
| e.setLocation(model.getLocation(), false); | |||
| throw e; | |||
| } catch (RuntimeException e) { | |||
| throw new ExecutionException(e.getClass().getName() + ": " | |||
| + e.getMessage(), e, model.getLocation()); | |||
| } | |||
| services.put(ExecService.class, execService); | |||
| } | |||
| } | |||
| @@ -102,65 +102,48 @@ public class Ant1Factory extends StandardLibFactory { | |||
| /** | |||
| * Create an instance of the requested type class | |||
| * Create an instance of the given component class | |||
| * | |||
| * @param typeClass the class from which an instance is required | |||
| * @param localName the name of the type within its library | |||
| * @return an instance of the requested class | |||
| * @exception ExecutionException the instance could not be created. | |||
| * @exception InstantiationException if the type cannot be instantiated | |||
| * @exception IllegalAccessException if the type cannot be accessed | |||
| * @param componentClass the class for which an instance is required | |||
| * @param localName the name within the library under which the task is | |||
| * defined | |||
| * @return an instance of the required class | |||
| * @exception InstantiationException if the class cannot be instantiated | |||
| * @exception IllegalAccessException if the instance cannot be accessed | |||
| * @exception ExecutionException if there is a problem creating the task | |||
| */ | |||
| public Object createTypeInstance(Class typeClass, String localName) | |||
| public Object createComponent(Class componentClass, String localName) | |||
| throws InstantiationException, IllegalAccessException, | |||
| ExecutionException { | |||
| try { | |||
| java.lang.reflect.Constructor ctor = null; | |||
| java.lang.reflect.Constructor constructor = null; | |||
| // DataType can have a "no arg" constructor or take a single | |||
| // Project argument. | |||
| Object o = null; | |||
| Object component = null; | |||
| try { | |||
| ctor = typeClass.getConstructor(new Class[0]); | |||
| o = ctor.newInstance(new Object[0]); | |||
| constructor = componentClass.getConstructor(new Class[0]); | |||
| component = constructor.newInstance(new Object[0]); | |||
| } catch (NoSuchMethodException nse) { | |||
| ctor = typeClass.getConstructor(new Class[]{Project.class}); | |||
| o = ctor.newInstance(new Object[]{project}); | |||
| constructor | |||
| = componentClass.getConstructor(new Class[]{Project.class}); | |||
| component = constructor.newInstance(new Object[]{project}); | |||
| } | |||
| if (o instanceof ProjectComponent) { | |||
| ((ProjectComponent)o).setProject(project); | |||
| if (component instanceof ProjectComponent) { | |||
| ((ProjectComponent)component).setProject(project); | |||
| } | |||
| return o; | |||
| return component; | |||
| } catch (java.lang.reflect.InvocationTargetException ite) { | |||
| Throwable t = ite.getTargetException(); | |||
| String msg = "Could not create datatype of type: " | |||
| + typeClass.getName() + " due to " + t; | |||
| String msg = "Could not create component of type: " | |||
| + componentClass.getName() + " due to " + t; | |||
| throw new ExecutionException(msg, t); | |||
| } catch (NoSuchMethodException e) { | |||
| throw new ExecutionException("Unable to find an appropriate " | |||
| + "constructor for type " + typeClass.getName(), e); | |||
| + "constructor for component " + componentClass.getName(), e); | |||
| } | |||
| } | |||
| /** | |||
| * Create an instance of the requested task class | |||
| * | |||
| * @param taskClass the class from which an instance is required | |||
| * @param localName the name of the task within its library | |||
| * @return an instance of the requested class | |||
| * @exception InstantiationException if the task cannot be instantiated | |||
| * @exception IllegalAccessException if the task cannot be accessed | |||
| */ | |||
| public Object createTaskInstance(Class taskClass, String localName) | |||
| throws InstantiationException, IllegalAccessException { | |||
| Object instance = taskClass.newInstance(); | |||
| if (instance instanceof ProjectComponent) { | |||
| ((ProjectComponent)instance).setProject(project); | |||
| } | |||
| return instance; | |||
| } | |||
| /** | |||
| * Create a converter. | |||
| * | |||
| @@ -474,7 +474,7 @@ public class Project implements org.apache.ant.common.event.BuildListener { | |||
| public void targetStarted(org.apache.ant.common.event.BuildEvent event) { | |||
| Target newTarget = new Target(this); | |||
| org.apache.ant.common.model.Target realTarget = | |||
| (org.apache.ant.common.model.Target)event.getModelElement(); | |||
| (org.apache.ant.common.model.Target)event.getSource(); | |||
| newTarget.setName(realTarget.getName()); | |||
| targetStack.push(newTarget); | |||
| fireTargetStarted(newTarget); | |||
| @@ -487,7 +487,7 @@ public class Project implements org.apache.ant.common.event.BuildListener { | |||
| */ | |||
| public void targetFinished(org.apache.ant.common.event.BuildEvent event) { | |||
| org.apache.ant.common.model.Target realTarget = | |||
| (org.apache.ant.common.model.Target)event.getModelElement(); | |||
| (org.apache.ant.common.model.Target)event.getSource(); | |||
| Target currentTarget = (Target)targetStack.pop(); | |||
| fireTargetFinished(currentTarget, event.getCause()); | |||
| currentTarget = null; | |||
| @@ -881,7 +881,7 @@ public class Project implements org.apache.ant.common.event.BuildListener { | |||
| try { | |||
| task = (Task)c.newInstance(); | |||
| task.setProject(this); | |||
| task.init(context); | |||
| task.init(context, taskType); | |||
| return task; | |||
| } catch (Throwable e) { | |||
| throw new BuildException(e); | |||
| @@ -69,6 +69,8 @@ public abstract class ProjectComponent { | |||
| protected Location location; | |||
| /** The core context for this component */ | |||
| private AntContext context; | |||
| /** The type of the component bneing created */ | |||
| private String componentType; | |||
| /** | |||
| * Sets the project of the ProjectComponent | |||
| @@ -108,16 +110,39 @@ public abstract class ProjectComponent { | |||
| return location; | |||
| } | |||
| /** | |||
| * Gets the componentType of the ProjectComponent | |||
| * | |||
| * @return the componentType value | |||
| */ | |||
| public String getComponentType() { | |||
| return componentType; | |||
| } | |||
| /** | |||
| * Get the context associated with this component | |||
| * | |||
| * @return the AntContext | |||
| */ | |||
| public AntContext getAntContext() { | |||
| return context; | |||
| } | |||
| /** | |||
| * Initialise this component | |||
| * | |||
| * @param context the core context for this component | |||
| * @param componentType the component type of this component | |||
| * @exception ExecutionException if the component cannot be initialized | |||
| */ | |||
| public void init(AntContext context) throws ExecutionException { | |||
| public void init(AntContext context, String componentType) | |||
| throws ExecutionException { | |||
| this.context = context; | |||
| this.componentType = componentType; | |||
| org.apache.ant.common.util.Location contextLocation | |||
| = context.getModelElement().getLocation(); | |||
| = context.getLocation(); | |||
| if (contextLocation | |||
| == org.apache.ant.common.util.Location.UNKNOWN_LOCATION) { | |||
| @@ -129,11 +154,6 @@ public abstract class ProjectComponent { | |||
| } | |||
| } | |||
| /** Destroy this component */ | |||
| public void destroy() { | |||
| // nothing to do | |||
| } | |||
| /** | |||
| * Log a message as a build event | |||
| * | |||
| @@ -154,15 +174,5 @@ public abstract class ProjectComponent { | |||
| public void log(String message) { | |||
| log(message, Project.MSG_INFO); | |||
| } | |||
| /** | |||
| * Get the context associated with this component | |||
| * | |||
| * @return the AntContext | |||
| */ | |||
| protected AntContext getContext() { | |||
| return context; | |||
| } | |||
| } | |||
| @@ -54,8 +54,8 @@ | |||
| package org.apache.tools.ant; | |||
| import org.apache.ant.common.antlib.AntContext; | |||
| import org.apache.ant.common.service.ExecService; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| import org.apache.ant.common.model.BuildElement; | |||
| /** | |||
| * Ant1 Task facade | |||
| @@ -74,22 +74,6 @@ public abstract class Task extends ProjectComponent | |||
| /** The description of this task */ | |||
| protected String description = null; | |||
| /** | |||
| * Initialise this component | |||
| * | |||
| * @param context the core context for this component | |||
| * @exception ExecutionException if the component cannot be initialized | |||
| */ | |||
| public void init(AntContext context) throws ExecutionException { | |||
| super.init(context); | |||
| if (context.getModelElement() instanceof BuildElement) { | |||
| BuildElement buildElement = (BuildElement)context.getModelElement(); | |||
| taskType = buildElement.getType(); | |||
| taskName = taskType; | |||
| } | |||
| } | |||
| /** | |||
| * Set the name to use in logging messages. | |||
| * | |||
| @@ -147,12 +131,39 @@ public abstract class Task extends ProjectComponent | |||
| return description; | |||
| } | |||
| /** | |||
| * Initialise this component | |||
| * | |||
| * @param context the core context for this component | |||
| * @param componentType the component type of this component | |||
| * @exception ExecutionException if the component cannot be initialized | |||
| */ | |||
| public void init(AntContext context, String componentType) | |||
| throws ExecutionException { | |||
| super.init(context, componentType); | |||
| taskType = componentType; | |||
| taskName = componentType; | |||
| } | |||
| /** Validate this component */ | |||
| public void validateComponent() { | |||
| // no default validation for Ant1 tasks | |||
| } | |||
| /** Execute this task sending the appropriate build events */ | |||
| public final void perform() { | |||
| try { | |||
| AntContext context = getAntContext(); | |||
| ExecService execService | |||
| = (ExecService)context.getCoreService(ExecService.class); | |||
| execService.executeTask(this); | |||
| } catch (ExecutionException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| /** | |||
| * Handle output captured for this task | |||
| * | |||
| @@ -122,7 +122,7 @@ public class ScriptBase extends AbstractTask implements DeferredTask { | |||
| try { | |||
| BSFManager manager = new BSFManager(); | |||
| manager.declareBean("self", this, getClass()); | |||
| manager.declareBean("context", getContext(), AntContext.class); | |||
| manager.declareBean("context", getAntContext(), AntContext.class); | |||
| // execute the script | |||
| BSFEngine engine = manager.loadScriptingEngine(language); | |||
| @@ -139,9 +139,9 @@ public class ScriptFactory extends StandardLibFactory { | |||
| } | |||
| /** | |||
| * Create an instance of the given task class | |||
| * Create an instance of the given component class | |||
| * | |||
| * @param taskClass the class for which an instance is required | |||
| * @param componentClass the class for which an instance is required | |||
| * @param localName the name within the library undeer which the task is | |||
| * defined | |||
| * @return an instance of the required class | |||
| @@ -149,20 +149,20 @@ public class ScriptFactory extends StandardLibFactory { | |||
| * @exception IllegalAccessException if the instance cannot be accessed | |||
| * @exception ExecutionException if there is a problem creating the task | |||
| */ | |||
| public Object createTaskInstance(Class taskClass, String localName) | |||
| public Object createComponent(Class componentClass, String localName) | |||
| throws InstantiationException, IllegalAccessException, | |||
| ExecutionException { | |||
| Object task = super.createTaskInstance(taskClass, localName); | |||
| Object component = super.createComponent(componentClass, localName); | |||
| if (task instanceof ScriptDef) { | |||
| ScriptDef scriptDef = (ScriptDef)task; | |||
| if (component instanceof ScriptDef) { | |||
| ScriptDef scriptDef = (ScriptDef)component; | |||
| scriptDef.setFactory(this); | |||
| } else if (task instanceof ScriptBase) { | |||
| ScriptBase scriptBase = (ScriptBase)task; | |||
| } else if (component instanceof ScriptBase) { | |||
| ScriptBase scriptBase = (ScriptBase)component; | |||
| scriptBase.setFactory(this); | |||
| scriptBase.setScriptName(localName); | |||
| } | |||
| return task; | |||
| return component; | |||
| } | |||
| /** | |||
| @@ -105,7 +105,7 @@ public class Ant extends AntBase { | |||
| */ | |||
| public void execute() throws ExecutionException { | |||
| if (baseDir == null) { | |||
| baseDir = getContext().getBaseDir(); | |||
| baseDir = getAntContext().getBaseDir(); | |||
| } | |||
| if (antFile == null) { | |||
| antFile = new File(baseDir, "build.ant"); | |||
| @@ -253,10 +253,13 @@ public abstract class AntBase extends AbstractTask { | |||
| * Initialise this task | |||
| * | |||
| * @param context core's context | |||
| * @param componentType the component type of this component (i.e its | |||
| * defined name in the build file) | |||
| * @exception ExecutionException if we can't access the data service | |||
| */ | |||
| public void init(AntContext context) throws ExecutionException { | |||
| super.init(context); | |||
| public void init(AntContext context, String componentType) | |||
| throws ExecutionException { | |||
| super.init(context, componentType); | |||
| dataService = (DataService)getCoreService(DataService.class); | |||
| } | |||
| @@ -70,7 +70,7 @@ public class AntCall extends AntBase { | |||
| */ | |||
| public void execute() throws ExecutionException { | |||
| setProperty(MagicProperties.BASEDIR, | |||
| getContext().getBaseDir().getAbsolutePath()); | |||
| getAntContext().getBaseDir().getAbsolutePath()); | |||
| ExecService execService | |||
| = (ExecService)getCoreService(ExecService.class); | |||
| @@ -143,7 +143,7 @@ public class Import extends AbstractTask { | |||
| * @exception ExecutionException if the components cannot be imported | |||
| */ | |||
| public void execute() throws ExecutionException { | |||
| AntContext context = getContext(); | |||
| AntContext context = getAntContext(); | |||
| ComponentService componentService = (ComponentService) | |||
| context.getCoreService(ComponentService.class); | |||
| if (ref != null) { | |||
| @@ -150,7 +150,7 @@ public class LibPath extends AbstractTask { | |||
| * the library | |||
| */ | |||
| public void execute() throws ExecutionException { | |||
| AntContext context = getContext(); | |||
| AntContext context = getAntContext(); | |||
| ComponentService componentService = (ComponentService) | |||
| context.getCoreService(ComponentService.class); | |||
| componentService.addLibPath(libraryId, url); | |||
| @@ -148,7 +148,7 @@ public class LoadLib extends AbstractTask { | |||
| * loaded. | |||
| */ | |||
| public void execute() throws ExecutionException { | |||
| AntContext context = getContext(); | |||
| AntContext context = getAntContext(); | |||
| ComponentService componentService = (ComponentService) | |||
| context.getCoreService(ComponentService.class); | |||
| componentService.loadLib(url.toString(), importAll); | |||
| @@ -138,6 +138,7 @@ public class Builder { | |||
| files.add(new File(TASKDEFS_ROOT, "LogStreamHandler.java")); | |||
| files.add(new File(TASKDEFS_ROOT, "LogOutputStream.java")); | |||
| files.add(new File(TASKDEFS_ROOT, "condition/Os.java")); | |||
| files.add(new File(TASKDEFS_ROOT, "condition/Contains.java")); | |||
| files.add(new File(TASKDEFS_ROOT, "condition/Condition.java")); | |||
| files.add(new File(TASKDEFS_ROOT, "Available.java")); | |||
| files.add(new File(TASKDEFS_ROOT, "Mkdir.java")); | |||
| @@ -54,50 +54,73 @@ | |||
| package org.apache.ant.cli; | |||
| import java.io.PrintStream; | |||
| import org.apache.ant.common.model.BuildElement; | |||
| import org.apache.ant.common.model.Target; | |||
| import org.apache.ant.common.antlib.ExecutionComponent; | |||
| import org.apache.ant.common.antlib.Task; | |||
| import org.apache.ant.common.event.BuildEvent; | |||
| import org.apache.ant.common.event.MessageLevel; | |||
| import org.apache.ant.common.model.Target; | |||
| import org.apache.ant.common.util.AntException; | |||
| import org.apache.ant.common.util.Location; | |||
| import org.apache.ant.common.event.MessageLevel; | |||
| /** | |||
| * Writes build event to a PrintStream. Currently, it only writes which | |||
| * targets are being executed, and any messages that get logged. | |||
| * Writes build event to a PrintStream. Currently, it only writes which | |||
| * targets are being executed, and any messages that get logged. | |||
| * | |||
| * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
| * @created 15 January 2002 | |||
| * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
| * @created 15 January 2002 | |||
| */ | |||
| public class DefaultLogger implements BuildLogger { | |||
| /** The stream where output should be written */ | |||
| /** Standard field separator */ | |||
| private static String lSep = System.getProperty("line.separator"); | |||
| /** spacing to allow for task tags */ | |||
| private static final int LEFT_COLUMN_SIZE = 12; | |||
| /** The stream where output should be written */ | |||
| private PrintStream out; | |||
| /** The stream to where errors should be written */ | |||
| /** The stream to where errors should be written */ | |||
| private PrintStream err; | |||
| /** The level of messages which should be let through */ | |||
| /** The level of messages which should be let through */ | |||
| private int messageOutputLevel = MessageLevel.MSG_ERR; | |||
| /** Controls whether adornments are added */ | |||
| /** Controls whether adornments are added */ | |||
| private boolean emacsMode = false; | |||
| /** The time at which the build started */ | |||
| /** The time at which the build started */ | |||
| private long startTime = System.currentTimeMillis(); | |||
| /** Standard field separator */ | |||
| private static String lSep = System.getProperty("line.separator"); | |||
| /** spacing to allow for task tags */ | |||
| private static final int LEFT_COLUMN_SIZE = 12; | |||
| /** | |||
| * Format the time into something readable | |||
| * | |||
| * @param millis Java millis value | |||
| * @return the formatted time | |||
| */ | |||
| protected static String formatTime(long millis) { | |||
| long seconds = millis / 1000; | |||
| long minutes = seconds / 60; | |||
| if (minutes > 0) { | |||
| return Long.toString(minutes) + " minute" | |||
| + (minutes == 1 ? " " : "s ") | |||
| + Long.toString(seconds % 60) + " second" | |||
| + (seconds % 60 == 1 ? "" : "s"); | |||
| } else { | |||
| return Long.toString(seconds) + " second" | |||
| + (seconds % 60 == 1 ? "" : "s"); | |||
| } | |||
| } | |||
| /** | |||
| * Set the messageOutputLevel this logger is to respond to. Only | |||
| * messages with a message level lower than or equal to the given level | |||
| * are output to the log. <P> | |||
| * Set the messageOutputLevel this logger is to respond to. Only | |||
| * messages with a message level lower than or equal to the given level | |||
| * are output to the log. <P> | |||
| * | |||
| * Constants for the message levels are in Project.java. The order of | |||
| * the levels, from least to most verbose, is MSG_ERR, MSG_WARN, | |||
| * MSG_INFO, MSG_VERBOSE, MSG_DEBUG. The default message level for | |||
| * DefaultLogger is Project.MSG_ERR. | |||
| * Constants for the message levels are in Project.java. The order of | |||
| * the levels, from least to most verbose, is MSG_ERR, MSG_WARN, | |||
| * MSG_INFO, MSG_VERBOSE, MSG_DEBUG. The default message level for | |||
| * DefaultLogger is Project.MSG_ERR. | |||
| * | |||
| * @param level the logging level for the logger. | |||
| * @param level the logging level for the logger. | |||
| */ | |||
| public void setMessageOutputLevel(int level) { | |||
| this.messageOutputLevel = level; | |||
| @@ -105,28 +128,27 @@ public class DefaultLogger implements BuildLogger { | |||
| /** | |||
| * Set the output stream to which this logger is to send its output. | |||
| * Set the output stream to which this logger is to send its output. | |||
| * | |||
| * @param output the output stream for the logger. | |||
| * @param output the output stream for the logger. | |||
| */ | |||
| public void setOutputPrintStream(PrintStream output) { | |||
| this.out = output; | |||
| } | |||
| /** | |||
| * Set the output stream to which this logger is to send error | |||
| * messages. | |||
| * Set the output stream to which this logger is to send error messages. | |||
| * | |||
| * @param err the error stream for the logger. | |||
| * @param err the error stream for the logger. | |||
| */ | |||
| public void setErrorPrintStream(PrintStream err) { | |||
| this.err = err; | |||
| } | |||
| /** | |||
| * Set this logger to produce emacs (and other editor) friendly output. | |||
| * Set this logger to produce emacs (and other editor) friendly output. | |||
| * | |||
| * @param emacsMode true if output is to be unadorned so that emacs and | |||
| * @param emacsMode true if output is to be unadorned so that emacs and | |||
| * other editors can parse files names, etc. | |||
| */ | |||
| public void setEmacsMode(boolean emacsMode) { | |||
| @@ -134,9 +156,9 @@ public class DefaultLogger implements BuildLogger { | |||
| } | |||
| /** | |||
| * Report an exception | |||
| * Report an exception | |||
| * | |||
| * @param t The exception to be reported. | |||
| * @param t The exception to be reported. | |||
| */ | |||
| public void reportException(Throwable t) { | |||
| if (t instanceof AntException) { | |||
| @@ -161,18 +183,18 @@ public class DefaultLogger implements BuildLogger { | |||
| } | |||
| /** | |||
| * Description of the Method | |||
| * Description of the Method | |||
| * | |||
| * @param event Description of Parameter | |||
| * @param event Description of Parameter | |||
| */ | |||
| public void buildStarted(BuildEvent event) { | |||
| startTime = System.currentTimeMillis(); | |||
| } | |||
| /** | |||
| * Description of the Method | |||
| * Description of the Method | |||
| * | |||
| * @param event Description of Parameter | |||
| * @param event Description of Parameter | |||
| */ | |||
| public void buildFinished(BuildEvent event) { | |||
| Throwable cause = event.getCause(); | |||
| @@ -190,9 +212,9 @@ public class DefaultLogger implements BuildLogger { | |||
| } | |||
| /** | |||
| * Description of the Method | |||
| * Description of the Method | |||
| * | |||
| * @param event Description of Parameter | |||
| * @param event Description of Parameter | |||
| */ | |||
| public void targetStarted(BuildEvent event) { | |||
| if (MessageLevel.MSG_INFO <= messageOutputLevel) { | |||
| @@ -202,33 +224,33 @@ public class DefaultLogger implements BuildLogger { | |||
| } | |||
| /** | |||
| * Description of the Method | |||
| * Description of the Method | |||
| * | |||
| * @param event Description of Parameter | |||
| * @param event Description of Parameter | |||
| */ | |||
| public void targetFinished(BuildEvent event) { | |||
| } | |||
| /** | |||
| * Description of the Method | |||
| * Description of the Method | |||
| * | |||
| * @param event Description of Parameter | |||
| * @param event Description of Parameter | |||
| */ | |||
| public void taskStarted(BuildEvent event) { | |||
| } | |||
| /** | |||
| * Description of the Method | |||
| * Description of the Method | |||
| * | |||
| * @param event Description of Parameter | |||
| * @param event Description of Parameter | |||
| */ | |||
| public void taskFinished(BuildEvent event) { | |||
| } | |||
| /** | |||
| * Description of the Method | |||
| * Description of the Method | |||
| * | |||
| * @param event Description of Parameter | |||
| * @param event Description of Parameter | |||
| */ | |||
| public void messageLogged(BuildEvent event) { | |||
| PrintStream logTo | |||
| @@ -236,20 +258,26 @@ public class DefaultLogger implements BuildLogger { | |||
| // Filter out messages based on priority | |||
| if (event.getPriority() <= messageOutputLevel) { | |||
| if (event.getModelElement() instanceof BuildElement) { | |||
| // Print out the name of the task if we're in one | |||
| BuildElement buildElement | |||
| = (BuildElement)event.getModelElement(); | |||
| String name = buildElement.getType(); | |||
| String name = null; | |||
| Object source = event.getSource(); | |||
| if (source instanceof Task) { | |||
| name = ((Task)source).getTaskName(); | |||
| } | |||
| if (name == null && source instanceof ExecutionComponent) { | |||
| name = ((ExecutionComponent)source).getComponentType(); | |||
| } | |||
| if (name != null) { | |||
| // Print out the name of the task if we're in one | |||
| if (!emacsMode) { | |||
| String msg = "[" + name + "] "; | |||
| int indentSize = LEFT_COLUMN_SIZE - msg.length(); | |||
| String tag = "[" + name + "] "; | |||
| int indentSize = LEFT_COLUMN_SIZE - tag.length(); | |||
| for (int i = 0; i < indentSize; i++) { | |||
| logTo.print(" "); | |||
| } | |||
| logTo.print(msg); | |||
| logTo.print(tag); | |||
| } | |||
| } | |||
| @@ -257,27 +285,5 @@ public class DefaultLogger implements BuildLogger { | |||
| logTo.println(event.getMessage()); | |||
| } | |||
| } | |||
| /** | |||
| * Format the time into something readable | |||
| * | |||
| * @param millis Java millis value | |||
| * @return the formatted time | |||
| */ | |||
| protected static String formatTime(long millis) { | |||
| long seconds = millis / 1000; | |||
| long minutes = seconds / 60; | |||
| if (minutes > 0) { | |||
| return Long.toString(minutes) + " minute" | |||
| + (minutes == 1 ? " " : "s ") | |||
| + Long.toString(seconds % 60) + " second" | |||
| + (seconds % 60 == 1 ? "" : "s"); | |||
| } else { | |||
| return Long.toString(seconds) + " second" | |||
| + (seconds % 60 == 1 ? "" : "s"); | |||
| } | |||
| } | |||
| } | |||
| @@ -65,15 +65,43 @@ public abstract class AbstractComponent implements ExecutionComponent { | |||
| /** The components's context */ | |||
| private AntContext context; | |||
| /** | |||
| * the type of the component. The type is the name of the component in | |||
| * the build file. This may be different from the name under which this | |||
| * componenent is known in its library due to aliasing | |||
| */ | |||
| private String componentType; | |||
| /** | |||
| * Get this component's context | |||
| * | |||
| * @return the component context | |||
| */ | |||
| public AntContext getAntContext() { | |||
| return context; | |||
| } | |||
| /** | |||
| * Gets the componentType of the AbstractComponent | |||
| * | |||
| * @return the componentType value | |||
| */ | |||
| public String getComponentType() { | |||
| return componentType; | |||
| } | |||
| /** | |||
| * Initialise the component. The component may use the AntContext to | |||
| * request services from the Ant core. | |||
| * | |||
| * @param context the component's context | |||
| * @param componentType the type of the component | |||
| * @exception ExecutionException if initialisation fails | |||
| */ | |||
| public void init(AntContext context) throws ExecutionException { | |||
| public void init(AntContext context, String componentType) | |||
| throws ExecutionException { | |||
| this.context = context; | |||
| this.componentType = componentType; | |||
| } | |||
| /** | |||
| @@ -87,15 +115,6 @@ public abstract class AbstractComponent implements ExecutionComponent { | |||
| // no validation by default | |||
| } | |||
| /** | |||
| * Get this component's context | |||
| * | |||
| * @return the component context | |||
| */ | |||
| protected AntContext getContext() { | |||
| return context; | |||
| } | |||
| /** | |||
| * Short cut to get a core service instance | |||
| * | |||
| @@ -60,9 +60,26 @@ package org.apache.ant.common.antlib; | |||
| * @created 16 January 2002 | |||
| */ | |||
| public abstract class AbstractTask extends AbstractComponent implements Task { | |||
| /** Task is about to be cleaned up */ | |||
| public void destroy() { | |||
| // do nothing here | |||
| /** The name of this task. */ | |||
| private String taskName; | |||
| /** | |||
| * Sets the taskName of the AbstractTask | |||
| * | |||
| * @param taskName the new taskName value | |||
| */ | |||
| public final void setTaskName(String taskName) { | |||
| this.taskName = taskName; | |||
| } | |||
| /** | |||
| * Gets the taskName of the AbstractTask | |||
| * | |||
| * @return the taskName value | |||
| */ | |||
| public final String getTaskName() { | |||
| return taskName; | |||
| } | |||
| } | |||
| @@ -53,9 +53,8 @@ | |||
| */ | |||
| package org.apache.ant.common.antlib; | |||
| import java.io.File; | |||
| import org.apache.ant.common.model.ModelElement; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| import org.apache.ant.common.util.Location; | |||
| /** | |||
| * The AntContext is the interface through which the Ant container and the | |||
| @@ -95,10 +94,10 @@ public interface AntContext { | |||
| File getBaseDir(); | |||
| /** | |||
| * Get the model element associated with this context | |||
| * Gets the location associated witj the AntContext | |||
| * | |||
| * @return the modelElement associated with this context | |||
| * @return the location | |||
| */ | |||
| ModelElement getModelElement(); | |||
| Location getLocation(); | |||
| } | |||
| @@ -64,21 +64,6 @@ import org.apache.ant.common.util.ExecutionException; | |||
| * @created 31 January 2002 | |||
| */ | |||
| public interface AntLibFactory { | |||
| /** | |||
| * Create an instance of the given type class | |||
| * | |||
| * @param typeClass the class for which an instance is required | |||
| * @param localName the name within the library under which the type is | |||
| * defined | |||
| * @return an instance of the required class | |||
| * @exception InstantiationException if the class cannot be instantiated | |||
| * @exception IllegalAccessException if the instance cannot be accessed | |||
| * @exception ExecutionException if there is a problem creating the type | |||
| */ | |||
| Object createTypeInstance(Class typeClass, String localName) | |||
| throws InstantiationException, IllegalAccessException, | |||
| ExecutionException; | |||
| /** | |||
| * Initialise the factory | |||
| * | |||
| @@ -88,9 +73,9 @@ public interface AntLibFactory { | |||
| void init(AntContext context) throws ExecutionException; | |||
| /** | |||
| * Create an instance of the given task class | |||
| * Create an instance of the given component class | |||
| * | |||
| * @param taskClass the class for which an instance is required | |||
| * @param componentClass the class for which an instance is required | |||
| * @param localName the name within the library under which the task is | |||
| * defined | |||
| * @return an instance of the required class | |||
| @@ -98,7 +83,7 @@ public interface AntLibFactory { | |||
| * @exception IllegalAccessException if the instance cannot be accessed | |||
| * @exception ExecutionException if there is a problem creating the task | |||
| */ | |||
| Object createTaskInstance(Class taskClass, String localName) | |||
| Object createComponent(Class componentClass, String localName) | |||
| throws InstantiationException, IllegalAccessException, | |||
| ExecutionException; | |||
| @@ -67,17 +67,34 @@ public interface ExecutionComponent { | |||
| * services from the Ant core. | |||
| * | |||
| * @param context the Task's context | |||
| * @param componentType the type of the component | |||
| * @exception ExecutionException if the component cannot be initialised | |||
| */ | |||
| void init(AntContext context) throws ExecutionException; | |||
| void init(AntContext context, String componentType) | |||
| throws ExecutionException; | |||
| /** | |||
| * Validate the component. This is called after the element has been | |||
| * configured from its build model. The element may perform validation | |||
| * of its configuration | |||
| * | |||
| * @exception ExecutionException if the component is not validly configured | |||
| * @exception ExecutionException if the component is not validly | |||
| * configured | |||
| */ | |||
| void validateComponent() throws ExecutionException; | |||
| /** | |||
| * Get the AntContext associated with this component | |||
| * | |||
| * @return the component's context | |||
| */ | |||
| AntContext getAntContext(); | |||
| /** | |||
| * Get the type of the component in the build file | |||
| * | |||
| * @return the type of the component | |||
| */ | |||
| String getComponentType(); | |||
| } | |||
| @@ -66,9 +66,9 @@ public class StandardLibFactory implements AntLibFactory { | |||
| private AntContext context; | |||
| /** | |||
| * Create an instance of the given task class | |||
| * Create an instance of the given component class | |||
| * | |||
| * @param taskClass the class for which an instance is required | |||
| * @param componentClass the class for which an instance is required | |||
| * @param localName the name within the library under which the task is | |||
| * defined | |||
| * @return an instance of the required class | |||
| @@ -76,27 +76,10 @@ public class StandardLibFactory implements AntLibFactory { | |||
| * @exception IllegalAccessException if the instance cannot be accessed | |||
| * @exception ExecutionException if there is a problem creating the task | |||
| */ | |||
| public Object createTaskInstance(Class taskClass, String localName) | |||
| public Object createComponent(Class componentClass, String localName) | |||
| throws InstantiationException, IllegalAccessException, | |||
| ExecutionException { | |||
| return taskClass.newInstance(); | |||
| } | |||
| /** | |||
| * Create an instance of the given type class | |||
| * | |||
| * @param typeClass the class for which an instance is required | |||
| * @param localName the name within the library under which the type is | |||
| * defined, if any. | |||
| * @return an instance of the required class | |||
| * @exception InstantiationException if the class cannot be instantiated | |||
| * @exception IllegalAccessException if the instance cannot be accessed | |||
| * @exception ExecutionException if there is a problem creating the type | |||
| */ | |||
| public Object createTypeInstance(Class typeClass, String localName) | |||
| throws InstantiationException, IllegalAccessException, | |||
| ExecutionException { | |||
| return typeClass.newInstance(); | |||
| return componentClass.newInstance(); | |||
| } | |||
| /** | |||
| @@ -68,7 +68,18 @@ public interface Task extends ExecutionComponent { | |||
| */ | |||
| void execute() throws ExecutionException; | |||
| /** Task is about to be cleaned up */ | |||
| void destroy(); | |||
| /** | |||
| * Sets the taskName of the Task | |||
| * | |||
| * @param name the new taskName value | |||
| */ | |||
| void setTaskName(String name); | |||
| /** | |||
| * Gets the taskName of the Task | |||
| * | |||
| * @return the taskName value | |||
| */ | |||
| String getTaskName(); | |||
| } | |||
| @@ -54,7 +54,6 @@ | |||
| package org.apache.ant.common.event; | |||
| import java.util.EventObject; | |||
| import org.apache.ant.common.model.ModelElement; | |||
| /** | |||
| * A BuildEvent indicates the occurence of a significant event in the build. | |||
| @@ -170,18 +169,5 @@ public class BuildEvent extends EventObject { | |||
| return cause; | |||
| } | |||
| /** | |||
| * Gets the modelElement of the BuildEvent | |||
| * | |||
| * @return the model element this event is associated with | |||
| */ | |||
| public ModelElement getModelElement() { | |||
| Object source = getSource(); | |||
| if (source instanceof ModelElement) { | |||
| return (ModelElement)getSource(); | |||
| } | |||
| return null; | |||
| } | |||
| } | |||
| @@ -158,5 +158,18 @@ public interface ComponentService { | |||
| */ | |||
| void importFrameComponent(String relativeName, String alias) | |||
| throws ExecutionException; | |||
| /** | |||
| * Create a component. The component will have a context but will not be | |||
| * configured. It should be configured using the appropriate set methods | |||
| * and then validated before being used. | |||
| * | |||
| * @param componentName the name of the component | |||
| * @return the created component. The return type of this method depends | |||
| * on the component type. | |||
| * @exception ExecutionException if the component cannot be created | |||
| */ | |||
| Object createComponent(String componentName) throws ExecutionException; | |||
| } | |||
| @@ -55,6 +55,7 @@ package org.apache.ant.common.service; | |||
| import java.io.File; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import org.apache.ant.common.antlib.Task; | |||
| import org.apache.ant.common.model.Project; | |||
| import org.apache.ant.common.util.ExecutionException; | |||
| @@ -97,5 +98,13 @@ public interface ExecService { | |||
| void callTarget(Map properties, List targets) | |||
| throws ExecutionException; | |||
| /** | |||
| * execute a task. The task should have already been initialised by | |||
| * the core | |||
| * | |||
| * @param task the task to be executed. | |||
| * @exception ExecutionException if there is a problem in execution. | |||
| */ | |||
| void executeTask(Task task) throws ExecutionException; | |||
| } | |||
| @@ -267,5 +267,20 @@ public class LoaderUtils { | |||
| } | |||
| return urls; | |||
| } | |||
| /** | |||
| * Set the context loader of the current thread and returns the existing | |||
| * classloader | |||
| * | |||
| * @param newLoader the new context loader | |||
| * @return the old context loader | |||
| */ | |||
| public static ClassLoader setContextLoader(ClassLoader newLoader) { | |||
| Thread thread = Thread.currentThread(); | |||
| ClassLoader currentLoader = thread.getContextClassLoader(); | |||
| thread.setContextClassLoader(newLoader); | |||
| return currentLoader; | |||
| } | |||
| } | |||