diff --git a/proposal/embed/src/java/org/apache/tools/ant/taskdefs/SystemPath.java b/proposal/embed/src/java/org/apache/tools/ant/taskdefs/SystemPath.java index 21a76cbbc..6f6cb1684 100644 --- a/proposal/embed/src/java/org/apache/tools/ant/taskdefs/SystemPath.java +++ b/proposal/embed/src/java/org/apache/tools/ant/taskdefs/SystemPath.java @@ -171,7 +171,7 @@ public class SystemPath extends Task { Class taskClass = acl.loadClass(c.getName()); //project.addTaskDefinition(key, taskClass); project.getTaskDefinitions().put(key, taskClass); - System.out.println("Loaded " + key + " " + taskClass.getClassLoader() ); + //System.out.println("Loaded " + key + " " + taskClass.getClassLoader() ); } catch (NoClassDefFoundError ncdfe) { log("Could not load a dependent class (" + ncdfe.getMessage() + ") for task " + key, Project.MSG_DEBUG); diff --git a/proposal/embed/src/java/org/apache/tools/ant/taskdefs/Taskdef2.java b/proposal/embed/src/java/org/apache/tools/ant/taskdefs/Taskdef2.java new file mode 100644 index 000000000..08c834403 --- /dev/null +++ b/proposal/embed/src/java/org/apache/tools/ant/taskdefs/Taskdef2.java @@ -0,0 +1,349 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.types.*; +import java.io.*; +import java.util.*; + +// XXX Had to cut&paste the code in Definer - since most fields are private +// and no accessor is available. + +/** + * Special version of taskdef using the configurable ant class loader. + * It will also have additional features ( META-INF/ant.properties ,etc ). + * + * + * @author Stefan Bodewig + * @author Costin Manolache + * @since Ant 1.6 + * @ant.task category="internal" + */ +public class Taskdef2 extends Definer { + private String name; + private String value; + private Path classpath; + private File file; + private String resource; + private boolean reverseLoader = false; + private String loaderId = null; + private String classpathId = null; + + private static final String REUSE_LOADER_REF = "ant.reuse.loader"; + + /** + * @deprecated stop using this attribute + * @ant.attribute ignore="true" + */ + public void setReverseLoader(boolean reverseLoader) { + this.reverseLoader = reverseLoader; + log("The reverseloader attribute is DEPRECATED. It will be removed", + Project.MSG_WARN); + } + + /** + * Set the classpath to be used when searching for component being defined + * + * @param classpath an Ant Path object containing the classpath. + */ + public void setClasspath(Path classpath) { + if (this.classpath == null) { + this.classpath = classpath; + } else { + this.classpath.append(classpath); + } + } + + /** + * Create the classpath to be used when searching for component being defined + */ + public Path createClasspath() { + if (this.classpath == null) { + this.classpath = new Path(getProject()); + } + return this.classpath.createPath(); + } + + /** + * reference to a classpath to use when loading the files. + * To actually share the same loader, set loaderref as well + */ + public void setClasspathRef(Reference r) { + classpathId=r.getRefId(); + createClasspath().setRefid(r); + } + + /** + * Use the reference to locate the loader. If the loader is not + * found, taskdef will use the specified classpath and register it + * with the specified name. + * + * This allow multiple taskdef/typedef to use the same class loader, + * so they can be used together. It eliminate the need to + * put them in the CLASSPATH. + * + * @since Ant 1.5 + */ + public void setLoaderRef(Reference r) { + loaderId = r.getRefId(); + } + + + public void execute() throws BuildException { + AntClassLoader al = createLoader(); + + if (file == null && resource == null) { + + // simple case - one definition + if (name == null || value == null) { + String msg = "name or classname attributes of " + + getTaskName() + " element " + + "are undefined"; + throw new BuildException(msg); + } + addDefinition(al, name, value); + + } else { + + InputStream is = null; + try { + if (name != null || value != null) { + String msg = "You must not specify name or value " + + "together with file or resource."; + throw new BuildException(msg, getLocation()); + } + + if (file != null && resource != null) { + String msg = "You must not specify both, file and " + + "resource."; + throw new BuildException(msg, getLocation()); + } + + + Properties props = new Properties(); + if (file != null) { + log("Loading definitions from file " + file, + Project.MSG_VERBOSE); + is = new FileInputStream(file); + if (is == null) { + log("Could not load definitions from file " + file + + ". It doesn\'t exist.", Project.MSG_WARN); + } + } + if (resource != null) { + log("Loading definitions from resource " + resource, + Project.MSG_VERBOSE); + is = al.getResourceAsStream(resource); + if (is == null) { + log("Could not load definitions from resource " + + resource + ". It could not be found.", + Project.MSG_WARN); + } + } + + if (is != null) { + props.load(is); + Enumeration keys = props.keys(); + while (keys.hasMoreElements()) { + String n = (String) keys.nextElement(); + String v = props.getProperty(n); + addDefinition(al, n, v); + } + } + } catch (IOException ex) { + throw new BuildException(ex, getLocation()); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) {} + } + } + } + } + + /** + * create the classloader then hand the definition off to the subclass; + * @throws BuildException when the class wont load for any reason + */ + private void addDefinition(ClassLoader al, String name, String value) + throws BuildException { + try { + Class c = al.loadClass(value); + AntClassLoader.initializeClass(c); + addDefinition(name, c); + } catch (ClassNotFoundException cnfe) { + String msg = getTaskName() + " class " + value + + " cannot be found"; + throw new BuildException(msg, cnfe, getLocation()); + } catch (NoClassDefFoundError ncdfe) { + String msg = getTaskName() + " class " + value + + " cannot be found"; + throw new BuildException(msg, ncdfe, getLocation()); + } + } + + /** + * create a classloader for this definition + */ + private AntClassLoader createLoader() { + // magic property + if (getProject().getProperty(REUSE_LOADER_REF) != null) { + // Generate the 'reuse' name automatically from the reference. + // This allows that work on both ant1.4 and ant1.5. + // ( in 1.4 it'll require the task/type to be in classpath if they + // are used togheter ). + if (loaderId == null && classpathId != null) { + loaderId = "ant.loader." + classpathId; + } + } + + // If a loader has been set ( either by loaderRef or magic property ) + if (loaderId != null) { + Object reusedLoader = getProject().getReference(loaderId); + if (reusedLoader != null) { + if (reusedLoader instanceof AntClassLoader) { + return (AntClassLoader)reusedLoader; + } + // In future the reference object may be the type + // if( reusedLoader instanceof Loader ) { + // return ((Loader)reusedLoader).getLoader(project); + // } + } + } + + AntClassLoader al = (AntClassLoader)project.getReference( "ant.system.loader" ); + if( al==null ) { + if (classpath != null) { + al = new AntClassLoader(getProject(), classpath, !reverseLoader); + } else { + al = new AntClassLoader(getProject(), Path.systemClasspath, + !reverseLoader); + } + } else { + if (classpath != null) { + al = new AntClassLoader(al, getProject(), classpath, !reverseLoader); + } else { + al = new AntClassLoader(al, getProject(), Path.systemClasspath, + !reverseLoader); + } + } + // need to load Task via system classloader or the new + // task we want to define will never be a Task but always + // be wrapped into a TaskAdapter. + al.addSystemPackageRoot("org.apache.tools.ant"); + + + // If the loader is new, record it for future uses by other + // task/typedefs + if (loaderId != null) { + if (getProject().getReference(loaderId) == null) { + getProject().addReference(loaderId, al); + } + } + + return al; + } + + /** + * Name of the property file to load + * ant name/classname pairs from. + */ + public void setFile(File file) { + this.file = file; + } + + /** + * Name of the property resource to load + * ant name/classname pairs from. + */ + public void setResource(String res) { + this.resource = res; + } + + /** + * Name of the property resource to load + * ant name/classname pairs from. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns the classname of the object we are defining. + * May be null. + */ + public String getClassname() { + return value; + } + + /** + * The full class name of the object being defined. + * Required, unless file or resource have + * been specified. + */ + public void setClassname(String v) { + value = v; + } + + /** + * subclassed handler for definitions; called by parent during + * execution. + */ + protected void addDefinition(String name, Class c) throws BuildException { + getProject().addTaskDefinition(name, c); + } +} diff --git a/proposal/embed/src/java/org/apache/tools/ant/taskdefs/optional/JXPath.java b/proposal/embed/src/java/org/apache/tools/ant/taskdefs/optional/JXPath.java new file mode 100644 index 000000000..5880ce414 --- /dev/null +++ b/proposal/embed/src/java/org/apache/tools/ant/taskdefs/optional/JXPath.java @@ -0,0 +1,149 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.optional; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.types.*; + +import java.io.*; +import java.util.*; +import org.xml.sax.Locator; +import org.xml.sax.InputSource; +//import org.xml.sax.HandlerBase; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +import org.xml.sax.SAXException; +import org.xml.sax.DocumentHandler; +import org.xml.sax.Attributes; +import org.xml.sax.AttributeList; +import org.xml.sax.helpers.XMLReaderAdapter; +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.helpers.AttributeListImpl; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.jxpath.*; + +// Experimental: need to add code to select the 'root', etc. + +/** + * Enable JXPath dynamic properties + * + * + * @author Costin Manolache + */ +public class JXPath extends Task implements PropertyInterceptor { + JXPathContext jxpathCtx; + + public JXPath() { + } + + public Object getProperty( Project p, String ns, String name ) { + if( ! name.startsWith("jxpath:" ) ) + return null; + name=name.substring( 7 ); + Object o=jxpathCtx.getValue( name ); + //System.out.println("JXPath: getProperty " + ns + " " + name + "=" + o); + if( o==null ) return "null"; + return o; + } + + + public void execute() { + JXPathIntrospector.registerDynamicClass(Hashtable.class, JXPathHashtableHandler.class); + + PropertyHelper phelper=PropertyHelper.getPropertyHelper( project ); + phelper.addPropertyInterceptor( this ); + + jxpathCtx=JXPathContext.newContext( project ); + } + + public static class JXPathHashtableHandler implements DynamicPropertyHandler { + + private static final String[] STRING_ARRAY = new String[0]; + + /** + * Returns string representations of all keys in the map. + */ + public String[] getPropertyNames(Object object){ + // System.out.println("getPropertyNames " + object ); + Hashtable map = (Hashtable) object; + String names[] = new String[map.size()]; + Enumeration it = map.keys(); + for (int i = 0; i < names.length; i++){ + names[i] = String.valueOf(it.nextElement()); + } + return names; + } + + /** + * Returns the value for the specified key. + */ + public Object getProperty(Object object, String propertyName) { + // System.out.println("getProperty " + object + " " + propertyName); + return ((Hashtable) object).get(propertyName); + } + + /** + * Sets the specified key value. + */ + public void setProperty(Object object, String propertyName, Object value){ + ((Hashtable)object).put(propertyName, value); + } + } + +}