Browse Source

Modifications to Ant1 compatibility layer.

* Use modified version of Path.java, to provide all
  available classes in Path.systemClasspath.
  (Uses LoaderUtils.java taken from Mutant proposal,
  for obtaining complete classpath from a ClassLoader.)

* Removed <ant> and <antcall> from ant1compat.atl
  descriptor, since they don't work.

* Modified build so that xdoclet.jar and
  jdepend.jar aren't included in dist/lib.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271907 13f79535-47bb-0310-9956-ffa450edef68
master
Darrell DeBoer 23 years ago
parent
commit
4b93240e47
8 changed files with 946 additions and 142 deletions
  1. +12
    -10
      proposal/myrmidon/ant1compat.xml
  2. +4
    -1
      proposal/myrmidon/build.xml
  3. +1
    -1
      proposal/myrmidon/src/ant1compat/README.txt
  4. +10
    -4
      proposal/myrmidon/src/ant1compat/ant-descriptor.xml
  5. +6
    -101
      proposal/myrmidon/src/ant1compat/org/apache/tools/ant/Ant1CompatProject.java
  6. +286
    -0
      proposal/myrmidon/src/ant1compat/org/apache/tools/ant/LoaderUtils.java
  7. +2
    -25
      proposal/myrmidon/src/ant1compat/org/apache/tools/ant/Task.java
  8. +625
    -0
      proposal/myrmidon/src/ant1compat/org/apache/tools/ant/types/Path.java

+ 12
- 10
proposal/myrmidon/ant1compat.xml View File

@@ -1,7 +1,7 @@
<project name="ant1-compatibility" default="main">

<property name="ant1compat.source" value="src/ant1compat"/>
<property name="manifest.dir" value="src/manifest"/>
<property name="java.dir" value="src/java"/>

@@ -10,7 +10,7 @@
<property name="build.classes" value="${build.dir}/classes"/>

<property name="custom-tasks-dir" value="build/tasks"/>
<path id="project.class.path">
<pathelement location="build/classes"/>
<fileset dir="lib">
@@ -18,7 +18,8 @@
</fileset>
</path>

<taskdef name="antlib-jar" classname="org.apache.myrmidon.build.AntlibJarTask">
<taskdef name="antlib-jar"
classname="org.apache.myrmidon.build.AntlibJarTask">
<classpath location="${custom-tasks-dir}"/>
</taskdef>

@@ -31,11 +32,11 @@
<!-- Builds the Ant1 compatibility layer -->
<target name="antlib"
description="Builds the Ant1 compatibility layer.">
<property name="ant1compat.dir" value="src/ant1compat"/>
<property name="ant1.jar" value="${ant1compat.dir}/jar/ant.jar"/>
<property name="ant1optional.jar" value="${ant1compat.dir}/jar/optional.jar"/>
<property name="ant1.package" value="org/apache/tools"/>

<property name="build.ant1classes" value="${build.dir}/ant1classes"/>
@@ -57,16 +58,17 @@
<src location="${ant1compat.dir}"/>
<include name="${ant1.package}/**"/>
</javac>
<patternset id="ant1.omit">
<exclude name="${ant1.package}/ant/Main.class"/>
<exclude name="${ant1.package}/ant/Task.class"/>
<exclude name="${ant1.package}/ant/taskdefs/Ant.class"/>
<exclude name="${ant1.package}/ant/taskdefs/CallTarget.class"/>
<exclude name="${ant1.package}/ant/types/Path.class"/>
</patternset>

<property name="antlib.file" value="${build.lib}/ant1compat.atl"/>

<!-- Create the ant1compat antlib -->
<antlib-jar jarfile="${build.lib}/ant1compat.atl"
<antlib-jar jarfile="${antlib.file}"
descriptor="${ant1compat.dir}/ant-descriptor.xml"
rolesDescriptor="${manifest.dir}/empty-roles.xml"
manifest="${ant1compat.dir}/ant1compat.mf">
@@ -79,7 +81,7 @@
</fileset>
</antlib-jar>

