git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271710 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -6,21 +6,24 @@ | |||||
| <property name='build' location='build' /> | <property name='build' location='build' /> | ||||
| <property name='dist' location='dist' /> | <property name='dist' location='dist' /> | ||||
| <property name='classes' location='${build}/classes' /> | <property name='classes' location='${build}/classes' /> | ||||
| <property name='testcases' location='src/testcases' /> | |||||
| <property name="debug" value="true" /> | <property name="debug" value="true" /> | ||||
| <property name="deprecation" value="false" /> | <property name="deprecation" value="false" /> | ||||
| <property name="optimize" value="true" /> | <property name="optimize" value="true" /> | ||||
| <target name='init'> | <target name='init'> | ||||
| <ant target='build' dir='${orig}' inheritAll='false' /> | <ant target='build' dir='${orig}' inheritAll='false' /> | ||||
| <mkdir dir='${classes}' /> | <mkdir dir='${classes}' /> | ||||
| <copy toDir='${classes}' preservelastmodified='true' > | <copy toDir='${classes}' preservelastmodified='true' > | ||||
| <fileset dir='${orig-classes}'> | <fileset dir='${orig-classes}'> | ||||
| <include name='**' /> | <include name='**' /> | ||||
| <exclude name='org/apache/tools/ant/Project.class' /> | |||||
| <exclude name='org/apache/tools/ant/TaskAdapter.class' /> | |||||
| <exclude name='org/apache/tools/ant/taskdefs/Ant.class' /> | |||||
| <exclude name='org/apache/tools/ant/Project.class' /> | |||||
| <exclude name='org/apache/tools/ant/ProjectHelper.class' /> | |||||
| <exclude name='org/apache/tools/ant/IntrospectionHelper.class' /> | |||||
| <exclude name='org/apache/tools/ant/TaskAdapter.class' /> | |||||
| <exclude name='org/apache/tools/ant/taskdefs/Ant.class' /> | |||||
| </fileset> | </fileset> | ||||
| </copy> | </copy> | ||||
| </target> | </target> | ||||
| @@ -39,6 +42,32 @@ | |||||
| <property name="build.dir" value="${build}"/> | <property name="build.dir" value="${build}"/> | ||||
| <property name="dist.dir" value="${dist}"/> | <property name="dist.dir" value="${dist}"/> | ||||
| </ant> | </ant> | ||||
| <!-- | |||||
| Rejar things to use lib descriptors | |||||
| It needs to work with the original ANT processor | |||||
| --> | |||||
| <path id="newtasks"> | |||||
| <pathelement location="${classes}" /> | |||||
| </path> | |||||
| <taskdef name="antjar" classname="org.apache.tools.ant.taskdefs.Antjar" | |||||
| classpathref="newtasks" /> | |||||
| <taskdef name="antlib" classname="org.apache.tools.ant.taskdefs.Antlib" | |||||
| classpathref="newtasks" /> | |||||
| <mkdir dir='${dist}/autolib' /> | |||||
| <antjar antxml="src/main/org/apache/tools/ant/opt-antlib.xml" | |||||
| destfile="${dist}/autolib/optional.jar" > | |||||
| <zipfileset src="${dist}/lib/optional.jar" > | |||||
| <include name="**/*" /> | |||||
| </zipfileset> | |||||
| </antjar> | |||||
| <antjar antxml="src/main/org/apache/tools/ant/antlib.xml" | |||||
| destfile="${dist}/lib/newant.jar" > | |||||
| <zipfileset src="${dist}/lib/ant.jar" > | |||||
| <include name="**/*" /> | |||||
| </zipfileset> | |||||
| </antjar> | |||||
| <delete file="${dist}/lib/optional.jar" /> | |||||
| <move file="${dist}/lib/newant.jar" tofile="${dist}/lib/ant.jar"/> | |||||
| </target> | </target> | ||||
| <target name='compile'> | <target name='compile'> | ||||
| @@ -48,6 +77,11 @@ | |||||
| optimize="${optimize}"> | optimize="${optimize}"> | ||||
| <include name='**/*.java'/> | <include name='**/*.java'/> | ||||
| </javac> | </javac> | ||||
| <copy toDir='${classes}' preservelastmodified='true' > | |||||
| <fileset dir='src/main'> | |||||
| <include name='**/*.xml' /> | |||||
| </fileset> | |||||
| </copy> | |||||
| </target> | </target> | ||||
| <target name='clean'> | <target name='clean'> | ||||
| @@ -56,7 +90,7 @@ | |||||
| <target name='test'> | <target name='test'> | ||||
| <ant dir='${testcases}' inheritAll='false'/> | <ant dir='${testcases}' inheritAll='false'/> | ||||
| <ant dir='${testcases}' | |||||
| <ant dir='${testcases}' | |||||
| antfile='${testcases}/case.xml' inheritAll='false'/> | antfile='${testcases}/case.xml' inheritAll='false'/> | ||||
| </target> | </target> | ||||
| @@ -114,7 +114,7 @@ public class ProjectHelper { | |||||
| private void parse() throws BuildException { | private void parse() throws BuildException { | ||||
| FileInputStream inputStream = null; | FileInputStream inputStream = null; | ||||
| InputSource inputSource = null; | InputSource inputSource = null; | ||||
| try { | try { | ||||
| SAXParser saxParser = getParserFactory().newSAXParser(); | SAXParser saxParser = getParserFactory().newSAXParser(); | ||||
| parser = saxParser.getParser(); | parser = saxParser.getParser(); | ||||
| @@ -123,7 +123,7 @@ public class ProjectHelper { | |||||
| for (int index = uri.indexOf('#'); index != -1; index = uri.indexOf('#')) { | for (int index = uri.indexOf('#'); index != -1; index = uri.indexOf('#')) { | ||||
| uri = uri.substring(0, index) + "%23" + uri.substring(index+1); | uri = uri.substring(0, index) + "%23" + uri.substring(index+1); | ||||
| } | } | ||||
| inputStream = new FileInputStream(buildFile); | inputStream = new FileInputStream(buildFile); | ||||
| inputSource = new InputSource(inputStream); | inputSource = new InputSource(inputStream); | ||||
| inputSource.setSystemId(uri); | inputSource.setSystemId(uri); | ||||
| @@ -145,7 +145,7 @@ public class ProjectHelper { | |||||
| } | } | ||||
| throw be; | throw be; | ||||
| } | } | ||||
| throw new BuildException(exc.getMessage(), t, location); | throw new BuildException(exc.getMessage(), t, location); | ||||
| } | } | ||||
| catch(SAXException exc) { | catch(SAXException exc) { | ||||
| @@ -231,20 +231,20 @@ public class ProjectHelper { | |||||
| */ | */ | ||||
| public InputSource resolveEntity(String publicId, | public InputSource resolveEntity(String publicId, | ||||
| String systemId) { | String systemId) { | ||||
| project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE); | project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE); | ||||
| if (systemId.startsWith("file:")) { | if (systemId.startsWith("file:")) { | ||||
| String path = systemId.substring(5); | String path = systemId.substring(5); | ||||
| int index = path.indexOf("file:"); | int index = path.indexOf("file:"); | ||||
| // we only have to handle these for backward compatibility | // we only have to handle these for backward compatibility | ||||
| // since they are in the FAQ. | // since they are in the FAQ. | ||||
| while (index != -1) { | while (index != -1) { | ||||
| path = path.substring(0, index) + path.substring(index + 5); | path = path.substring(0, index) + path.substring(index + 5); | ||||
| index = path.indexOf("file:"); | index = path.indexOf("file:"); | ||||
| } | } | ||||
| String entitySystemId = path; | String entitySystemId = path; | ||||
| index = path.indexOf("%23"); | index = path.indexOf("%23"); | ||||
| // convert these to # | // convert these to # | ||||
| @@ -257,13 +257,13 @@ public class ProjectHelper { | |||||
| if (!file.isAbsolute()) { | if (!file.isAbsolute()) { | ||||
| file = new File(buildFileParent, path); | file = new File(buildFileParent, path); | ||||
| } | } | ||||
| try { | try { | ||||
| InputSource inputSource = new InputSource(new FileInputStream(file)); | InputSource inputSource = new InputSource(new FileInputStream(file)); | ||||
| inputSource.setSystemId("file:" + entitySystemId); | inputSource.setSystemId("file:" + entitySystemId); | ||||
| return inputSource; | return inputSource; | ||||
| } catch (FileNotFoundException fne) { | } catch (FileNotFoundException fne) { | ||||
| project.log(file.getAbsolutePath()+" could not be found", | |||||
| project.log(file.getAbsolutePath()+" could not be found", | |||||
| Project.MSG_WARN); | Project.MSG_WARN); | ||||
| } | } | ||||
| } | } | ||||
| @@ -316,10 +316,10 @@ public class ProjectHelper { | |||||
| } | } | ||||
| if (def == null) { | if (def == null) { | ||||
| throw new SAXParseException("The default attribute of project is required", | |||||
| throw new SAXParseException("The default attribute of project is required", | |||||
| locator); | locator); | ||||
| } | } | ||||
| project.setDefaultTarget(def); | project.setDefaultTarget(def); | ||||
| @@ -360,6 +360,8 @@ public class ProjectHelper { | |||||
| handleTopTask(name, attrs); | handleTopTask(name, attrs); | ||||
| } else if (name.equals("target")) { | } else if (name.equals("target")) { | ||||
| handleTarget(name, attrs); | handleTarget(name, attrs); | ||||
| } else if (name.equals("description")) { | |||||
| handleDescription(name, attrs); | |||||
| } else if (project.isDefinedOnRole(Project.DATATYPE_ROLE, name)) { | } else if (project.isDefinedOnRole(Project.DATATYPE_ROLE, name)) { | ||||
| handleTopTask(name, attrs); | handleTopTask(name, attrs); | ||||
| } else { | } else { | ||||
| @@ -367,9 +369,9 @@ public class ProjectHelper { | |||||
| } | } | ||||
| } | } | ||||
| private void handleTopTask(String name, AttributeList attrs) | |||||
| throws SAXParseException { | |||||
| InmediateTarget target = new InmediateTarget(name); | |||||
| private void handleTopTask(String name, AttributeList attrs) | |||||
| throws SAXParseException { | |||||
| InmediateTarget target = new InmediateTarget(name); | |||||
| (new TaskHandler(this, target, null, target)).init(name, attrs); | (new TaskHandler(this, target, null, target)).init(name, attrs); | ||||
| } | } | ||||
| @@ -377,6 +379,10 @@ public class ProjectHelper { | |||||
| new TargetHandler(this).init(tag, attrs); | new TargetHandler(this).init(tag, attrs); | ||||
| } | } | ||||
| private void handleDescription(String tag, AttributeList attrs) throws SAXParseException { | |||||
| new DescriptionHandler(this).init(tag, attrs); | |||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -441,8 +447,13 @@ public class ProjectHelper { | |||||
| } | } | ||||
| public void startElement(String name, AttributeList attrs) throws SAXParseException { | public void startElement(String name, AttributeList attrs) throws SAXParseException { | ||||
| new TaskHandler(this, target, null, target).init(name, attrs); | |||||
| } | |||||
| if (name.equals("description")) { | |||||
| new DescriptionHandler(this).init(name, attrs); | |||||
| } | |||||
| else { | |||||
| new TaskHandler(this, target, null, target).init(name, attrs); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -466,7 +477,7 @@ public class ProjectHelper { | |||||
| try { | try { | ||||
| task = (Task)project.createInRole(container, tag); | task = (Task)project.createInRole(container, tag); | ||||
| } catch (BuildException e) { | } catch (BuildException e) { | ||||
| // swallow here, will be thrown again in | |||||
| // swallow here, will be thrown again in | |||||
| // UnknownElement.maybeConfigure if the problem persists. | // UnknownElement.maybeConfigure if the problem persists. | ||||
| } | } | ||||
| @@ -475,21 +486,21 @@ public class ProjectHelper { | |||||
| task.setProject(project); | task.setProject(project); | ||||
| task.setTaskType(tag); | task.setTaskType(tag); | ||||
| task.setTaskName(tag); | task.setTaskName(tag); | ||||
| container.addTask(task); | |||||
| container.addTask(task); | |||||
| } | } | ||||
| task.setLocation(new Location(buildFile.toString(), | |||||
| locator.getLineNumber(), | |||||
| locator.getColumnNumber())); | |||||
| task.setLocation(new Location(buildFile.toString(), | |||||
| locator.getLineNumber(), | |||||
| locator.getColumnNumber())); | |||||
| configureId(task, attrs); | configureId(task, attrs); | ||||
| task.setOwningTarget(target); | |||||
| task.init(); | |||||
| wrapper = task.getRuntimeConfigurableWrapper(); | |||||
| wrapper.setAttributes(attrs); | |||||
| if (parentWrapper != null) { | |||||
| parentWrapper.addChild(wrapper); | |||||
| } | |||||
| task.setOwningTarget(target); | |||||
| task.init(); | |||||
| wrapper = task.getRuntimeConfigurableWrapper(); | |||||
| wrapper.setAttributes(attrs); | |||||
| if (parentWrapper != null) { | |||||
| parentWrapper.addChild(wrapper); | |||||
| } | |||||
| } | } | ||||
| protected void finished() { | protected void finished() { | ||||
| @@ -531,7 +542,7 @@ public class ProjectHelper { | |||||
| private RuntimeConfigurable childWrapper = null; | private RuntimeConfigurable childWrapper = null; | ||||
| private Target target; | private Target target; | ||||
| public NestedElementHandler(DocumentHandler parentHandler, | |||||
| public NestedElementHandler(DocumentHandler parentHandler, | |||||
| Object parent, | Object parent, | ||||
| RuntimeConfigurable parentWrapper, | RuntimeConfigurable parentWrapper, | ||||
| Target target) { | Target target) { | ||||
| @@ -548,7 +559,7 @@ public class ProjectHelper { | |||||
| public void init(String propType, AttributeList attrs) throws SAXParseException { | public void init(String propType, AttributeList attrs) throws SAXParseException { | ||||
| Class parentClass = parent.getClass(); | Class parentClass = parent.getClass(); | ||||
| IntrospectionHelper ih = | |||||
| IntrospectionHelper ih = | |||||
| IntrospectionHelper.getHelper(parentClass); | IntrospectionHelper.getHelper(parentClass); | ||||
| try { | try { | ||||
| @@ -557,9 +568,9 @@ public class ProjectHelper { | |||||
| UnknownElement uc = new UnknownElement(elementName); | UnknownElement uc = new UnknownElement(elementName); | ||||
| uc.setProject(project); | uc.setProject(project); | ||||
| ((UnknownElement) parent).addChild(uc); | ((UnknownElement) parent).addChild(uc); | ||||
| // Set this parameters just in case is a Task | |||||
| uc.setTaskType(elementName); | |||||
| uc.setTaskName(elementName); | |||||
| // Set this parameters just in case is a Task | |||||
| uc.setTaskType(elementName); | |||||
| uc.setTaskName(elementName); | |||||
| child = uc; | child = uc; | ||||
| } else { | } else { | ||||
| child = ih.createElement(project, parent, elementName); | child = ih.createElement(project, parent, elementName); | ||||
| @@ -594,7 +605,7 @@ public class ProjectHelper { | |||||
| public void startElement(String name, AttributeList attrs) throws SAXParseException { | public void startElement(String name, AttributeList attrs) throws SAXParseException { | ||||
| if (child instanceof TaskContainer) { | if (child instanceof TaskContainer) { | ||||
| // taskcontainer nested element can contain other tasks - no other | |||||
| // taskcontainer nested element can contain other tasks - no other | |||||
| // nested elements possible | // nested elements possible | ||||
| new TaskHandler(this, (TaskContainer)child, childWrapper, target).init(name, attrs); | new TaskHandler(this, (TaskContainer)child, childWrapper, target).init(name, attrs); | ||||
| } | } | ||||
| @@ -604,39 +615,64 @@ public class ProjectHelper { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Handler to perform appropriate semantics for the special | |||||
| * <description> element on tasks. | |||||
| */ | |||||
| private class DescriptionHandler extends AbstractHandler { | |||||
| public DescriptionHandler(DocumentHandler parent) { | |||||
| super(parent); | |||||
| } | |||||
| public void init(String tag, AttributeList attrs) throws SAXParseException { | |||||
| if (attrs.getLength() > 0) { | |||||
| throw new SAXParseException("No attributes allowed on " + tag, locator); | |||||
| } | |||||
| } | |||||
| public void characters(char[] buf, int start, int end) throws SAXParseException { | |||||
| String desc = project.getDescription(); | |||||
| if (desc == null) { | |||||
| desc = ""; | |||||
| } | |||||
| project.setDescription(desc + new String(buf, start, end)); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Special target type for top level Tasks and Datatypes. | * Special target type for top level Tasks and Datatypes. | ||||
| * This will allow eliminating special cases. | * This will allow eliminating special cases. | ||||
| */ | */ | ||||
| private class InmediateTarget extends Target { | private class InmediateTarget extends Target { | ||||
| /** | |||||
| * Create a target for a top level task or datatype. | |||||
| * @param name the name of the task to be run on this target. | |||||
| */ | |||||
| InmediateTarget(String name) { | |||||
| super(); | |||||
| setProject(project); | |||||
| setName("Top level " + name); | |||||
| } | |||||
| /** | |||||
| * Create a target for a top level task or datatype. | |||||
| * @param name the name of the task to be run on this target. | |||||
| */ | |||||
| InmediateTarget(String name) { | |||||
| super(); | |||||
| setProject(project); | |||||
| setName("Top level " + name); | |||||
| } | |||||
| } | } | ||||
| public static void configure(Object target, AttributeList attrs, | |||||
| public static void configure(Object target, AttributeList attrs, | |||||
| Project project) throws BuildException { | Project project) throws BuildException { | ||||
| if( target instanceof RoleAdapter ) { | if( target instanceof RoleAdapter ) { | ||||
| target=((RoleAdapter)target).getProxy(); | target=((RoleAdapter)target).getProxy(); | ||||
| } | } | ||||
| IntrospectionHelper ih = | |||||
| IntrospectionHelper ih = | |||||
| IntrospectionHelper.getHelper(target.getClass()); | IntrospectionHelper.getHelper(target.getClass()); | ||||
| project.addBuildListener(ih); | project.addBuildListener(ih); | ||||
| for (int i = 0; i < attrs.getLength(); i++) { | for (int i = 0; i < attrs.getLength(); i++) { | ||||
| // reflect these into the target | // reflect these into the target | ||||
| String value=replaceProperties(project, attrs.getValue(i), | |||||
| String value=replaceProperties(project, attrs.getValue(i), | |||||
| project.getProperties() ); | project.getProperties() ); | ||||
| try { | try { | ||||
| ih.setAttribute(project, target, | |||||
| ih.setAttribute(project, target, | |||||
| attrs.getName(i).toLowerCase(Locale.US), value); | attrs.getName(i).toLowerCase(Locale.US), value); | ||||
| } catch (BuildException be) { | } catch (BuildException be) { | ||||
| @@ -674,7 +710,7 @@ public class ProjectHelper { | |||||
| } | } | ||||
| /** | /** | ||||
| * Stores a configured child element into its parent object | |||||
| * Stores a configured child element into its parent object | |||||
| */ | */ | ||||
| public static void storeChild(Project project, Object parent, Object child, String tag) { | public static void storeChild(Project project, Object parent, Object child, String tag) { | ||||
| IntrospectionHelper ih = IntrospectionHelper.getHelper(parent.getClass()); | IntrospectionHelper ih = IntrospectionHelper.getHelper(parent.getClass()); | ||||
| @@ -719,23 +755,23 @@ public class ProjectHelper { | |||||
| if (!keys.containsKey(propertyName)) { | if (!keys.containsKey(propertyName)) { | ||||
| project.log("Property ${" + propertyName + "} has not been set", Project.MSG_VERBOSE); | project.log("Property ${" + propertyName + "} has not been set", Project.MSG_VERBOSE); | ||||
| } | } | ||||
| fragment = (keys.containsKey(propertyName)) ? (String) keys.get(propertyName) | |||||
| : "${" + propertyName + "}"; | |||||
| fragment = (keys.containsKey(propertyName)) ? (String) keys.get(propertyName) | |||||
| : "${" + propertyName + "}"; | |||||
| } | } | ||||
| sb.append(fragment); | sb.append(fragment); | ||||
| } | |||||
| } | |||||
| return sb.toString(); | return sb.toString(); | ||||
| } | } | ||||
| /** | /** | ||||
| * This method will parse a string containing ${value} style | |||||
| * This method will parse a string containing ${value} style | |||||
| * property values into two lists. The first list is a collection | * property values into two lists. The first list is a collection | ||||
| * of text fragments, while the other is a set of string property names | * of text fragments, while the other is a set of string property names | ||||
| * null entries in the first list indicate a property reference from the | * null entries in the first list indicate a property reference from the | ||||
| * second list. | * second list. | ||||
| */ | */ | ||||
| public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs) | |||||
| public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs) | |||||
| throws BuildException { | throws BuildException { | ||||
| int prev = 0; | int prev = 0; | ||||
| int pos; | int pos; | ||||
| @@ -754,7 +790,7 @@ public class ProjectHelper { | |||||
| } else { | } else { | ||||
| int endName = value.indexOf('}', pos); | int endName = value.indexOf('}', pos); | ||||
| if (endName < 0) { | if (endName < 0) { | ||||
| throw new BuildException("Syntax error in property: " | |||||
| throw new BuildException("Syntax error in property: " | |||||
| + value ); | + value ); | ||||
| } | } | ||||
| String propertyName = value.substring(pos + 2, endName); | String propertyName = value.substring(pos + 2, endName); | ||||
| @@ -779,17 +815,17 @@ public class ProjectHelper { | |||||
| /** | /** | ||||
| * Scan AttributeList for the id attribute and maybe add a | * Scan AttributeList for the id attribute and maybe add a | ||||
| * reference to project. | |||||
| * reference to project. | |||||
| * | * | ||||
| * <p>Moved out of {@link #configure configure} to make it happen | * <p>Moved out of {@link #configure configure} to make it happen | ||||
| * at parser time.</p> | |||||
| * at parser time.</p> | |||||
| */ | */ | ||||
| private void configureId(Object target, AttributeList attr) { | private void configureId(Object target, AttributeList attr) { | ||||
| String id = attr.getValue("id"); | String id = attr.getValue("id"); | ||||
| if (id != null) { | if (id != null) { | ||||
| if( target instanceof RoleAdapter ) { | |||||
| ((RoleAdapter)target).setId(id); | |||||
| } | |||||
| if( target instanceof RoleAdapter ) { | |||||
| ((RoleAdapter)target).setId(id); | |||||
| } | |||||
| project.addReference(id, target); | project.addReference(id, target); | ||||
| } | } | ||||
| } | } | ||||
| @@ -55,6 +55,11 @@ package org.apache.tools.ant; | |||||
| public interface RoleAdapter { | public interface RoleAdapter { | ||||
| /** | |||||
| * Obtain the id in case it is needed. | |||||
| */ | |||||
| public void setId(String id); | |||||
| /** | /** | ||||
| * Set the object being adapted. | * Set the object being adapted. | ||||
| * @param o the object being adapted | * @param o the object being adapted | ||||
| @@ -54,6 +54,7 @@ | |||||
| package org.apache.tools.ant; | package org.apache.tools.ant; | ||||
| import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Constructor; | |||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
| import java.lang.reflect.Modifier; | import java.lang.reflect.Modifier; | ||||
| import java.util.*; | import java.util.*; | ||||
| @@ -64,7 +65,7 @@ public class SymbolTable { | |||||
| /** Parent symbol table */ | /** Parent symbol table */ | ||||
| private SymbolTable parentTable; | private SymbolTable parentTable; | ||||
| /** Project associated with this symbol table */ | /** Project associated with this symbol table */ | ||||
| private Project project; | private Project project; | ||||
| @@ -82,8 +83,8 @@ public class SymbolTable { | |||||
| /** | /** | ||||
| * Parameters for checking adapters. | * Parameters for checking adapters. | ||||
| */ | */ | ||||
| private static final Class[] CHECK_ADAPTER_PARAMS = | |||||
| new Class[]{Class.class, Project.class}; | |||||
| private static final Class[] CHECK_ADAPTER_PARAMS = | |||||
| new Class[]{Class.class, Project.class}; | |||||
| /** | /** | ||||
| * Create a top level Symbol table. | * Create a top level Symbol table. | ||||
| @@ -96,8 +97,8 @@ public class SymbolTable { | |||||
| * from that defined in the calling Project. | * from that defined in the calling Project. | ||||
| * @param p the calling project | * @param p the calling project | ||||
| */ | */ | ||||
| public SymbolTable(Project p) { | |||||
| parentTable = p.getSymbols(); | |||||
| public SymbolTable(SymbolTable st) { | |||||
| parentTable = st; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -105,7 +106,55 @@ public class SymbolTable { | |||||
| * @param p the project for this symbol table | * @param p the project for this symbol table | ||||
| */ | */ | ||||
| public void setProject(Project p) { | public void setProject(Project p) { | ||||
| this.project = p; | |||||
| this.project = p; | |||||
| } | |||||
| /** | |||||
| * Get the specified loader for the project. | |||||
| * @param name the name of the loader | |||||
| * @return the corresponding ANT classloader | |||||
| */ | |||||
| private AntClassLoader getLoader(String name) { | |||||
| AntClassLoader cl = (AntClassLoader) loaders.get(name); | |||||
| if (cl == null && parentTable != null) { | |||||
| return parentTable.getLoader(name); | |||||
| } | |||||
| return cl; | |||||
| } | |||||
| /** | |||||
| * Add the specified class-path to a loader. | |||||
| * If the loader is defined in an ancestor project then a new | |||||
| * classloader inheritin from the one already existing | |||||
| * will be created, otherwise the path willbe added to the existing | |||||
| * ClassLoader. | |||||
| * @param name the name of the loader to use. | |||||
| * @param clspath the path to be added to the classloader | |||||
| */ | |||||
| public ClassLoader addToLoader(String name, Path clspath) { | |||||
| // Find if the loader is already defined in the current project | |||||
| AntClassLoader cl = (AntClassLoader) loaders.get(name); | |||||
| if (cl == null) { | |||||
| // Is it inherited from the calling project | |||||
| if (parentTable != null) { | |||||
| cl = parentTable.getLoader(name); | |||||
| } | |||||
| cl = new AntClassLoader(cl, project, clspath, true); | |||||
| loaders.put(name, cl); | |||||
| } | |||||
| else { | |||||
| // Add additional path to the existing definition | |||||
| String[] pathElements = clspath.list(); | |||||
| for (int i = 0; i < pathElements.length; ++i) { | |||||
| try { | |||||
| cl.addPathElement(pathElements[i]); | |||||
| } | |||||
| catch (BuildException e) { | |||||
| // ignore path elements invalid relative to the project | |||||
| } | |||||
| } | |||||
| } | |||||
| return cl; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -115,9 +164,9 @@ public class SymbolTable { | |||||
| * @return an array of roles supported by the class | * @return an array of roles supported by the class | ||||
| */ | */ | ||||
| public String[] findRoles(final Class clz) { | public String[] findRoles(final Class clz) { | ||||
| Vector list = new Vector(); | |||||
| findRoles(clz, list); | |||||
| return (String[])list.toArray(new String[list.size()]); | |||||
| Vector list = new Vector(); | |||||
| findRoles(clz, list); | |||||
| return (String[])list.toArray(new String[list.size()]); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -126,27 +175,27 @@ public class SymbolTable { | |||||
| * @param list the roles collected up to this point | * @param list the roles collected up to this point | ||||
| */ | */ | ||||
| private void findRoles(final Class clz, Vector list) { | private void findRoles(final Class clz, Vector list) { | ||||
| for (Enumeration e = roles.keys(); e.hasMoreElements();) { | |||||
| String role = (String) e.nextElement(); | |||||
| if (((Role) roles.get(role)).isImplementedBy(clz)) { | |||||
| list.addElement(role); | |||||
| } | |||||
| } | |||||
| if (parentTable != null) findRoles(clz, list); | |||||
| for (Enumeration e = roles.keys(); e.hasMoreElements();) { | |||||
| String role = (String) e.nextElement(); | |||||
| if (((Role) roles.get(role)).isImplementedBy(clz)) { | |||||
| list.addElement(role); | |||||
| } | |||||
| } | |||||
| if (parentTable != null) parentTable.findRoles(clz, list); | |||||
| } | } | ||||
| /** | /** | ||||
| * Get the Role definition | * Get the Role definition | ||||
| * @param role the name of the role | * @param role the name of the role | ||||
| * @return the method used to support objects on this role | |||||
| * @return the Role description | |||||
| */ | */ | ||||
| public Role getRole(String role) { | public Role getRole(String role) { | ||||
| Role r = (Role) roles.get(role); | |||||
| if (r == null && parentTable != null) { | |||||
| return parentTable.getRole(role); | |||||
| } | |||||
| return r; | |||||
| Role r = (Role) roles.get(role); | |||||
| if (r == null && parentTable != null) { | |||||
| return parentTable.getRole(role); | |||||
| } | |||||
| return r; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -157,126 +206,19 @@ public class SymbolTable { | |||||
| * @return whether the role replaced a different definition | * @return whether the role replaced a different definition | ||||
| */ | */ | ||||
| public boolean addRole(String role, Class rclz, Class aclz) { | public boolean addRole(String role, Class rclz, Class aclz) { | ||||
| // Check if role already declared | |||||
| Role old = getRole(role); | |||||
| if (old != null && old.isSameAsFor(rclz, aclz) | |||||
| ) { | |||||
| project.log("Ignoring override for role " + role | |||||
| + ", it is already defined by the same definition.", | |||||
| project.MSG_VERBOSE); | |||||
| return false; | |||||
| } | |||||
| // Role interfaces should only contain one method | |||||
| roles.put(role, new Role(rclz, aclz)); | |||||
| return (old != null); | |||||
| } | |||||
| /** | |||||
| * Verify if the interface is valid. | |||||
| * @param clz the interface to validate | |||||
| * @return the method defined by the interface | |||||
| */ | |||||
| private Method validInterface(Class clz) { | |||||
| Method m[] = clz.getDeclaredMethods(); | |||||
| if (m.length == 1 | |||||
| && java.lang.Void.TYPE.equals(m[0].getReturnType())) { | |||||
| Class args[] = m[0].getParameterTypes(); | |||||
| if (args.length == 1 | |||||
| && !java.lang.String.class.equals(args[0]) | |||||
| && !args[0].isArray() | |||||
| && !args[0].isPrimitive()) { | |||||
| return m[0]; | |||||
| } | |||||
| else { | |||||
| throw new BuildException("Invalid role interface method in: " | |||||
| + clz.getName()); | |||||
| } | |||||
| } | |||||
| else { | |||||
| throw new BuildException("More than one method on role interface"); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Verify if the adapter is valid with respect to the interface. | |||||
| * @param clz the class adapter to validate | |||||
| * @param mtd the method whose only argument must match | |||||
| * @return the static method to use for validating adaptees | |||||
| */ | |||||
| private Method validAdapter(Class clz, Method mtd) { | |||||
| if (clz == null) return null; | |||||
| checkClass(clz); | |||||
| if (!mtd.getParameterTypes()[0].isAssignableFrom(clz)) { | |||||
| String msg = "Adapter " + clz.getName() + | |||||
| " is incompatible with role interface " + | |||||
| mtd.getDeclaringClass().getName(); | |||||
| throw new BuildException(msg); | |||||
| } | |||||
| String msg = "Class " + clz.getName() + " is not an adapter: "; | |||||
| if (!RoleAdapter.class.isAssignableFrom(clz)) { | |||||
| throw new BuildException(msg + "does not implement RoleAdapter"); | |||||
| } | |||||
| try { | |||||
| Method chk = clz.getMethod("checkClass", CHECK_ADAPTER_PARAMS); | |||||
| if (!Modifier.isStatic(chk.getModifiers())) { | |||||
| throw new BuildException(msg + "checkClass() is not static"); | |||||
| } | |||||
| return chk; | |||||
| } | |||||
| catch(NoSuchMethodException nme){ | |||||
| throw new BuildException(msg + "checkClass() not found", nme); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Get the specified loader for the project. | |||||
| * @param name the name of the loader | |||||
| * @return the corresponding ANT classloader | |||||
| */ | |||||
| private AntClassLoader getLoader(String name) { | |||||
| AntClassLoader cl = (AntClassLoader) loaders.get(name); | |||||
| if (cl == null && parentTable != null) { | |||||
| return parentTable.getLoader(name); | |||||
| } | |||||
| return cl; | |||||
| // Check if role already declared | |||||
| Role old = getRole(role); | |||||
| if (old != null && old.isSameAsFor(rclz, aclz)) { | |||||
| project.log("Ignoring override for role " + role | |||||
| + ", it is already defined by the same definition.", | |||||
| project.MSG_VERBOSE); | |||||
| return false; | |||||
| } | |||||
| // Role interfaces should only contain one method | |||||
| roles.put(role, new Role(rclz, aclz)); | |||||
| return (old != null); | |||||
| } | } | ||||
| /** | |||||
| * Add the specified class-path to a loader. | |||||
| * If the loader is defined in an ancestor project then a new | |||||
| * classloader inheritin from the one already existing | |||||
| * will be created, otherwise the path willbe added to the existing | |||||
| * ClassLoader. | |||||
| * @param name the name of the loader to use. | |||||
| * @param clspath the path to be added to the classloader | |||||
| */ | |||||
| public ClassLoader addToLoader(String name, Path clspath) { | |||||
| // Find if the loader is already defined in the current project | |||||
| AntClassLoader cl = (AntClassLoader) loaders.get(name); | |||||
| if (cl == null) { | |||||
| // Is it inherited from the calling project | |||||
| if (parentTable != null) { | |||||
| cl = parentTable.getLoader(name); | |||||
| } | |||||
| cl = new AntClassLoader(cl, project, clspath, true); | |||||
| loaders.put(name, cl); | |||||
| } | |||||
| else { | |||||
| // Add additional path to the existing definition | |||||
| String[] pathElements = clspath.list(); | |||||
| for (int i = 0; i < pathElements.length; ++i) { | |||||
| try { | |||||
| cl.addPathElement(pathElements[i]); | |||||
| } | |||||
| catch (BuildException e) { | |||||
| // ignore path elements invalid relative to the project | |||||
| } | |||||
| } | |||||
| } | |||||
| return cl; | |||||
| } | |||||
| /** | /** | ||||
| * Add a new type of element to a role. | * Add a new type of element to a role. | ||||
| * @param role the role for this Class. | * @param role the role for this Class. | ||||
| @@ -285,46 +227,53 @@ public class SymbolTable { | |||||
| * @return the old definition | * @return the old definition | ||||
| */ | */ | ||||
| public Class add(String role, String name, Class clz) { | public Class add(String role, String name, Class clz) { | ||||
| // Find the role definition | |||||
| Role r = getRole(role); | |||||
| if (r == null) { | |||||
| throw new BuildException("Unknown role: " + role); | |||||
| } | |||||
| // Check if it is already defined | |||||
| Class old = get(role, name); | |||||
| if (old != null) { | |||||
| if (old.equals(clz)) { | |||||
| project.log("Ignoring override for "+ role + " " + name | |||||
| + ", it is already defined by the same class.", | |||||
| project.MSG_VERBOSE); | |||||
| return old; | |||||
| } | |||||
| else { | |||||
| // Find the role definition | |||||
| Role r = getRole(role); | |||||
| if (r == null) { | |||||
| throw new BuildException("Unknown role: " + role); | |||||
| } | |||||
| // Check if it is already defined | |||||
| Factory old = get(role, name); | |||||
| if (old != null) { | |||||
| if (old.getOriginalClass().equals(clz)) { | |||||
| project.log("Ignoring override for "+ role + " " + name | |||||
| + ", it is already defined by the same class.", | |||||
| project.MSG_VERBOSE); | |||||
| return old.getOriginalClass(); | |||||
| } | |||||
| else { | |||||
| project.log("Trying to override old definition of " + | project.log("Trying to override old definition of " + | ||||
| role + " " + name, | |||||
| project.MSG_WARN); | |||||
| } | |||||
| } | |||||
| checkClass(clz); | |||||
| // Check that the Class is compatible with the role definition | |||||
| r.verifyAdaptability(role, clz); | |||||
| // Record the new type | |||||
| Hashtable defTable = (Hashtable)defs.get(role); | |||||
| if (defTable == null) { | |||||
| defTable = new Hashtable(); | |||||
| defs.put(role, defTable); | |||||
| } | |||||
| defTable.put(name, clz); | |||||
| return old; | |||||
| role + " " + name, | |||||
| project.MSG_WARN); | |||||
| } | |||||
| } | |||||
| Factory f = checkClass(clz); | |||||
| // Check that the Class is compatible with the role definition | |||||
| f = r.verifyAdaptability(role, f); | |||||
| // Record the new type | |||||
| Hashtable defTable = (Hashtable)defs.get(role); | |||||
| if (defTable == null) { | |||||
| defTable = new Hashtable(); | |||||
| defs.put(role, defTable); | |||||
| } | |||||
| defTable.put(name, f); | |||||
| String msg = | |||||
| " +User " + role + ": " + name + " " + clz.getName(); | |||||
| project.log(msg, project.MSG_DEBUG); | |||||
| return (old != null ? old.getOriginalClass() : null); | |||||
| } | } | ||||
| /** | /** | ||||
| * Checks a class, whether it is suitable for serving in ANT. | * Checks a class, whether it is suitable for serving in ANT. | ||||
| * @return the factory to use when instantiating the class | |||||
| * @throws BuildException and logs as Project.MSG_ERR for | * @throws BuildException and logs as Project.MSG_ERR for | ||||
| * conditions, that will cause execution to fail. | * conditions, that will cause execution to fail. | ||||
| */ | */ | ||||
| void checkClass(final Class clz) | |||||
| throws BuildException { | |||||
| Factory checkClass(final Class clz) // Package on purpose | |||||
| throws BuildException { | |||||
| if (clz == null) return null; | |||||
| if(!Modifier.isPublic(clz.getModifiers())) { | if(!Modifier.isPublic(clz.getModifiers())) { | ||||
| final String message = clz + " is not public"; | final String message = clz + " is not public"; | ||||
| project.log(message, Project.MSG_ERR); | project.log(message, Project.MSG_ERR); | ||||
| @@ -336,21 +285,53 @@ public class SymbolTable { | |||||
| throw new BuildException(message); | throw new BuildException(message); | ||||
| } | } | ||||
| try { | try { | ||||
| // Class can have a "no arg" constructor or take a single | |||||
| // Class can have a "no arg" constructor or take a single | |||||
| // Project argument. | // Project argument. | ||||
| // don't have to check for public, since | // don't have to check for public, since | ||||
| // getConstructor finds public constructors only. | // getConstructor finds public constructors only. | ||||
| try { | try { | ||||
| clz.getConstructor(new Class[0]); | clz.getConstructor(new Class[0]); | ||||
| return new Factory(){ | |||||
| public Object create(Project p) { | |||||
| try { | |||||
| return clz.newInstance(); | |||||
| } | |||||
| catch(Exception e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| public Class getOriginalClass() { | |||||
| return clz; | |||||
| } | |||||
| }; | |||||
| } catch (NoSuchMethodException nse) { | } catch (NoSuchMethodException nse) { | ||||
| clz.getConstructor(new Class[] {Project.class}); | |||||
| final Constructor c = | |||||
| clz.getConstructor(new Class[] {Project.class}); | |||||
| return new Factory(){ | |||||
| public Object create(Project p) { | |||||
| try { | |||||
| return c.newInstance(new Object[]{p}); | |||||
| } | |||||
| catch(Exception e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| public Class getOriginalClass() { | |||||
| return clz; | |||||
| } | |||||
| }; | |||||
| } | } | ||||
| } catch(NoSuchMethodException e) { | } catch(NoSuchMethodException e) { | ||||
| final String message = | |||||
| "No valid public constructor in " + clz; | |||||
| final String message = "No valid public constructor in " + clz; | |||||
| project.log(message, Project.MSG_ERR); | project.log(message, Project.MSG_ERR); | ||||
| throw new BuildException(message); | throw new BuildException(message); | ||||
| } | } | ||||
| catch (NoClassDefFoundError ncdfe) { | |||||
| final String msg = "Class cannot be loaded: " + ncdfe.getMessage(); | |||||
| throw new BuildException(msg, ncdfe); | |||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -359,32 +340,25 @@ public class SymbolTable { | |||||
| * @param name the name of the element to sea | * @param name the name of the element to sea | ||||
| * @return the Class implementation | * @return the Class implementation | ||||
| */ | */ | ||||
| public Class get(String role, String name) { | |||||
| Hashtable defTable = (Hashtable)defs.get(role); | |||||
| if (defTable != null) { | |||||
| Class clz = (Class)defTable.get(name); | |||||
| if (clz != null) return clz; | |||||
| } | |||||
| if (parentTable != null) { | |||||
| return parentTable.get(role, name); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * Get a Hashtable that is usable for manipulating Tasks, | |||||
| * @return a Hashtable that delegates to the Symbol table. | |||||
| */ | |||||
| public Hashtable getTaskDefinitions() { | |||||
| return new SymbolHashtable("task"); | |||||
| public Factory get(String role, String name) { | |||||
| Hashtable defTable = (Hashtable)defs.get(role); | |||||
| if (defTable != null) { | |||||
| Factory f = (Factory)defTable.get(name); | |||||
| if (f != null) return f; | |||||
| } | |||||
| if (parentTable != null) { | |||||
| return parentTable.get(role, name); | |||||
| } | |||||
| return null; | |||||
| } | } | ||||
| /** | /** | ||||
| * Get a Hashtable that is usable for manipulating Datatypes, | |||||
| * Get a Hashtable that is usable for manipulating elements on Role. | |||||
| * @param role the role of the elements in the table | |||||
| * @return a Hashtable that delegates to the Symbol table. | * @return a Hashtable that delegates to the Symbol table. | ||||
| */ | */ | ||||
| public Hashtable getDataTypeDefinitions() { | |||||
| return new SymbolHashtable("datatype"); | |||||
| Hashtable getDefinitions(String role) { // package scope on purpose | |||||
| return new SymbolHashtable(role); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -392,100 +366,196 @@ public class SymbolTable { | |||||
| * the search operations to the Symbol table | * the search operations to the Symbol table | ||||
| */ | */ | ||||
| private class SymbolHashtable extends Hashtable { | private class SymbolHashtable extends Hashtable { | ||||
| final String role; | |||||
| SymbolHashtable(String role) { | |||||
| this.role = role; | |||||
| } | |||||
| public synchronized Object put(Object key, Object value) { | |||||
| return SymbolTable.this.add(role, (String) key, (Class) value); | |||||
| } | |||||
| public synchronized Object get(Object key) { | |||||
| return SymbolTable.this.get(role, (String)key); | |||||
| } | |||||
| final String role; | |||||
| SymbolHashtable(String role) { | |||||
| this.role = role; | |||||
| } | |||||
| public synchronized Object put(Object key, Object value) { | |||||
| return SymbolTable.this.add(role, (String) key, (Class) value); | |||||
| } | |||||
| public synchronized Object get(Object key) { | |||||
| Factory f = SymbolTable.this.get(role, (String)key); | |||||
| return (f == null? null : f.getOriginalClass()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Factory for creating ANT objects. | |||||
| * Class objects are not instanciated directly but through a Factory | |||||
| * which is able to resolve issues such as proxys and such. | |||||
| */ | |||||
| public static interface Factory { | |||||
| /** | |||||
| * Creates an object for the Role | |||||
| * @param the project in which it is created | |||||
| * @return the instantiated object with a proxy if necessary | |||||
| */ | |||||
| public Object create(Project p); | |||||
| /** | |||||
| * Creates an object for the Role, adapted if necessary | |||||
| * for a particular interface. | |||||
| */ | |||||
| // public Object adaptFor(Class clz, Project p, Object o); | |||||
| /** | |||||
| * The original class of the object without proxy. | |||||
| */ | |||||
| public Class getOriginalClass(); | |||||
| } | } | ||||
| /** | /** | ||||
| * The definition of a role | * The definition of a role | ||||
| */ | */ | ||||
| public class Role { | public class Role { | ||||
| private Method interfaceMethod; | |||||
| private Method adapterVerifier; | |||||
| /** | |||||
| * Creates a new Role object | |||||
| * @param roleClz the class that defines the role | |||||
| * @param adapterClz the class for the adapter, or null if none | |||||
| */ | |||||
| Role(Class roleClz, Class adapterClz) { | |||||
| interfaceMethod = validInterface(roleClz); | |||||
| adapterVerifier = validAdapter(adapterClz, interfaceMethod); | |||||
| } | |||||
| /** | |||||
| * Get the method used to set on interface | |||||
| */ | |||||
| public Method getInterfaceMethod() { | |||||
| return interfaceMethod; | |||||
| } | |||||
| /** | |||||
| * Instantiate a new adapter for this role. | |||||
| */ | |||||
| public RoleAdapter createAdapter() { | |||||
| if (adapterVerifier == null) return null; | |||||
| try { | |||||
| return (RoleAdapter) | |||||
| adapterVerifier.getDeclaringClass().newInstance(); | |||||
| } | |||||
| catch(BuildException be) { | |||||
| throw be; | |||||
| } | |||||
| catch(Exception e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Verify if the class can be adapted to use by the role | |||||
| * @param role the name of the role to verify | |||||
| * @param clz the class to verify | |||||
| */ | |||||
| public void verifyAdaptability(String role, Class clz) { | |||||
| if (interfaceMethod.getParameterTypes()[0].isAssignableFrom(clz)) { | |||||
| return; | |||||
| } | |||||
| if (adapterVerifier == null) { | |||||
| String msg = "Class " + clz.getName() + | |||||
| " incompatible with role: " + role; | |||||
| throw new BuildException(msg); | |||||
| } | |||||
| try { | |||||
| try { | |||||
| adapterVerifier.invoke(null, | |||||
| new Object[]{clz, project}); | |||||
| } | |||||
| catch (InvocationTargetException ite) { | |||||
| throw ite.getTargetException(); | |||||
| } | |||||
| } | |||||
| catch(BuildException be) { throw be; } | |||||
| catch(Error err) {throw err; } | |||||
| catch(Throwable t) { | |||||
| throw new BuildException(t); | |||||
| } | |||||
| } | |||||
| public boolean isSameAsFor(Class clz, Class pclz) { | |||||
| return interfaceMethod.getDeclaringClass().equals(clz) && | |||||
| ((adapterVerifier == null && pclz == null) || | |||||
| adapterVerifier.getDeclaringClass().equals(pclz)); | |||||
| } | |||||
| public boolean isImplementedBy(Class clz) { | |||||
| return interfaceMethod.getDeclaringClass().isAssignableFrom(clz); | |||||
| } | |||||
| private Method interfaceMethod; | |||||
| private Method adapterVerifier; | |||||
| private Factory adapterFactory; | |||||
| /** | |||||
| * Creates a new Role object | |||||
| * @param roleClz the class that defines the role | |||||
| * @param adapterClz the class for the adapter, or null if none | |||||
| */ | |||||
| Role(Class roleClz, Class adapterClz) { | |||||
| interfaceMethod = validInterface(roleClz); | |||||
| adapterFactory = checkClass(adapterClz); | |||||
| adapterVerifier = validAdapter(adapterClz, interfaceMethod); | |||||
| } | |||||
| /** | |||||
| * Get the method used to set on interface | |||||
| */ | |||||
| public Method getInterfaceMethod() { | |||||
| return interfaceMethod; | |||||
| } | |||||
| /** | |||||
| * Instantiate a new adapter for this role. | |||||
| */ | |||||
| public RoleAdapter createAdapter(Project p) { | |||||
| if (adapterFactory == null) return null; | |||||
| try { | |||||
| return (RoleAdapter) adapterFactory.create(p); | |||||
| } | |||||
| catch(BuildException be) { | |||||
| throw be; | |||||
| } | |||||
| catch(Exception e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Verify if the class can be adapted to use by the role | |||||
| * @param role the name of the role to verify | |||||
| * @param f the factory for the class to verify | |||||
| */ | |||||
| public Factory verifyAdaptability(String role, final Factory f) { | |||||
| final Class clz = f.getOriginalClass(); | |||||
| if (interfaceMethod.getParameterTypes()[0].isAssignableFrom(clz)) { | |||||
| return f; | |||||
| } | |||||
| if (adapterVerifier == null) { | |||||
| String msg = "Class " + clz.getName() + | |||||
| " incompatible with role: " + role; | |||||
| throw new BuildException(msg); | |||||
| } | |||||
| try { | |||||
| try { | |||||
| adapterVerifier.invoke(null, new Object[]{clz, project}); | |||||
| return new Factory(){ | |||||
| public Object create(Project p) { | |||||
| RoleAdapter ra = createAdapter(p); | |||||
| ra.setProxy(f.create(p)); | |||||
| return ra; | |||||
| } | |||||
| public Class getOriginalClass() { | |||||
| return clz; | |||||
| } | |||||
| }; | |||||
| } | |||||
| catch (InvocationTargetException ite) { | |||||
| throw ite.getTargetException(); | |||||
| } | |||||
| } | |||||
| catch(BuildException be) { throw be; } | |||||
| catch(Error err) {throw err; } | |||||
| catch(Throwable t) { | |||||
| throw new BuildException(t); | |||||
| } | |||||
| } | |||||
| public boolean isSameAsFor(Class clz, Class pclz) { | |||||
| return interfaceMethod.getDeclaringClass().equals(clz) && | |||||
| ((adapterVerifier == null && pclz == null) || | |||||
| adapterVerifier.getDeclaringClass().equals(pclz)); | |||||
| } | |||||
| public boolean isImplementedBy(Class clz) { | |||||
| return interfaceMethod.getDeclaringClass().isAssignableFrom(clz); | |||||
| } | |||||
| /** | |||||
| * Verify if the interface is valid. | |||||
| * @param clz the interface to validate | |||||
| * @return the method defined by the interface | |||||
| */ | |||||
| private Method validInterface(Class clz) { | |||||
| Method m[] = clz.getDeclaredMethods(); | |||||
| if (m.length == 1 | |||||
| && java.lang.Void.TYPE.equals(m[0].getReturnType())) { | |||||
| Class args[] = m[0].getParameterTypes(); | |||||
| if (args.length == 1 | |||||
| && !java.lang.String.class.equals(args[0]) | |||||
| && !args[0].isArray() | |||||
| && !args[0].isPrimitive()) { | |||||
| return m[0]; | |||||
| } | |||||
| else { | |||||
| throw new BuildException("Invalid role interface method in: " | |||||
| + clz.getName()); | |||||
| } | |||||
| } | |||||
| else { | |||||
| throw new BuildException("More than one method on role interface"); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Verify if the adapter is valid with respect to the interface. | |||||
| * @param clz the class adapter to validate | |||||
| * @param mtd the method whose only argument must match | |||||
| * @return the static method to use for validating adaptees | |||||
| */ | |||||
| private Method validAdapter(Class clz, Method mtd) { | |||||
| if (clz == null) return null; | |||||
| if (!mtd.getParameterTypes()[0].isAssignableFrom(clz)) { | |||||
| String msg = "Adapter " + clz.getName() + | |||||
| " is incompatible with role interface " + | |||||
| mtd.getDeclaringClass().getName(); | |||||
| throw new BuildException(msg); | |||||
| } | |||||
| String msg = "Class " + clz.getName() + " is not an adapter: "; | |||||
| if (!RoleAdapter.class.isAssignableFrom(clz)) { | |||||
| throw new BuildException(msg + "does not implement RoleAdapter"); | |||||
| } | |||||
| try { | |||||
| Method chk = clz.getMethod("checkClass", CHECK_ADAPTER_PARAMS); | |||||
| if (!Modifier.isStatic(chk.getModifiers())) { | |||||
| throw new BuildException(msg + "checkClass() is not static"); | |||||
| } | |||||
| return chk; | |||||
| } | |||||
| catch(NoSuchMethodException nme){ | |||||
| throw new BuildException(msg + "checkClass() not found", nme); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| /* | /* | ||||
| * The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
| * | * | ||||
| * Copyright (c) 2000-2001 The Apache Software Foundation. All rights | |||||
| * Copyright (c) 2000-2001 The Apache Software Foundation. All rights | |||||
| * reserved. | * reserved. | ||||
| * | * | ||||
| * Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
| @@ -9,7 +9,7 @@ | |||||
| * are met: | * are met: | ||||
| * | * | ||||
| * 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
| * notice, this list of conditions and the following disclaimer. | |||||
| * notice, this list of conditions and the following disclaimer. | |||||
| * | * | ||||
| * 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
| * notice, this list of conditions and the following disclaimer in | * notice, this list of conditions and the following disclaimer in | ||||
| @@ -17,15 +17,15 @@ | |||||
| * distribution. | * distribution. | ||||
| * | * | ||||
| * 3. The end-user documentation included with the redistribution, if | * 3. The end-user documentation included with the redistribution, if | ||||
| * any, must include the following acknowlegement: | |||||
| * "This product includes software developed by the | |||||
| * any, must include the following acknowlegement: | |||||
| * "This product includes software developed by the | |||||
| * Apache Software Foundation (http://www.apache.org/)." | * Apache Software Foundation (http://www.apache.org/)." | ||||
| * Alternately, this acknowlegement may appear in the software itself, | * Alternately, this acknowlegement may appear in the software itself, | ||||
| * if and wherever such third-party acknowlegements normally appear. | * if and wherever such third-party acknowlegements normally appear. | ||||
| * | * | ||||
| * 4. The names "The Jakarta Project", "Ant", and "Apache Software | * 4. The names "The Jakarta Project", "Ant", and "Apache Software | ||||
| * Foundation" must not be used to endorse or promote products derived | * Foundation" must not be used to endorse or promote products derived | ||||
| * from this software without prior written permission. For written | |||||
| * from this software without prior written permission. For written | |||||
| * permission, please contact apache@apache.org. | * permission, please contact apache@apache.org. | ||||
| * | * | ||||
| * 5. Products derived from this software may not be called "Apache" | * 5. Products derived from this software may not be called "Apache" | ||||
| @@ -55,6 +55,7 @@ | |||||
| package org.apache.tools.ant; | package org.apache.tools.ant; | ||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
| import java.lang.reflect.InvocationTargetException; | |||||
| @@ -68,7 +69,7 @@ import java.lang.reflect.Method; | |||||
| public class TaskAdapter extends Task implements RoleAdapter { | public class TaskAdapter extends Task implements RoleAdapter { | ||||
| Object proxy; | Object proxy; | ||||
| /** | /** | ||||
| * Checks a class, whether it is suitable to be adapted by TaskAdapter. | * Checks a class, whether it is suitable to be adapted by TaskAdapter. | ||||
| * | * | ||||
| @@ -81,15 +82,15 @@ public class TaskAdapter extends Task implements RoleAdapter { | |||||
| * Logs other suspicious conditions with Project.MSG_WARN. | * Logs other suspicious conditions with Project.MSG_WARN. | ||||
| */ | */ | ||||
| public static void checkTaskClass(final Class taskClass, final Project project) { | public static void checkTaskClass(final Class taskClass, final Project project) { | ||||
| // This code is for backward compatibility | |||||
| checkClass(taskClass, project); | |||||
| // This code is for backward compatibility | |||||
| checkClass(taskClass, project); | |||||
| } | } | ||||
| /** | /** | ||||
| * Checks a class, whether it is suitable to be adapted. | * Checks a class, whether it is suitable to be adapted. | ||||
| * | * | ||||
| * Checks conditions only, which are additionally required for a tasks | * Checks conditions only, which are additionally required for a tasks | ||||
| * adapted by TaskAdapter. | |||||
| * adapted by TaskAdapter. | |||||
| * | * | ||||
| * Throws a BuildException and logs as Project.MSG_ERR for | * Throws a BuildException and logs as Project.MSG_ERR for | ||||
| * conditions, that will cause the task execution to fail. | * conditions, that will cause the task execution to fail. | ||||
| @@ -114,7 +115,7 @@ public class TaskAdapter extends Task implements RoleAdapter { | |||||
| throw new BuildException(message); | throw new BuildException(message); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Do the execution. | * Do the execution. | ||||
| */ | */ | ||||
| @@ -122,7 +123,7 @@ public class TaskAdapter extends Task implements RoleAdapter { | |||||
| Method setProjectM = null; | Method setProjectM = null; | ||||
| try { | try { | ||||
| Class c = proxy.getClass(); | Class c = proxy.getClass(); | ||||
| setProjectM = | |||||
| setProjectM = | |||||
| c.getMethod( "setProject", new Class[] {Project.class}); | c.getMethod( "setProject", new Class[] {Project.class}); | ||||
| if(setProjectM != null) { | if(setProjectM != null) { | ||||
| setProjectM.invoke(proxy, new Object[] {project}); | setProjectM.invoke(proxy, new Object[] {project}); | ||||
| @@ -131,7 +132,7 @@ public class TaskAdapter extends Task implements RoleAdapter { | |||||
| // ignore this if the class being used as a task does not have | // ignore this if the class being used as a task does not have | ||||
| // a set project method. | // a set project method. | ||||
| } catch( Exception ex ) { | } catch( Exception ex ) { | ||||
| log("Error setting project in " + proxy.getClass(), | |||||
| log("Error setting project in " + proxy.getClass(), | |||||
| Project.MSG_ERR); | Project.MSG_ERR); | ||||
| throw new BuildException( ex ); | throw new BuildException( ex ); | ||||
| } | } | ||||
| @@ -146,14 +147,20 @@ public class TaskAdapter extends Task implements RoleAdapter { | |||||
| throw new BuildException("No public execute() in " + proxy.getClass()); | throw new BuildException("No public execute() in " + proxy.getClass()); | ||||
| } | } | ||||
| executeM.invoke(proxy, null); | executeM.invoke(proxy, null); | ||||
| return; | |||||
| return; | |||||
| } catch( InvocationTargetException ite ) { | |||||
| Throwable t = ite.getTargetException(); | |||||
| if (t instanceof BuildException) { | |||||
| throw (BuildException) t; | |||||
| } | |||||
| throw new BuildException(t); | |||||
| } catch( Exception ex ) { | } catch( Exception ex ) { | ||||
| log("Error in " + proxy.getClass(), Project.MSG_ERR); | log("Error in " + proxy.getClass(), Project.MSG_ERR); | ||||
| throw new BuildException( ex ); | throw new BuildException( ex ); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Set the target object class | * Set the target object class | ||||
| */ | */ | ||||
| @@ -165,4 +172,5 @@ public class TaskAdapter extends Task implements RoleAdapter { | |||||
| return this.proxy ; | return this.proxy ; | ||||
| } | } | ||||
| public void setId(String id) {} | |||||
| } | } | ||||
| @@ -138,10 +138,8 @@ public class Ant extends Task { | |||||
| } | } | ||||
| public void init() { | public void init() { | ||||
| newProject = new Project(project); | |||||
| newProject = project.createSubProject(); | |||||
| newProject.setJavaVersionProperty(); | newProject.setJavaVersionProperty(); | ||||
| // newProject.addTaskDefinition("property", | |||||
| // (Class)project.getTaskDefinitions().get("property")); | |||||
| } | } | ||||
| private void reinit() { | private void reinit() { | ||||
| @@ -185,26 +183,6 @@ public class Ant extends Task { | |||||
| } | } | ||||
| } | } | ||||
| // Hashtable taskdefs = project.getTaskDefinitions(); | |||||
| // Enumeration et = taskdefs.keys(); | |||||
| // while (et.hasMoreElements()) { | |||||
| // String taskName = (String) et.nextElement(); | |||||
| // if (taskName.equals("property")) { | |||||
| // // we have already added this taskdef in #init | |||||
| // continue; | |||||
| // } | |||||
| // Class taskClass = (Class) taskdefs.get(taskName); | |||||
| // newProject.addTaskDefinition(taskName, taskClass); | |||||
| // } | |||||
| // Hashtable typedefs = project.getDataTypeDefinitions(); | |||||
| // Enumeration e = typedefs.keys(); | |||||
| // while (e.hasMoreElements()) { | |||||
| // String typeName = (String) e.nextElement(); | |||||
| // Class typeClass = (Class) typedefs.get(typeName); | |||||
| // newProject.addDataTypeDefinition(typeName, typeClass); | |||||
| // } | |||||
| // set user-defined or all properties from calling project | // set user-defined or all properties from calling project | ||||
| Hashtable prop1; | Hashtable prop1; | ||||
| if (inheritAll) { | if (inheritAll) { | ||||
| @@ -104,7 +104,8 @@ public class Antjar extends Jar { | |||||
| public void setAntxml(File descriptor) { | public void setAntxml(File descriptor) { | ||||
| libraryDescriptor = descriptor; | libraryDescriptor = descriptor; | ||||
| if (!libraryDescriptor.exists()) { | if (!libraryDescriptor.exists()) { | ||||
| throw new BuildException("Deployment descriptor: " + libraryDescriptor + " does not exist."); | |||||
| throw new BuildException("Deployment descriptor: " + | |||||
| libraryDescriptor + " does not exist."); | |||||
| } | } | ||||
| // Create a ZipFileSet for this file, and pass it up. | // Create a ZipFileSet for this file, and pass it up. | ||||
| @@ -127,7 +128,8 @@ public class Antjar extends Jar { | |||||
| throws IOException, BuildException { | throws IOException, BuildException { | ||||
| // If no antxml file is specified, it's an error. | // If no antxml file is specified, it's an error. | ||||
| if (libraryDescriptor == null) { | if (libraryDescriptor == null) { | ||||
| throw new BuildException("antxml attribute is required", location); | |||||
| throw new BuildException("antxml attribute is required", | |||||
| location); | |||||
| } | } | ||||
| super.initZipOutputStream(zOut); | super.initZipOutputStream(zOut); | ||||
| @@ -149,10 +151,12 @@ public class Antjar extends Jar { | |||||
| // meaning the same file is specified by the "antxml" attribute and in | // meaning the same file is specified by the "antxml" attribute and in | ||||
| // a <fileset> element. | // a <fileset> element. | ||||
| if (vPath.equalsIgnoreCase(Antlib.ANT_DESCRIPTOR)) { | if (vPath.equalsIgnoreCase(Antlib.ANT_DESCRIPTOR)) { | ||||
| if (libraryDescriptor == null || !libraryDescriptor.equals(file) || descriptorAdded) { | |||||
| if (libraryDescriptor == null || | |||||
| !libraryDescriptor.equals(file) || descriptorAdded) { | |||||
| log("Warning: selected " + archiveType + " files include a " + | log("Warning: selected " + archiveType + " files include a " + | ||||
| Antlib.ANT_DESCRIPTOR + " which will be ignored " + | |||||
| "(please use antxml attribute to " + archiveType + " task)", Project.MSG_WARN); | |||||
| Antlib.ANT_DESCRIPTOR + " which will be ignored " + | |||||
| "(please use antxml attribute to " + archiveType + | |||||
| " task)", Project.MSG_WARN); | |||||
| } | } | ||||
| else { | else { | ||||
| super.zipFile(file, zOut, vPath); | super.zipFile(file, zOut, vPath); | ||||
| @@ -55,12 +55,14 @@ package org.apache.tools.ant.taskdefs; | |||||
| import org.apache.tools.ant.*; | import org.apache.tools.ant.*; | ||||
| import org.apache.tools.ant.types.*; | import org.apache.tools.ant.types.*; | ||||
| import org.apache.tools.ant.taskdefs.*; | |||||
| import org.xml.sax.*; | import org.xml.sax.*; | ||||
| import javax.xml.parsers.*; | import javax.xml.parsers.*; | ||||
| import java.util.*; | import java.util.*; | ||||
| import java.util.zip.*; | import java.util.zip.*; | ||||
| import java.io.*; | import java.io.*; | ||||
| import java.net.*; | |||||
| /** | /** | ||||
| * Make available the tasks and types from an Ant library. <pre> | * Make available the tasks and types from an Ant library. <pre> | ||||
| @@ -76,16 +78,18 @@ import java.io.*; | |||||
| * @since ant1.5 | * @since ant1.5 | ||||
| */ | */ | ||||
| public class Antlib extends Task { | public class Antlib extends Task { | ||||
| /** | |||||
| * Location of descriptor in library | |||||
| */ | |||||
| public static final String ANT_DESCRIPTOR = "META-INF/antlib.xml"; | |||||
| /** | /** | ||||
| * The named classloader to use. | * The named classloader to use. | ||||
| * Defaults to the default classLoader. | * Defaults to the default classLoader. | ||||
| */ | */ | ||||
| private String loaderId = ""; | private String loaderId = ""; | ||||
| /** | |||||
| * library attribute | |||||
| */ | |||||
| private String library = null; | |||||
| /** | /** | ||||
| * file attribute | * file attribute | ||||
| */ | */ | ||||
| @@ -95,62 +99,200 @@ public class Antlib extends Task { | |||||
| */ | */ | ||||
| private boolean override = false; | private boolean override = false; | ||||
| /** | /** | ||||
| * attribute to control classloader use | |||||
| * attribute to control failure when loading | |||||
| */ | */ | ||||
| private boolean useCurrentClassloader = false; | |||||
| private FailureAction onerror = new FailureAction(); | |||||
| /** | /** | ||||
| * classpath to build up | * classpath to build up | ||||
| */ | */ | ||||
| private Path classpath = null; | private Path classpath = null; | ||||
| /** | |||||
| * the manufacture set of classes to load | |||||
| */ | |||||
| private Path loaderPath = null; | |||||
| /** | /** | ||||
| * our little xml parse | * our little xml parse | ||||
| */ | */ | ||||
| private SAXParserFactory saxFactory; | private SAXParserFactory saxFactory; | ||||
| /** | /** | ||||
| * table of aliases | * table of aliases | ||||
| */ | */ | ||||
| private Vector aliases = new Vector(); | private Vector aliases = new Vector(); | ||||
| /** | /** | ||||
| * Location of descriptor in library | |||||
| * Some internal constants. | |||||
| */ | */ | ||||
| public static String ANT_DESCRIPTOR = "META-INF/antlib.xml"; | |||||
| private static final int FAIL = 0, REPORT = 1, IGNORE = 2; | |||||
| /** | /** | ||||
| * Prefix name for DTD of descriptor | |||||
| */ | |||||
| public static String ANTLIB_DTD_URL = | |||||
| "http://jakarta.apache.org/ant/"; | |||||
| /** | |||||
| * prefix of the antlib | |||||
| */ | |||||
| public static String ANTLIB_DTD_PREFIX = "Antlib-V"; | |||||
| /** | |||||
| * version counter | |||||
| * Posible actions when classes are not found | |||||
| */ | */ | ||||
| public static String ANTLIB_DTD_VERSION = "1_0"; | |||||
| /** | |||||
| * dtd file extension | |||||
| */ | |||||
| public static String ANTLIB_DTD_EXT = ".dtd"; | |||||
| public static class FailureAction extends EnumeratedAttribute { | |||||
| public String[] getValues() { | |||||
| return new String[]{"fail", "report", "ignore"}; | |||||
| } | |||||
| } | |||||
| private static class DescriptorEnumeration implements Enumeration { | |||||
| /** | |||||
| * The name of the resource being searched for. | |||||
| */ | |||||
| private String resourceName; | |||||
| /** | |||||
| * The index of the next file to search. | |||||
| */ | |||||
| private int index; | |||||
| /** | |||||
| * The list of files to search | |||||
| */ | |||||
| private File files[]; | |||||
| /** | |||||
| * The URL of the next resource to return in the enumeration. If this | |||||
| * field is <code>null</code> then the enumeration has been completed, | |||||
| * i.e., there are no more elements to return. | |||||
| */ | |||||
| private URL nextDescriptor; | |||||
| /** | |||||
| * Construct a new enumeration of resources of the given name found | |||||
| * within this class loader's classpath. | |||||
| * | |||||
| * @param name the name of the resource to search for. | |||||
| */ | |||||
| DescriptorEnumeration(String fileNames[], String name) { | |||||
| this.resourceName = name; | |||||
| this.index = 0; | |||||
| this.files = new File[fileNames.length]; | |||||
| for (int i = 0; i < files.length; i++) { | |||||
| files[i] = new File(fileNames[i]); | |||||
| } | |||||
| findNextDescriptor(); | |||||
| } | |||||
| /** | |||||
| * Indicates whether there are more elements in the enumeration to | |||||
| * return. | |||||
| * | |||||
| * @return <code>true</code> if there are more elements in the | |||||
| * enumeration; <code>false</code> otherwise. | |||||
| */ | |||||
| public boolean hasMoreElements() { | |||||
| return (this.nextDescriptor != null); | |||||
| } | |||||
| /** | |||||
| * Returns the next resource in the enumeration. | |||||
| * | |||||
| * @return the next resource in the enumeration. | |||||
| */ | |||||
| public Object nextElement() { | |||||
| URL ret = this.nextDescriptor; | |||||
| findNextDescriptor(); | |||||
| return ret; | |||||
| } | |||||
| /** | |||||
| * Locates the next descriptor of the correct name in the files and | |||||
| * sets <code>nextDescriptor</code> to the URL of that resource. If no | |||||
| * more resources can be found, <code>nextDescriptor</code> is set to | |||||
| * <code>null</code>. | |||||
| */ | |||||
| private void findNextDescriptor() { | |||||
| URL url = null; | |||||
| while (index < files.length && url == null) { | |||||
| try { | |||||
| url = getDescriptorURL(files[index], this.resourceName); | |||||
| index++; | |||||
| } | |||||
| catch (BuildException e) { | |||||
| // ignore path elements which are not valid relative to the | |||||
| // project | |||||
| } | |||||
| } | |||||
| this.nextDescriptor = url; | |||||
| } | |||||
| /** | |||||
| * Get an URL to a given resource in the given file which may | |||||
| * either be a directory or a zip file. | |||||
| * | |||||
| * @param file the file (directory or jar) in which to search for | |||||
| * the resource. Must not be <code>null</code>. | |||||
| * @param resourceName the name of the resource for which a URL | |||||
| * is required. Must not be <code>null</code>. | |||||
| * | |||||
| * @return a URL to the required resource or <code>null</code> if the | |||||
| * resource cannot be found in the given file object | |||||
| * @todo This code is extracted from AntClassLoader.getResourceURL | |||||
| * I hate when that happens but the code there is too tied to | |||||
| * the ClassLoader internals. Maybe we can find a nice place | |||||
| * to put it where both can use it. | |||||
| */ | |||||
| private URL getDescriptorURL(File file, String resourceName) { | |||||
| try { | |||||
| if (!file.exists()) { | |||||
| return null; | |||||
| } | |||||
| if (file.isDirectory()) { | |||||
| File resource = new File(file, resourceName); | |||||
| if (resource.exists()) { | |||||
| try { | |||||
| return new URL("file:"+resource.toString()); | |||||
| } catch (MalformedURLException ex) { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| } | |||||
| else { | |||||
| ZipFile zipFile = new ZipFile(file); | |||||
| try { | |||||
| ZipEntry entry = zipFile.getEntry(resourceName); | |||||
| if (entry != null) { | |||||
| try { | |||||
| return new URL("jar:file:"+file.toString()+"!/"+entry); | |||||
| } catch (MalformedURLException ex) { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| } | |||||
| finally { | |||||
| zipFile.close(); | |||||
| } | |||||
| } | |||||
| } | |||||
| catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * constructor creates a validating sax parser | * constructor creates a validating sax parser | ||||
| */ | */ | ||||
| public Antlib() { | public Antlib() { | ||||
| super(); | super(); | ||||
| // Default error action | |||||
| onerror.setValue("report"); | |||||
| saxFactory = SAXParserFactory.newInstance(); | saxFactory = SAXParserFactory.newInstance(); | ||||
| saxFactory.setValidating(true); | |||||
| saxFactory.setValidating(false); | |||||
| } | } | ||||
| /** | /** | ||||
| * constructor binds to a project as well as setting up internal state | |||||
| * constructor binds to a project and sets ignore mode on errors | |||||
| * | * | ||||
| * @param p Description of Parameter | * @param p Description of Parameter | ||||
| */ | */ | ||||
| @@ -161,12 +303,12 @@ public class Antlib extends Task { | |||||
| /** | /** | ||||
| * Set name of library to load. The library is located in $ANT_HOME/lib. | |||||
| * Set name of library to load. The library is located in $ANT_HOME/antlib. | |||||
| * | * | ||||
| * @param lib the name of library relative to $ANT_HOME/lib. | |||||
| * @param lib the name of library relative to $ANT_HOME/antlib. | |||||
| */ | */ | ||||
| public void setLibrary(String lib) { | public void setLibrary(String lib) { | ||||
| this.library = lib; | |||||
| setFile(libraryFile("antlib", lib)); | |||||
| } | } | ||||
| @@ -180,13 +322,13 @@ public class Antlib extends Task { | |||||
| } | } | ||||
| /** | /** | ||||
| * Set the ClassLoader to use for this library. | |||||
| * Set the ID of the ClassLoader to use for this library. | |||||
| * | * | ||||
| * @param id the id for the ClassLoader to use, | |||||
| * if other than the default. | |||||
| * @param id the id for the ClassLoader to use, | |||||
| * <code>null</code> means use ANT's core classloader. | |||||
| */ | */ | ||||
| public void setLoaderid(String id) { | public void setLoaderid(String id) { | ||||
| this.loaderId = id; | |||||
| this.loaderId = id; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -200,15 +342,26 @@ public class Antlib extends Task { | |||||
| /** | /** | ||||
| * Set whether to use a new classloader or not. | |||||
| * Default is <code>false</code>. | |||||
| * Get what to do if a definition cannot be loaded | |||||
| * This method is mostly used by the core when loading core tasks. | |||||
| * | |||||
| * @return what to do if a definition cannot be loaded | |||||
| */ | |||||
| final protected FailureAction getOnerror() { | |||||
| return this.onerror; | |||||
| } | |||||
| /** | |||||
| * Set whether to fail if a definition cannot be loaded | |||||
| * Default is <code>true</code>. | |||||
| * This property is mostly used by the core when loading core tasks. | * This property is mostly used by the core when loading core tasks. | ||||
| * | * | ||||
| * @param useCurrentClassloader if true the current classloader will | |||||
| * be used to load the definitions. | |||||
| * @param failedonerror if true loading will stop if classes | |||||
| * cannot be instantiated | |||||
| */ | */ | ||||
| public void setUseCurrentClassloader(boolean useCurrentClassloader) { | |||||
| this.useCurrentClassloader = useCurrentClassloader; | |||||
| public void setOnerror(FailureAction onerror) { | |||||
| this.onerror = onerror; | |||||
| } | } | ||||
| @@ -262,78 +415,97 @@ public class Antlib extends Task { | |||||
| } | } | ||||
| /** | |||||
| * Obtain library file from ANT_HOME directory. | |||||
| * | |||||
| * @param lib the library name. | |||||
| * @return the File instance of the library | |||||
| */ | |||||
| private File libraryFile(String homeSubDir, String lib) { | |||||
| // For the time being libraries live in $ANT_HOME/antlib. | |||||
| // The idea being that not to load all the jars there anymore | |||||
| String home = project.getProperty("ant.home"); | |||||
| if (home == null) { | |||||
| throw new BuildException("ANT_HOME not set as required."); | |||||
| } | |||||
| return new File(new File(home, homeSubDir), lib); | |||||
| } | |||||
| /** | /** | ||||
| * actually do the work of loading the library | * actually do the work of loading the library | ||||
| * | * | ||||
| * @exception BuildException Description of Exception | * @exception BuildException Description of Exception | ||||
| * @todo maybe have failonerror support for missing file? | |||||
| */ | */ | ||||
| public void execute() | public void execute() | ||||
| throws BuildException { | throws BuildException { | ||||
| File realFile = file; | |||||
| if (library != null) { | |||||
| if (file != null) { | |||||
| String msg = "You cannot specify both file and library."; | |||||
| throw new BuildException(msg, location); | |||||
| } | |||||
| // For the time being libraries live in $ANT_HOME/antlib. | |||||
| // The idea being that we would not load all the jars there anymore | |||||
| String home = project.getProperty("ant.home"); | |||||
| if (home == null) { | |||||
| throw new BuildException("ANT_HOME not set as required."); | |||||
| } | |||||
| realFile = new File(new File(home, "antlib"), library); | |||||
| } | |||||
| else if (file == null) { | |||||
| String msg = "Must specify either library or file attribute."; | |||||
| if (file == null && classpath == null) { | |||||
| String msg = | |||||
| "Must specify either library or file attribute or classpath."; | |||||
| throw new BuildException(msg, location); | throw new BuildException(msg, location); | ||||
| } | } | ||||
| if (!realFile.exists()) { | |||||
| String msg = "Cannot find library: " + realFile; | |||||
| if (file != null && !file.exists()) { | |||||
| String msg = "Cannot find library: " + file; | |||||
| throw new BuildException(msg, location); | throw new BuildException(msg, location); | ||||
| } | } | ||||
| //open the descriptor | |||||
| InputStream is = getDescriptor(realFile); | |||||
| if (is == null) { | |||||
| String msg = "Missing descriptor on library: " + realFile; | |||||
| throw new BuildException(msg, location); | |||||
| } | |||||
| loadDefinitions(); | |||||
| } | |||||
| ClassLoader classloader=null; | |||||
| if (useCurrentClassloader && classpath != null) { | |||||
| log("ignoring the useCurrentClassloader option as a classpath is defined", | |||||
| Project.MSG_WARN); | |||||
| useCurrentClassloader=false; | |||||
| } | |||||
| if (!useCurrentClassloader) { | |||||
| classloader = makeClassLoader(realFile); | |||||
| } | |||||
| //parse it and evaluate it. | |||||
| evaluateDescriptor(classloader, processAliases(), is); | |||||
| /** | |||||
| * Load definitions in library and classpath | |||||
| * | |||||
| * @exception BuildException failure to access the resource | |||||
| */ | |||||
| public boolean loadDefinitions() throws BuildException { | |||||
| return loadDefinitions(ANT_DESCRIPTOR); | |||||
| } | } | ||||
| /** | /** | ||||
| * Load definitions directly from an external XML file. | |||||
| * Load definitions from resource name in library and classpath | |||||
| * | * | ||||
| * @param xmlfile XML file in the Antlib format. | |||||
| * @exception BuildException failure to open the file | |||||
| * @param res the name of the resources to load | |||||
| * @exception BuildException failure to access the resource | |||||
| */ | */ | ||||
| public void loadDefinitions(File xmlfile) | |||||
| final protected boolean loadDefinitions(String res) | |||||
| throws BuildException { | throws BuildException { | ||||
| Path path = makeLoaderClasspath(); | |||||
| ClassLoader cl = makeClassLoader(path); | |||||
| boolean found = false; | |||||
| try { | try { | ||||
| InputStream is = new FileInputStream(xmlfile); | |||||
| loadDefinitions(is); | |||||
| for (Enumeration e = getDescriptors(path, res); e.hasMoreElements(); ) { | |||||
| URL resURL = (URL)e.nextElement(); | |||||
| InputStream is = resURL.openStream(); | |||||
| loadDefinitions(cl, is); | |||||
| found = true; | |||||
| } | |||||
| if (!found && onerror.getIndex() != IGNORE) { | |||||
| String sPath = path.toString(); | |||||
| if ("".equals(sPath.trim())) { | |||||
| sPath = System.getProperty("java.classpath"); | |||||
| } | |||||
| String msg = "Cannot find any " + res + | |||||
| " antlib descriptors in: " + sPath; | |||||
| switch (onerror.getIndex()) { | |||||
| case FAIL: | |||||
| throw new BuildException(msg); | |||||
| case REPORT: | |||||
| log(msg, project.MSG_WARN); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| catch (IOException io) { | catch (IOException io) { | ||||
| throw new BuildException("Cannot read file: " + file, io); | |||||
| String msg = "Cannot load definitions from: " + res; | |||||
| switch (onerror.getIndex()) { | |||||
| case FAIL: | |||||
| throw new BuildException(msg, io); | |||||
| case REPORT: | |||||
| log(io.getMessage(), project.MSG_WARN); | |||||
| } | |||||
| } | } | ||||
| return found; | |||||
| } | } | ||||
| @@ -343,46 +515,29 @@ public class Antlib extends Task { | |||||
| * @param is InputStream for the Antlib descriptor. | * @param is InputStream for the Antlib descriptor. | ||||
| * @exception BuildException trouble | * @exception BuildException trouble | ||||
| */ | */ | ||||
| public void loadDefinitions(InputStream is) | |||||
| private void loadDefinitions(ClassLoader cl, InputStream is) | |||||
| throws BuildException { | throws BuildException { | ||||
| evaluateDescriptor(null, processAliases(), is); | |||||
| evaluateDescriptor(cl, processAliases(), is); | |||||
| } | } | ||||
| /** | /** | ||||
| * get a descriptor from the library file | |||||
| * get an Enumeration of URLs for all resouces corresponding to the | |||||
| * descriptor name. | |||||
| * | * | ||||
| * @param file jarfile to open | |||||
| * @return input stream to the Descriptor | |||||
| * @param res the name of the resource to collect | |||||
| * @return input stream to the Descriptor or null if none existent | |||||
| * @exception BuildException io trouble, or it isnt a zipfile | * @exception BuildException io trouble, or it isnt a zipfile | ||||
| */ | */ | ||||
| private InputStream getDescriptor(File file) | |||||
| throws BuildException { | |||||
| try { | |||||
| final ZipFile zipfile = new ZipFile(file); | |||||
| ZipEntry entry = zipfile.getEntry(ANT_DESCRIPTOR); | |||||
| if (entry == null) { | |||||
| return null; | |||||
| } | |||||
| // Guarantee that when Entry is closed so does the zipfile instance. | |||||
| return | |||||
| new FilterInputStream(zipfile.getInputStream(entry)) { | |||||
| public void close() | |||||
| throws IOException { | |||||
| super.close(); | |||||
| zipfile.close(); | |||||
| } | |||||
| }; | |||||
| } | |||||
| catch (ZipException ze) { | |||||
| throw new BuildException("Not a library file.", ze, location); | |||||
| } | |||||
| catch (IOException ioe) { | |||||
| throw new BuildException("Cannot read library content.", | |||||
| ioe, location); | |||||
| private Enumeration getDescriptors(Path path, final String res) | |||||
| throws BuildException, IOException { | |||||
| if (loaderId == null) { | |||||
| // Path cannot be added to the CoreLoader so simply | |||||
| // ask for all instances of the resource descriptors | |||||
| return project.getCoreLoader().getResources(res); | |||||
| } | } | ||||
| return new DescriptorEnumeration(path.list(), res); | |||||
| } | } | ||||
| @@ -410,18 +565,34 @@ public class Antlib extends Task { | |||||
| * @return classloader using te | * @return classloader using te | ||||
| * @exception BuildException trouble creating the classloader | * @exception BuildException trouble creating the classloader | ||||
| */ | */ | ||||
| protected ClassLoader makeClassLoader(File file) | |||||
| protected ClassLoader makeClassLoader(Path clspath) | |||||
| throws BuildException { | throws BuildException { | ||||
| if (loaderId == null) { | |||||
| log("Loading definitions from CORE, <classpath> ignored", | |||||
| project.MSG_VERBOSE); | |||||
| return project.getCoreLoader(); | |||||
| } | |||||
| log("Using ClassLoader '" + loaderId + "' to load path: " + clspath, | |||||
| project.MSG_VERBOSE); | |||||
| return project.addToLoader(loaderId, clspath); | |||||
| } | |||||
| /** | |||||
| * Constructs the Path to add to the ClassLoader | |||||
| */ | |||||
| private Path makeLoaderClasspath() | |||||
| { | |||||
| Path clspath = new Path(project); | Path clspath = new Path(project); | ||||
| clspath.setLocation(file); | |||||
| if (file != null) clspath.setLocation(file); | |||||
| //append any build supplied classpath | //append any build supplied classpath | ||||
| if (classpath != null) { | if (classpath != null) { | ||||
| clspath.append(classpath); | clspath.append(classpath); | ||||
| } | } | ||||
| return project.getSymbols().addToLoader(loaderId, clspath); | |||||
| return clspath; | |||||
| } | } | ||||
| /** | /** | ||||
| * parse the antlib descriptor | * parse the antlib descriptor | ||||
| * | * | ||||
| @@ -431,8 +602,8 @@ public class Antlib extends Task { | |||||
| * @exception BuildException trouble | * @exception BuildException trouble | ||||
| */ | */ | ||||
| protected void evaluateDescriptor(ClassLoader cl, | protected void evaluateDescriptor(ClassLoader cl, | ||||
| Properties als, InputStream is) | |||||
| throws BuildException { | |||||
| Properties als, InputStream is) | |||||
| throws BuildException { | |||||
| try { | try { | ||||
| SAXParser saxParser = saxFactory.newSAXParser(); | SAXParser saxParser = saxFactory.newSAXParser(); | ||||
| Parser parser = saxParser.getParser(); | Parser parser = saxParser.getParser(); | ||||
| @@ -440,7 +611,7 @@ public class Antlib extends Task { | |||||
| InputSource inputSource = new InputSource(is); | InputSource inputSource = new InputSource(is); | ||||
| //inputSource.setSystemId(uri); //URI is nasty for jar entries | //inputSource.setSystemId(uri); //URI is nasty for jar entries | ||||
| project.log("parsing descriptor for library: " + file, | project.log("parsing descriptor for library: " + file, | ||||
| Project.MSG_VERBOSE); | |||||
| Project.MSG_VERBOSE); | |||||
| saxParser.parse(inputSource, new AntLibraryHandler(cl, als)); | saxParser.parse(inputSource, new AntLibraryHandler(cl, als)); | ||||
| } | } | ||||
| catch (ParserConfigurationException exc) { | catch (ParserConfigurationException exc) { | ||||
| @@ -485,8 +656,8 @@ public class Antlib extends Task { | |||||
| /** | /** | ||||
| * Parses the document describing the content of the | |||||
| * library. An inner class for access to Project.log | |||||
| * Parses the document describing the content of the | |||||
| * library. An inner class for access to Project.log | |||||
| */ | */ | ||||
| private class AntLibraryHandler extends HandlerBase { | private class AntLibraryHandler extends HandlerBase { | ||||
| @@ -503,13 +674,11 @@ public class Antlib extends Task { | |||||
| */ | */ | ||||
| private Locator locator = null; | private Locator locator = null; | ||||
| private int level = 0; | |||||
| private SymbolTable symbols = null; | |||||
| private int level = 0; | |||||
| private String name = null; | |||||
| private String className = null; | |||||
| private String adapter = null; | |||||
| private String name = null; | |||||
| private String className = null; | |||||
| private String adapter = null; | |||||
| /** | /** | ||||
| * Constructor for the AntLibraryHandler object | * Constructor for the AntLibraryHandler object | ||||
| @@ -520,7 +689,6 @@ public class Antlib extends Task { | |||||
| AntLibraryHandler(ClassLoader classloader, Properties als) { | AntLibraryHandler(ClassLoader classloader, Properties als) { | ||||
| this.classloader = classloader; | this.classloader = classloader; | ||||
| this.aliasMap = als; | this.aliasMap = als; | ||||
| this.symbols = project.getSymbols(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -533,35 +701,35 @@ public class Antlib extends Task { | |||||
| this.locator = locator; | this.locator = locator; | ||||
| } | } | ||||
| private void parseAttributes(String tag, AttributeList attrs) | |||||
| throws SAXParseException { | |||||
| name = null; | |||||
| className = null; | |||||
| adapter = null; | |||||
| for (int i = 0, last = attrs.getLength(); i < last; i++) { | |||||
| String key = attrs.getName(i); | |||||
| String value = attrs.getValue(i); | |||||
| if (key.equals("name")) { | |||||
| name = value; | |||||
| } | |||||
| else if (key.equals("class")) { | |||||
| className = value; | |||||
| } | |||||
| else if ("role".equals(tag) && key.equals("adapter")) { | |||||
| adapter = value; | |||||
| } | |||||
| else { | |||||
| throw new SAXParseException("Unexpected attribute \"" | |||||
| + key + "\"", locator); | |||||
| } | |||||
| } | |||||
| if (name == null || className == null) { | |||||
| String msg = "Underspecified " + tag + " declaration."; | |||||
| throw new SAXParseException(msg, locator); | |||||
| } | |||||
| } | |||||
| private void parseAttributes(String tag, AttributeList attrs) | |||||
| throws SAXParseException { | |||||
| name = null; | |||||
| className = null; | |||||
| adapter = null; | |||||
| for (int i = 0, last = attrs.getLength(); i < last; i++) { | |||||
| String key = attrs.getName(i); | |||||
| String value = attrs.getValue(i); | |||||
| if (key.equals("name")) { | |||||
| name = value; | |||||
| } | |||||
| else if (key.equals("class")) { | |||||
| className = value; | |||||
| } | |||||
| else if ("role".equals(tag) && key.equals("adapter")) { | |||||
| adapter = value; | |||||
| } | |||||
| else { | |||||
| throw new SAXParseException("Unexpected attribute \"" | |||||
| + key + "\"", locator); | |||||
| } | |||||
| } | |||||
| if (name == null || className == null) { | |||||
| String msg = "Underspecified " + tag + " declaration."; | |||||
| throw new SAXParseException(msg, locator); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * SAX callback handler | * SAX callback handler | ||||
| @@ -572,103 +740,105 @@ public class Antlib extends Task { | |||||
| */ | */ | ||||
| public void startElement(String tag, AttributeList attrs) | public void startElement(String tag, AttributeList attrs) | ||||
| throws SAXParseException { | throws SAXParseException { | ||||
| level ++; | |||||
| level ++; | |||||
| if ("antlib".equals(tag)) { | if ("antlib".equals(tag)) { | ||||
| if (level > 1) { | |||||
| throw new SAXParseException("Unexpected element: " + tag, | |||||
| locator); | |||||
| } | |||||
| if (level > 1) { | |||||
| throw new SAXParseException("Unexpected element: " + tag, | |||||
| locator); | |||||
| } | |||||
| // No attributes to worry about | // No attributes to worry about | ||||
| return; | return; | ||||
| } | } | ||||
| if (level == 1) { | |||||
| throw new SAXParseException("Missing antlib root element", | |||||
| locator); | |||||
| } | |||||
| // Must have the two attributes declared | |||||
| parseAttributes(tag, attrs); | |||||
| try { | |||||
| if ("role".equals(tag)) { | |||||
| if (isRoleInUse(name)) { | |||||
| String msg = "Cannot override role: " + name; | |||||
| log(msg, Project.MSG_WARN); | |||||
| return; | |||||
| } | |||||
| // Defining a new role | |||||
| symbols.addRole(name, loadClass(className), | |||||
| (adapter == null? | |||||
| null : loadClass(adapter))); | |||||
| return; | |||||
| } | |||||
| // Defining a new element kind | |||||
| //check for name alias | |||||
| String alias = aliasMap.getProperty(name); | |||||
| if (alias != null) { | |||||
| name = alias; | |||||
| } | |||||
| //catch an attempted override of an existing name | |||||
| if (!override && isInUse(tag, name)) { | |||||
| String msg = "Cannot override " + tag + ": " + name; | |||||
| log(msg, Project.MSG_WARN); | |||||
| return; | |||||
| } | |||||
| symbols.add(tag, name, loadClass(className)); | |||||
| } | |||||
| catch(BuildException be) { | |||||
| throw new SAXParseException(be.getMessage(), locator, be); | |||||
| } | |||||
| } | |||||
| public void endElement(String tag) { | |||||
| level--; | |||||
| } | |||||
| private Class loadClass(String className) | |||||
| throws SAXParseException { | |||||
| try { | |||||
| //load the named class | |||||
| Class cls; | |||||
| if(classloader==null) { | |||||
| cls=Class.forName(className); | |||||
| } | |||||
| else { | |||||
| cls=classloader.loadClass(className); | |||||
| } | |||||
| return cls; | |||||
| } | |||||
| catch (ClassNotFoundException cnfe) { | |||||
| String msg = "Class " + className + | |||||
| " cannot be found"; | |||||
| throw new SAXParseException(msg, locator, cnfe); | |||||
| } | |||||
| catch (NoClassDefFoundError ncdfe) { | |||||
| String msg = "Class " + className + | |||||
| " cannot be found"; | |||||
| throw new SAXParseException(msg, locator); | |||||
| } | |||||
| } | |||||
| if (level == 1) { | |||||
| throw new SAXParseException("Missing antlib root element", | |||||
| locator); | |||||
| } | |||||
| /** | |||||
| * test for a name being in use already on this role | |||||
| * | |||||
| * @param name the name to test | |||||
| * @return true if it is a task or a datatype | |||||
| */ | |||||
| private boolean isInUse(String role, String name) { | |||||
| return (symbols.get(role, name) != null); | |||||
| // Must have the two attributes declared | |||||
| parseAttributes(tag, attrs); | |||||
| try { | |||||
| if ("role".equals(tag)) { | |||||
| if (project.isRoleDefined(name)) { | |||||
| String msg = "Cannot override role: " + name; | |||||
| log(msg, Project.MSG_WARN); | |||||
| return; | |||||
| } | |||||
| // Defining a new role | |||||
| Class clz = loadClass(className); | |||||
| if (clz != null) { | |||||
| project.addRoleDefinition(name, clz, | |||||
| (adapter == null? null : | |||||
| loadClass(adapter))); | |||||
| } | |||||
| return; | |||||
| } | |||||
| // Defining a new element kind | |||||
| //check for name alias | |||||
| String alias = aliasMap.getProperty(name); | |||||
| if (alias != null) { | |||||
| name = alias; | |||||
| } | |||||
| //catch an attempted override of an existing name | |||||
| if (!override && project.isDefinedOnRole(tag, name)) { | |||||
| String msg = "Cannot override " + tag + ": " + name; | |||||
| log(msg, Project.MSG_WARN); | |||||
| return; | |||||
| } | |||||
| Class clz = loadClass(className); | |||||
| if (clz != null) | |||||
| project.addDefinitionOnRole(tag, name, clz); | |||||
| } | |||||
| catch(BuildException be) { | |||||
| switch (onerror.getIndex()) { | |||||
| case FAIL: | |||||
| throw new SAXParseException(be.getMessage(), locator, be); | |||||
| case REPORT: | |||||
| project.log(be.getMessage(), project.MSG_WARN); | |||||
| break; | |||||
| default: | |||||
| project.log(be.getMessage(), project.MSG_DEBUG); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| /** | |||||
| * test for a role name being in use already | |||||
| * | |||||
| * @param name the name to test | |||||
| * @return true if it is a task or a datatype | |||||
| */ | |||||
| private boolean isRoleInUse(String name) { | |||||
| return (symbols.getRole(name) != null); | |||||
| public void endElement(String tag) { | |||||
| level--; | |||||
| } | |||||
| private Class loadClass(String className) | |||||
| throws SAXParseException { | |||||
| String msg = null; | |||||
| try { | |||||
| //load the named class | |||||
| Class cls; | |||||
| if(classloader==null) { | |||||
| cls=Class.forName(className); | |||||
| } | |||||
| else { | |||||
| cls=classloader.loadClass(className); | |||||
| } | |||||
| return cls; | |||||
| } | |||||
| catch (ClassNotFoundException cnfe) { | |||||
| msg = "Class " + className + " cannot be found"; | |||||
| if (onerror.getIndex() == FAIL) | |||||
| throw new SAXParseException(msg, locator, cnfe); | |||||
| } | |||||
| catch (NoClassDefFoundError ncdfe) { | |||||
| msg = "Class " + className + " cannot be loaded"; | |||||
| if (onerror.getIndex() == FAIL) | |||||
| throw new SAXParseException(msg, locator); | |||||
| } | |||||
| if (onerror.getIndex() == REPORT) { | |||||
| project.log(msg, project.MSG_WARN); | |||||
| } | |||||
| else { | |||||
| project.log(msg, project.MSG_DEBUG); | |||||
| } | |||||
| return null; | |||||
| } | } | ||||
| //end inner class AntLibraryHandler | //end inner class AntLibraryHandler | ||||
| @@ -712,7 +882,7 @@ public class Antlib extends Task { | |||||
| } | } | ||||
| //end inner class alias | //end inner class alias | ||||
| } | } | ||||
| //end class Antlib | //end class Antlib | ||||
| } | } | ||||
| @@ -66,6 +66,7 @@ import org.apache.tools.ant.*; | |||||
| public class DataTypeAdapterTask extends Task implements RoleAdapter { | public class DataTypeAdapterTask extends Task implements RoleAdapter { | ||||
| Object proxy; | Object proxy; | ||||
| String id = null; | |||||
| /** | /** | ||||
| * Checks a class, whether it is suitable to be adapted. | * Checks a class, whether it is suitable to be adapted. | ||||
| @@ -83,14 +84,27 @@ public class DataTypeAdapterTask extends Task implements RoleAdapter { | |||||
| * Do the execution. | * Do the execution. | ||||
| */ | */ | ||||
| public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
| if (id != null) { | |||||
| // Need to re-register this reference | |||||
| // The container has register the Adapter instead | |||||
| project.addReference(id, proxy); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Propagate configuration of Project | |||||
| */ | |||||
| public void setProject(Project p) { | |||||
| super.setProject(p); | |||||
| // Check to see if the DataType has a setProject method to set | // Check to see if the DataType has a setProject method to set | ||||
| if (proxy instanceof ProjectComponent) { | if (proxy instanceof ProjectComponent) { | ||||
| ((ProjectComponent)proxy).setProject(project); | |||||
| ((ProjectComponent)proxy).setProject(p); | |||||
| return; | return; | ||||
| } | } | ||||
| // This may not be needed | // This may not be needed | ||||
| // We are trying to set project even it is was not declared | |||||
| // We are trying to set project even if is was not declared | |||||
| // just like TaskAdapter does for beans, this is not done | // just like TaskAdapter does for beans, this is not done | ||||
| // by the original code | // by the original code | ||||
| Method setProjectM = null; | Method setProjectM = null; | ||||
| @@ -99,7 +113,7 @@ public class DataTypeAdapterTask extends Task implements RoleAdapter { | |||||
| setProjectM = | setProjectM = | ||||
| c.getMethod( "setProject", new Class[] {Project.class}); | c.getMethod( "setProject", new Class[] {Project.class}); | ||||
| if(setProjectM != null) { | if(setProjectM != null) { | ||||
| setProjectM.invoke(proxy, new Object[] {project}); | |||||
| setProjectM.invoke(proxy, new Object[] {p}); | |||||
| } | } | ||||
| } catch (NoSuchMethodException e) { | } catch (NoSuchMethodException e) { | ||||
| // ignore this if the class being used as a task does not have | // ignore this if the class being used as a task does not have | ||||
| @@ -122,4 +136,8 @@ public class DataTypeAdapterTask extends Task implements RoleAdapter { | |||||
| return this.proxy ; | return this.proxy ; | ||||
| } | } | ||||
| public void setId(String id) { | |||||
| log("Setting adapter id to: " + id, Project.MSG_DEBUG); | |||||
| this.id = id; | |||||
| } | |||||
| } | } | ||||