Hi all

To provide nested elements in the JUnit task I needed something to build
nested classpath definitions. Browsing through the code (javac, javadoc,
java) I come along the idea of creating a general class representing
classpath alike structures.

The basic object is called "Path" which describes a list of PathElement
and other (recursiv) Path objects. A PathElement itself describes a
single location being either a (jar)file or a directory (containing
classes).
A task like "java" would have one Path object representing the classpath
to be used. A task like "javac" may have different Path object
representing different classpathes like classpath, extdirs,
bootclasspath, ...

A task like JUnit, javac, javadoc can use this implementation to define
nested classpath definitions:

<sometask>
    <somepath path="optional:path;definition" >
        <element location="/path/to/some.jar" />
        <element location="/path/to/some/classes" />
        <path path="optional:path;definition">
            <element location="/path/to/some/other.jar" />
            <element location="/path/to/some/other/classes" />
        </path>
    </somepath>
    ...
    <someotherpath>
        <element location="/yet/another/path/to/some.jar" />
        <element location="/yet/another/path/to/some/directory" />
    </someotherpath>
</sometask>

The object implementing "sometask" must provide the methods
"createSomepath" and "createSomeotherpath" which return the Path
objects. The nesting of path definitions is handled by the Path object.

Some rational:


   * The javac task does some proccessing of the variant path
     definitions. I beleive proccessing structured path definitions is
     easier than always manipulate strings.
   * Nesting many path definitions may not always make sense. It is done
     this way to easily mix single element definitions a predefined path
     strings in any order. I think that structures like the deeply
     nested somepath will probably only be used the append a predefined
     path instead of prepending it.
   * The class is named path as it may represent variant classpath like
     pathes and could even be used to represent the path environment
     variable as used on unix and windows systems.
   * A single element of a path is called PathElement as lack of
     phantasie for a better name.

I am using it reight now in the current JUnit task implementation and it
made nested classpath definitions very easy.
If the proposed classes get accepted I would like to propose to use them
to implement nested classpath definitions in javac, havadoc, java and
all other tasks dealing with classpath alike structures (I wanted to
provide a patch to javac, but did not understand the whole thing right
away). Maybe even project could store the classpath env. variable as
Path object.

Both classes are currently placed in org.apache.tools.ant, but it may
fit anywhere else as well.
I am still unsure about the naming of the classes, methods and
properties any improvemnts on this are especially welcomed.

I hope you like the stuff and awaiting you opinions.

- tom (even an hour erlier than usually ;-)


--
* Thomas Haas                    <mailto:[EMAIL PROTECTED]>
* SoftWired AG                   <http://www.softwired-inc.com/>
* Technoparkstr. 1  ***  CH-8005 Zurich  ***  +41-1-4452370