<copy todir="dist/lib" file="${build.lib}/ant1compat.atl"/>
<copy todir="dist/lib" file="${antlib.file}"/>
</target>

<!-- Runs the supplied build file through the XSL converter -->


+ 4
- 1
proposal/myrmidon/build.xml View File

@@ -621,7 +621,10 @@ Legal:
</copy>

<copy todir="${dist.lib}">
<fileset dir="${lib.dir}"/>
<fileset dir="${lib.dir}">
<exclude name="xdoclet.jar"/>
<exclude name="jdepend.jar"/>
</fileset>
</copy>

<copy todir="${dist.bin}">


+ 1
- 1
proposal/myrmidon/src/ant1compat/README.txt View File

@@ -56,5 +56,5 @@ TODO
to register tasks? (similar for DataTypes)
* Get a version of <ant> and <antcall> working
* Test heaps more tasks
* Fix problem with classloaders and <taskdef>
* Check that "if" and "unless" conversions are working.


+ 10
- 4
proposal/myrmidon/src/ant1compat/ant-descriptor.xml View File

@@ -6,11 +6,21 @@
classname="org.apache.tools.ant.Ant1CompatTypeInstanceTask" />
<task name="ant1.patternset"
classname="org.apache.tools.ant.Ant1CompatTypeInstanceTask" />
<task name="ant1.filterset"
classname="org.apache.tools.ant.Ant1CompatTypeInstanceTask" />

<!-- TaskAdapter tasks -->
<task name="ant1.condition"
classname="org.apache.tools.ant.Ant1CompatTaskAdapter" />

<!-- Tasks not currently supported.

<task name="ant1.antcall"
classname="org.apache.tools.ant.taskdefs.CallTarget" />
<task name="ant1.ant"
classname="org.apache.tools.ant.taskdefs.Ant" />
-->

<!-- standard ant tasks -->
<task name="ant1.mkdir"
classname="org.apache.tools.ant.taskdefs.Mkdir" />
@@ -58,8 +68,6 @@
classname="org.apache.tools.ant.taskdefs.Property" />
<task name="ant1.taskdef"
classname="org.apache.tools.ant.taskdefs.Taskdef" />
<task name="ant1.ant"
classname="org.apache.tools.ant.taskdefs.Ant" />
<task name="ant1.exec"
classname="org.apache.tools.ant.taskdefs.ExecTask" />
<task name="ant1.tar"
@@ -86,8 +94,6 @@
classname="org.apache.tools.ant.taskdefs.AntStructure" />
<task name="ant1.execon"
classname="org.apache.tools.ant.taskdefs.ExecuteOn" />
<task name="ant1.antcall"
classname="org.apache.tools.ant.taskdefs.CallTarget" />
<task name="ant1.sql"
classname="org.apache.tools.ant.taskdefs.SQLExec" />
<task name="ant1.mail"


+ 6
- 101
proposal/myrmidon/src/ant1compat/org/apache/tools/ant/Ant1CompatProject.java View File

@@ -35,6 +35,12 @@ public class Ant1CompatProject extends Project
super();
m_context = context;
setBaseDir( m_context.getBaseDirectory() );
String projectName = (String)
m_context.getProperty( org.apache.myrmidon.interfaces.model.Project.PROJECT );
if( projectName != null )
{
setName( projectName );
}
}

/**
@@ -238,105 +244,4 @@ public class Ant1CompatProject extends Project
typeManager.registerType( roleType, typeName, factory );
}


// /**
// * Sets a property. Any existing property of the same name
// * is overwritten, unless it is a user property.
// * @param name The name of property to set.
// * Must not be <code>null</code>.
// * @param value The new value of the property.
// * Must not be <code>null</code>.
// */
// public void setProperty( String name, String value )
// {
// if( null != getProperty( name ) )
// {
// log( "Overriding previous definition of property " + name,
// MSG_VERBOSE );
// }
//
// doSetProperty( name, value );
// }
//
// /**
// * Sets a property if no value currently exists. If the property
// * exists already, a message is logged and the method returns with
// * no other effect.
// *
// * @param name The name of property to set.
// * Must not be <code>null</code>.
// * @param value The new value of the property.
// * Must not be <code>null</code>.
// * @since 1.5
// */
// public void setNewProperty( String name, String value )
// {
// if( null != getProperty( name ) )
// {
// log( "Override ignored for property " + name, MSG_VERBOSE );
// return;
// }
// log( "Setting project property: " + name + " -> " +
// value, MSG_DEBUG );
// doSetProperty( name, value );
// }
//
// private void doSetProperty( String name, String value )
// {
// try
// {
// m_context.setProperty( name, value );
// }
// catch( TaskException e )
// {
// throw new BuildException( e );
// }
// }
//
// /**
// * Returns the value of a property, if it is set.
// *
// * @param name The name of the property.
// * May be <code>null</code>, in which case
// * the return value is also <code>null</code>.
// * @return the property value, or <code>null</code> for no match
// * or if a <code>null</code> name is provided.
// */
// public String getProperty( String name )
// {
// if( name == null )
// {
// return null;
// }
// Object value = m_context.getProperty( name );
// if( value == null )
// {
// return null;
// }
// return String.valueOf( value );
// }
//
// /**
// * Returns a copy of the properties table.
// * @return a hashtable containing all properties
// * (including user properties).
// */
// public Hashtable getProperties()
// {
// Map properties = m_context.getProperties();
// Hashtable propertiesCopy = new Hashtable();
//
// Iterator iterator = properties.keySet().iterator();
// while( iterator.hasNext() )
// {
// String key = (String)iterator.next();
// String value = (String)properties.get( key );
//
// propertiesCopy.put( key, value );
//
// }
//
// return propertiesCopy;
// }

}

+ 286
- 0
proposal/myrmidon/src/ant1compat/org/apache/tools/ant/LoaderUtils.java View File

@@ -0,0 +1,286 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 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
* <http://www.apache.org/>.
*/
package org.apache.tools.ant;
import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

/**
* LoaderUtils is a utility class with methods for configuring a class
* loader from a URL.
*
* @author Conor MacNeill
* @created 9 January 2002
*/
public class LoaderUtils {

/**
* This is the file that is consulted on remote systems to specify
* available jars
*/
public static final String LIST_FILE = "file.list";


/**
* Get the URLs of a set of libraries in the given location
*
* @param location the location to be searched
* @param defaultFile default file if none can be found
* @return an array of URLs for the relevant jars
* @exception MalformedURLException the URLs cannot be created
*/
public static URL[] getLocationURLs(URL location, String defaultFile)
throws MalformedURLException {
return getLocationURLs(location, defaultFile, new String[]{".jar"});
}

/**
* Get the URLs of a set of libraries in the given location
*
* @param location the location to be searched
* @param extensions array of allowable file extensions
* @param defaultFile default file if none can be found
* @return an array of URLs for the relevant jars
* @exception MalformedURLException if the URL to the jars could not be
* formed
*/
public static URL[] getLocationURLs(URL location, String defaultFile,
String[] extensions)
throws MalformedURLException {
URL[] urls = null;
if (location.getProtocol().equals("file")) {
// URL is local filesystem.
urls = getLocalURLs(new File(location.getFile()), extensions);
} else {
// URL is remote - try to read a file with the list of jars
URL jarListURL = new URL(location, LIST_FILE);
BufferedReader reader = null;
List jarList = new ArrayList();
try {
InputStreamReader isr
= new InputStreamReader(jarListURL.openStream());
reader = new BufferedReader(isr);
String line = null;
while ((line = reader.readLine().trim()) != null) {
for (int i = 0; i < extensions.length; ++i) {
if (line.endsWith(extensions[i])) {
jarList.add(new URL(location, line));
break;
}
}
}
urls = (URL[])jarList.toArray(new URL[0]);
} catch (IOException e) {
// use the default location
if (defaultFile != null) {
urls = new URL[]{new URL(location, defaultFile)};
}
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}
}
}
}