--- Path.java.orig      Mon Mar 27 11:05:35 2000
+++ Path.java   Mon Mar 27 11:06:03 2000
@@ -0,0 +1,224 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Tomcat", 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 [EMAIL PROTECTED]
+ *
+ * 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.File;
+import java.util.Vector;
+import java.util.StringTokenizer;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+
+/**
+ * This object represents a path as used by CLASSPATH or PATH
+ * environment variable.
+ *
+ * It consists of a list of <code>PathElement</code> and <code>Path</code>
+ * objects. It is used to represent a classpath or path like nested parameters
+ * in task definitions:
+ *
+ * <code>
+ * &lt;sometask&gt;<br>
+ * &nbsp;&nbsp;&lt;somepath&gt; path="optional:path;definition" &gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;element location="/path/to/some.jar" /&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;element location="/path/to/some/classes" 
/&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;path path="optional:path;definition"&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;element 
location="/path/to/some/other.jar" /&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;element 
location="/path/to/some/other/classes" /&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;/path&gt;<br>
+ * &nbsp;&nbsp;&lt;/somepath&gt;<br>
+ * &lt;/sometask&gt;<br>
+ * </code>
+ *
+ * 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>path</code>.<p>
+ *
+ * The path element takes a parameter <code>path</code> which will be parsed
+ * and split into <code>PathElement</code> objects. It will usually be used
+ * to define a path from an environment variable.
+ *
+ */
+
+public class Path {
+
+    private Vector elements = new Vector();
+
+
+    /**
+     * Creates a <code>PathElement</code> for path element definitions.
+     * @return an empty PathElement object.
+     */
+    public PathElement createElement() {
+        final PathElement result = new PathElement();
+        elements.addElement(result);
+        return result;
+    }
+
+
+    /**
+     * Creates a nested path object.
+     * @return a nested path object.
+     */
+    public Path createPath() {
+        final Path result = new Path();
+        elements.addElement(result);
+        return result;
+    }
+
+
+    /**
+     * Parses a path definition and creates single PatheElements.
+     * @param path the path definition.
+     */
+    public void setPath(String path) {
+        final StringTokenizer tokenizer = new StringTokenizer(
+            translatePath(path), File.pathSeparator, false);
+        while(tokenizer.hasMoreTokens()) {
+            createElement().setLocation(tokenizer.nextToken());
+        }
+    }
+
+
+    /**
+     * Returns all path elements defined by this and netsed path objects.
+     * @return list of path elements.
+     */
+    public File[] list() {
+        final Vector list = new Vector();
+        list(list);
+        final File[] result = new File[list.size()];
+        list.copyInto(result);
+        return result;
+    }
+
+
+    /**
+     * Recursivly creates a list of path elements.
+     * @param list the resulting list of path elements.
+     */
+    protected void list(Vector list) {
+        for (int i=0; i < elements.size(); i++) {
+            final Object o = elements.elementAt(i);
+            if (o instanceof PathElement) {
+                final File l = ((PathElement)o).getLocation();
+                if (l != null) {
+                    list.addElement(l);
+                }
+            } else {
+                ((Path)o).list(list);
+            }
+        }
+    }
+
+
+    /**
+     * 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 File[] list = list();
+        if (list.length == 0) return "";
+        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();
+    }
+
+
+
+    /**
+        Translate a path into its native (platform specific)
+        path. This should be extremely fast, code is
+        borrowed from ECS project.
+        <p>
+        All it does is translate the : into ; and / into \
+        if needed. In other words, it isn't perfect.
+
+        @returns translated string or empty string if to_process is null or 
empty
+        @author Jon S. Stevens <a href="mailto:[EMAIL PROTECTED]">[EMAIL 
PROTECTED]</a>
+    */
+    public static String translatePath(String to_process) {
+        if ( to_process == null || to_process.length() == 0 ) return "";
+
+        final StringBuffer bs = new StringBuffer(to_process.length() + 50);
+        final StringCharacterIterator sci = new 
StringCharacterIterator(to_process);
+        final String path = File.pathSeparator;
+        final String file = File.separator;
+        for (char c = sci.first(); c != CharacterIterator.DONE; c = 
sci.next()) {
+            String tmp = String.valueOf(c);
+
+            if (tmp.equals(":")) {
+                // could be a DOS drive or a Unix path separator...
+                // if followed by a backslash, assume it is a drive
+                c = sci.next();
+                tmp = String.valueOf(c);
+                bs.append( tmp.equals("\\") ? ":" : path );
+                if (c == CharacterIterator.DONE) break;
+            }
+
+            if (tmp.equals(":") || tmp.equals(";"))
+                tmp = path;
+            else if (tmp.equals("/") || tmp.equals ("\\"))
+                tmp = file;
+            bs.append(tmp);
+        }
+        return bs.toString();
+    }
+
+}
--- PathElement.java.orig       Mon Mar 27 11:05:43 2000
+++ PathElement.java    Mon Mar 27 11:06:06 2000
@@ -0,0 +1,83 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Tomcat", 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 [EMAIL PROTECTED]
+ *
+ * 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.File;
+
+
+/**
+ * This object represents an element of a path as used by CLASSPATH or PATH
+ * environment variable.
+ */
+public class PathElement {
+    private File location = null;
+
+    /**
+     * Returns the location of this element.
+     * @return the location of this element.
+     */
+    public File getLocation() {
+        return location;
+    }
+
+    /**
+     * Sets the lcoation of this element.
+     * @param location the location of this element (file or directory).
+     */
+    public void setLocation(String location) {
+        this.location = new File(location);
+    }
+
+}

Reply via email to