return urls;
}

/**
* Get the classpath from a classloader. This can only extract path
* components from the loaders which are instances of URLClassLoaders
*
* @param loader the loader whose path is required
* @return the loader's configuration expressed as a classpath
*/
public static String getClasspath(ClassLoader loader) {
StringBuffer pathBuffer = null;
if (loader instanceof URLClassLoader) {
URLClassLoader urlLoader = (URLClassLoader)loader;
URL[] urls = urlLoader.getURLs();
for (int i = 0; i < urls.length; ++i) {
if (!urls[i].getProtocol().equals("file")) {
continue;
}
String pathElement = urls[i].getFile();
if (pathBuffer == null) {
pathBuffer = new StringBuffer(pathElement);
} else {
pathBuffer.append(File.pathSeparatorChar);
pathBuffer.append(pathElement);
}
}
}
String path = pathBuffer == null ? "" : pathBuffer.toString();
ClassLoader parentLoader = loader.getParent();
if (parentLoader != null) {
String parentPath = getClasspath(parentLoader);
if (parentPath.length() != 0) {
path = parentPath + File.pathSeparator + path;
}
}

return path;
}


/**
* Debug method to dump a class loader hierarchy to a PrintStream
* URLClassLoaders dump their URLs
*
* @param loader the class loaders whose configuration is dumped
* @param ps PrintStream to which info is sent
*/
public static void dumpLoader(PrintStream ps, ClassLoader loader) {
if (loader instanceof URLClassLoader) {
URLClassLoader urlLoader = (URLClassLoader)loader;
URL[] urls = urlLoader.getURLs();
if (urls.length == 0) {
ps.println(" No URLs");
} else {
for (int i = 0; i < urls.length; ++i) {
ps.println(" URL: " + urls[i]);
}
}
} else {
ps.println("Class Loader: " + loader.getClass().getName());
}
ps.println();

ClassLoader parentLoader = loader.getParent();
if (parentLoader != null) {
ps.println("Parent Loader:");
dumpLoader(ps, parentLoader);
}
}


/**
* Get an array of URLs for each file in the filesystem. If the given
* location is a directory, it is searched for files of the given
* extension. If it is a file, it is returned as a URL if it matches the
* given extension list.
*
* @param location the location within the local filesystem to be
* searched
* @param extensions an array of file extensions to be considered in the
* search
* @return an array of URLs for the file found in the directory.
* @exception MalformedURLException if the URLs to the jars cannot be
* formed
*/
private static URL[] getLocalURLs(File location,
final String[] extensions)
throws MalformedURLException {
URL[] urls = new URL[0];

if (!location.exists()) {
return urls;
}

if (!location.isDirectory()) {
String path = location.getPath();
for (int i = 0; i < extensions.length; ++i) {
if (path.endsWith(extensions[i])) {
urls[0] = location.toURL();
break;
}
}
return urls;
}

File[] jars = location.listFiles(
new FilenameFilter() {
public boolean accept(File dir, String name) {
for (int i = 0; i < extensions.length; ++i) {
if (name.endsWith(extensions[i])) {
return true;
}
}
return false;
}
});
urls = new URL[jars.length];
for (int i = 0; i < jars.length; ++i) {
urls[i] = jars[i].toURL();
}
return urls;
}

/**
* Set the context loader of the current thread and returns the existing
* classloader
*
* @param newLoader the new context loader
* @return the old context loader
*/
public static ClassLoader setContextLoader(ClassLoader newLoader) {
Thread thread = Thread.currentThread();
ClassLoader currentLoader = thread.getContextClassLoader();
thread.setContextClassLoader(newLoader);
return currentLoader;
}

}


+ 2
- 25
proposal/myrmidon/src/ant1compat/org/apache/tools/ant/Task.java View File

@@ -27,7 +27,7 @@ import org.apache.myrmidon.api.TaskException;
public class Task extends OriginalAnt1Task
implements org.apache.myrmidon.api.Task, Configurable
{
private TaskContext m_context;
protected TaskContext m_context;

/**
* Specify the context in which the task operates in.
@@ -62,6 +62,7 @@ public class Task extends OriginalAnt1Task
public void configure( Configuration configuration ) throws ConfigurationException
{
configure( this, configuration );
this.init();
}

protected void configure( Object target, Configuration configuration ) throws ConfigurationException
@@ -115,30 +116,6 @@ public class Task extends OriginalAnt1Task
helper.storeElement( project, target, nestedElement, name );
}

/*
task.setLocation(new Location(helperImpl.buildFile.toString(), helperImpl.locator.getLineNumber(),
helperImpl.locator.getColumnNumber()));
String id = attr.getValue("id");
if (id != null) {
project.addReference(id, target);
}

// Top level tasks don't have associated targets
if (target != null) {
task.setOwningTarget(target);
container.addTask(task);
task.init();
wrapper = task.getRuntimeConfigurableWrapper();
wrapper.setAttributes(attrs);
if (parentWrapper != null) {
parentWrapper.addChild(wrapper);
}
} else {
task.init();
configure(task, attrs, helperImpl.project);
}
*/

}

protected String getAnt1Name( String fullName )


+ 625
- 0
proposal/myrmidon/src/ant1compat/org/apache/tools/ant/types/Path.java View File

@@ -0,0 +1,625 @@
/*
* 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
* <http://www.apache.org/>.
*/

package org.apache.tools.ant.types;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.PathTokenizer;
import org.apache.tools.ant.LoaderUtils;

import java.io.File;

import java.util.Enumeration;
import java.util.Locale;
import java.util.Stack;
import java.util.Vector;



/**
* ***********************************************************************
* Ant1Compatibility Layer version of Path, hacked to provide Ant1 runtime
* files in System Classpath.
* ***********************************************************************
*
* This object represents a path as used by CLASSPATH or PATH
* environment variable.
* <p>
* <code>
* &lt;sometask&gt;<br>
* &nbsp;&nbsp;&lt;somepath&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location="/path/to/file.jar" /&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement path="/path/to/file2.jar:/path/to/class2;/path/to/class3" /&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location="/path/to/file3.jar" /&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location="/path/to/file4.jar" /&gt;<br>
* &nbsp;&nbsp;&lt;/somepath&gt;<br>
* &lt;/sometask&gt;<br>
* </code>
* <p>
* The object implemention <code>sometask</code> must provide a method called
* <code>createSomepath</code> which returns an instance of <code>Path</code>.
* Nested path definitions are handled by the Path object and must be labeled
* <code>pathelement</code>.<p>
*
* The path element takes a parameter <code>path</code> which will be parsed
* and split into single elements. It will usually be used
* to define a path from an environment variable.
*
* @author Thomas.Haas@softwired-inc.com
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
*/

public class Path extends DataType implements Cloneable {

private Vector elements;


public static Path systemClasspath =
new Path(null, System.getProperty("java.class.path"));


//Modified from original source.
//Append Ant1 codebase to systemclasspath.
// ------------------Modified--------------------------------
static
{
String classpath = LoaderUtils.getClasspath( Path.class.getClassLoader() );
systemClasspath.append( new Path( null, classpath ) );
}
//-----------------End Modified------------------------------


/**
* Helper class, holds the nested <code>&lt;pathelement&gt;</code> values.
*/
public class PathElement {
private String[] parts;

public void setLocation(File loc) {
parts = new String[] {translateFile(loc.getAbsolutePath())};
}

public void setPath(String path) {
parts = Path.translatePath(getProject(), path);
}

public String[] getParts() {
return parts;
}
}

/**
* Invoked by IntrospectionHelper for <code>setXXX(Path p)</code>
* attribute setters.
*/
public Path(Project p, String path) {
this(p);
createPathElement().setPath(path);
}

public Path(Project project) {
setProject(project);
elements = new Vector();
}

/**
* Adds a element definition to the path.
* @param location the location of the element to add (must not be
* <code>null</code> nor empty.
*/
public void setLocation(File location) throws BuildException {
if (isReference()) {
throw tooManyAttributes();
}
createPathElement().setLocation(location);
}


/**
* Parses a path definition and creates single PathElements.
* @param path the path definition.
*/
public void setPath(String path) throws BuildException {
if (isReference()) {
throw tooManyAttributes();
}
createPathElement().setPath(path);
}

/**
* Makes this instance in effect a reference to another Path instance.
*
* <p>You must not set another attribute or nest elements inside
* this element if you make it a reference.</p>
*/
public void setRefid(Reference r) throws BuildException {
if (!elements.isEmpty()) {
throw tooManyAttributes();
}
elements.addElement(r);
super.setRefid(r);
}

/**
* Creates the nested <code>&lt;pathelement&gt;</code> element.
*/
public PathElement createPathElement() throws BuildException {
if (isReference()) {
throw noChildrenAllowed();
}
PathElement pe = new PathElement();
elements.addElement(pe);
return pe;
}

/**
* Adds a nested <code>&lt;fileset&gt;</code> element.
*/
public void addFileset(FileSet fs) throws BuildException {
if (isReference()) {
throw noChildrenAllowed();
}
elements.addElement(fs);
checked = false;
}

/**
* Creates a nested <code>&lt;path&gt;</code> element.
*/
public Path createPath() throws BuildException {
if (isReference()) {
throw noChildrenAllowed();
}
Path p = new Path(getProject());
elements.addElement(p);
checked = false;
return p;
}

/**
* Append the contents of the other Path instance to this.
*/
public void append(Path other) {
if (other == null) {
return;
}
String[] l = other.list();
for (int i=0; i<l.length; i++) {
if (elements.indexOf(l[i]) == -1) {
elements.addElement(l[i]);
}
}
}

/**
* Adds the components on the given path which exist to this
* Path. Components that don't exist, aren't added.
*
* @param source - source path whose components are examined for existence
*/
public void addExisting(Path source) {
String[] list = source.list();
for (int i=0; i<list.length; i++) {
File f = null;
if (getProject() != null) {
f = getProject().resolveFile(list[i]);
}
else {
f = new File(list[i]);
}

if (f.exists()) {
setLocation(f);
} else {
log("dropping " + f + " from path as it doesn't exist",
Project.MSG_VERBOSE);
}
}
}

/**
* Returns all path elements defined by this and nested path objects.
* @return list of path elements.
*/
public String[] list() {
if (!checked) {
// make sure we don't have a circular reference here
Stack stk = new Stack();
stk.push(this);
dieOnCircularReference(stk, getProject());
}

Vector result = new Vector(2*elements.size());
for (int i=0; i<elements.size(); i++) {
Object o = elements.elementAt(i);
if (o instanceof Reference) {
Reference r = (Reference) o;
o = r.getReferencedObject(getProject());
// we only support references to paths right now
if (!(o instanceof Path)) {
String msg = r.getRefId()+" doesn\'t denote a path";
throw new BuildException(msg);
}
}
if (o instanceof String) {
// obtained via append
addUnlessPresent(result, (String) o);
} else if (o instanceof PathElement) {
String[] parts = ((PathElement) o).getParts();
if (parts == null) {
throw new BuildException("You must either set location or path on <pathelement>");
}
for (int j=0; j<parts.length; j++) {
addUnlessPresent(result, parts[j]);
}
} else if (o instanceof Path) {
Path p = (Path) o;
if (p.getProject() == null) {
p.setProject(getProject());
}
String[] parts = p.list();
for (int j=0; j<parts.length; j++) {
addUnlessPresent(result, parts[j]);
}
} else if (o instanceof FileSet) {
FileSet fs = (FileSet) o;
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
String[] s = ds.getIncludedFiles();
File dir = fs.getDir(getProject());
for (int j=0; j<s.length; j++) {
File f = new File(dir, s[j]);
String absolutePath = f.getAbsolutePath();
addUnlessPresent(result, translateFile(absolutePath));
}
}
}
String[] res = new String[result.size()];
result.copyInto(res);
return res;
}


/**
* Returns a textual representation of the path, which can be used as
* CLASSPATH or PATH environment variable definition.
* @return a textual representation of the path.
*/
public String toString() {
final String[] list = list();

// empty path return empty string
if (list.length == 0) {
return "";
}

// path containing one or more elements
final StringBuffer result = new StringBuffer(list[0].toString());
for (int i=1; i < list.length; i++) {
result.append(File.pathSeparatorChar);
result.append(list[i]);
}

return result.toString();
}

/**
* Splits a PATH (with : or ; as separators) into its parts.
*/
public static String[] translatePath(Project project, String source) {
final Vector result = new Vector();
if (source == null) {
return new String[0];
}

PathTokenizer tok = new PathTokenizer(source);
StringBuffer element = new StringBuffer();
while (tok.hasMoreTokens()) {
element.setLength(0);
String pathElement = tok.nextToken();
try {
element.append(resolveFile(project, pathElement));
}
catch (BuildException e) {
project.log("Dropping path element " + pathElement + " as it is not valid relative to the project",
Project.MSG_VERBOSE);
}
for (int i=0; i<element.length(); i++) {
translateFileSep(element, i);
}
result.addElement(element.toString());
}
String[] res = new String[result.size()];
result.copyInto(res);
return res;
}

/**
* Returns its argument with all file separator characters
* replaced so that they match the local OS conventions.
*/
public static String translateFile(String source) {
if (source == null) {
return "";
}

final StringBuffer result = new StringBuffer(source);
for (int i=0; i < result.length(); i++) {
translateFileSep(result, i);
}

return result.toString();
}

/**
* Translates all occurrences of / or \ to correct separator of the
* current platform and returns whether it had to do any
* replacements.
*/
protected static boolean translateFileSep(StringBuffer buffer, int pos) {
if (buffer.charAt(pos) == '/' || buffer.charAt(pos) == '\\') {
buffer.setCharAt(pos, File.separatorChar);
return true;
}
return false;
}

/**
* How many parts does this Path instance consist of.
*/
public int size() {
return list().length;
}

/**
* Return a Path that holds the same elements as this instance.
*/
public Object clone() {
Path p = new Path(getProject());
p.append(this);
return p;
}

/**
* Overrides the version of DataType to recurse on all DataType
* child elements that may have been added.
*/
protected void dieOnCircularReference(Stack stk, Project p)
throws BuildException {

if (checked) {
return;
}

Enumeration enum = elements.elements();
while (enum.hasMoreElements()) {
Object o = enum.nextElement();
if (o instanceof Reference) {
o = ((Reference) o).getReferencedObject(p);
}

if (o instanceof DataType) {
if (stk.contains(o)) {
throw circularReference();
} else {
stk.push(o);
((DataType) o).dieOnCircularReference(stk, p);
stk.pop();
}
}
}
checked = true;
}

/**
* Resolve a filename with Project's help - if we know one that is.
*
* <p>Assume the filename is absolute if project is null.</p>
*/
private static String resolveFile(Project project, String relativeName) {
if (project != null) {
File f = project.resolveFile(relativeName);
return f.getAbsolutePath();
}
return relativeName;
}

/**
* Adds a String to the Vector if it isn't already included.
*/
private static void addUnlessPresent(Vector v, String s) {
if (v.indexOf(s) == -1) {
v.addElement(s);
}
}

/**
* Concatenates the system class path in the order specified by
* the ${build.sysclasspath} property - using &quot;last&quot; as
* default value.
*/
public Path concatSystemClasspath() {
return concatSystemClasspath("last");
}

/**
* Concatenates the system class path in the order specified by
* the ${build.sysclasspath} property - using the supplied value
* if ${build.sysclasspath} has not been set.
*/
public Path concatSystemClasspath(String defValue) {

Path result = new Path(getProject());

String order = defValue;
if (getProject() != null) {
String o = getProject().getProperty("build.sysclasspath");
if (o != null) {
order = o;
}
}
if (order.equals("only")) {
// only: the developer knows what (s)he is doing
result.addExisting(Path.systemClasspath);
} else if (order.equals("first")) {
// first: developer could use a little help
result.addExisting(Path.systemClasspath);
result.addExisting(this);

} else if (order.equals("ignore")) {
// ignore: don't trust anyone
result.addExisting(this);

} else {
// last: don't trust the developer
if (!order.equals("last")) {
log("invalid value for build.sysclasspath: " + order,
Project.MSG_WARN);
}

result.addExisting(this);
result.addExisting(Path.systemClasspath);
}

return result;

}

/**
* Add the Java Runtime classes to this Path instance.
*/
public void addJavaRuntime() {
if (System.getProperty("java.vendor").toLowerCase(Locale.US).indexOf("microsoft") >= 0) {
// Pull in *.zip from packages directory
FileSet msZipFiles = new FileSet();
msZipFiles.setDir(new File(System.getProperty("java.home") + File.separator + "Packages"));
msZipFiles.setIncludes("*.ZIP");
addFileset(msZipFiles);
} else if("Kaffe".equals(System.getProperty("java.vm.name"))) {
FileSet kaffeJarFiles = new FileSet();
kaffeJarFiles.setDir(new File(System.getProperty("java.home")
+ File.separator + "share"
+ File.separator + "kaffe"));
kaffeJarFiles.setIncludes("*.jar");
addFileset(kaffeJarFiles);
}
else if (Project.getJavaVersion() == Project.JAVA_1_1) {
addExisting(new Path(null,
System.getProperty("java.home")
+ File.separator + "lib"
+ File.separator
+ "classes.zip"));
} else {
// JDK > 1.1 seems to set java.home to the JRE directory.
addExisting(new Path(null,
System.getProperty("java.home")
+ File.separator + "lib"
+ File.separator + "rt.jar"));
// Just keep the old version as well and let addExisting
// sort it out.
addExisting(new Path(null,
System.getProperty("java.home")
+ File.separator +"jre"
+ File.separator + "lib"
+ File.separator + "rt.jar"));
// Added for MacOS X
addExisting(new Path(null,
System.getProperty("java.home")
+ File.separator + ".."
+ File.separator + "Classes"
+ File.separator + "classes.jar"));
addExisting(new Path(null,
System.getProperty("java.home")
+ File.separator + ".."
+ File.separator + "Classes"
+ File.separator + "ui.jar"));
}
}

/**
* Emulation of extdirs feature in java >= 1.2.
* This method adds all files in the given
* directories (but not in sub-directories!) to the classpath,
* so that you don't have to specify them all one by one.
* @param extdirs - Path to append files to
*/
public void addExtdirs(Path extdirs) {
if (extdirs == null) {
String extProp = System.getProperty("java.ext.dirs");
if (extProp != null) {
extdirs = new Path(getProject(), extProp);
} else {
return;
}
}

String[] dirs = extdirs.list();
for (int i=0; i<dirs.length; i++) {
File dir = getProject().resolveFile(dirs[i]);
if (dir.exists() && dir.isDirectory()) {
FileSet fs = new FileSet();
fs.setDir(dir);
fs.setIncludes("*");
addFileset(fs);
}
}
}
}

Loading…
Cancel
Save