Dear Committer

The nested classpath definition got votes. My response to one question
asked did not get any follow ups, therefor I beleive it is time to
include this into ANT. Below you find a description what this patch is
all about.

After this patch has been commited, I hope some volunters will help
adding the feature to the tasks using classpath definitions. I'll
certainly help, but the JUnit task got higher priority right now.

Thank you

- tom

DESCRPTION
==========


What
===
An XML definiton using nested classpath definitions looks like the
following:

<sometask>
    <somepath>
        <path defintion="/some/dir;/some/fil.jar:/some/other/path" />
        <element location="/a/file.jar" />
        <element location="/a/path" />
        <path
definition="/another/path/classes:/mor/classes;/another/file.jar" />
    </somepath>
</sometask>

In a task "sometask" define a classpath callled "somepath". A classpath
consists of any numbers of "element" and "path" element definitions. An
element adds a single location either file or directory. A path adds a
list of locations described by a string using the separators ";" and
":". Path definitions use th code from Project.translatePath to parse
and split the definitions. There primary use is the inclusion of some
predefined classpath property (like the CLASSPATH environment variable
or other).

Elements and Pathes are distinguished to allow the developer clearly
express, if she adds a single location or a predefined and to be parsed
list of locations to the classpath defintion in any sequence she may
wishes.


Why
===
Stefan Bodewig <[EMAIL PROTECTED]> and I are currently developing a target
to run unit tests using the JUnit framework. We wanted to provide nested
classpath definitions. As other task could reuse our work, I want first
to make shure, everyone agrees on how it is done, so it can go in
together with the JUnit task.

The JavaC, Javadoc and Java task would profit immediatly from this work.


How
===
Sometask must provide a method creatSomepath which returns an instance
of Path. The Path object implements the createPath (whic returns this),
setLocation and createElement methods.
setLocation uses Path.translatePath to parse the given argument.
createElement returns an instance of PathElement, which provides the
setLocation method to add a location to the classpath definition.
The classpath definition is stored as a list of File objects, which is
build by the setLocation and SetDefintion methods.


- tom

--
* 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 Apr 03 10:58:14 2000
@@ -0,0 +1,232 @@
+/*
+ * 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;
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;element location="/path/to/file.jar" /&gt;
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;element 
path="/path/to/file2.jar:/path/to/class2;/path/to/class3" /&gt;
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;element location="/path/to/file3.jar" /&gt;
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;element location="/path/to/file4.jar" /&gt;
+ * &nbsp;&nbsp;&lt;/somepath&gt;
+ * &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.
+ *
+ * @author [EMAIL PROTECTED]
+ */
+
+public class Path {
+    private Vector definition = new Vector();
+    private PathElement element = null;
+
+
+    /**
+    * Handles a single element definition.
+    * Each Path object creates at most one PathElement object. PathElement
+    * objects can be shared, as they are currently stateless.
+    **/
+    public class PathElement {
+
+        /**
+        * 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(String location) {
+            if (location != null && location.length() > 0) {
+                definition.addElement(new File(location));
+            }
+        }
+
+
+        /**
+         * Parses a path definition and creates single PatheElements.
+         * @param path the path definition.
+         */
+        public void setPath(String path) {
+            // TODO: could be improved, iftranslatePath returns list instead
+            //       of a string.
+
+            final StringTokenizer tokenizer = new StringTokenizer(
+                translatePath(path), File.pathSeparator, false);
+            while(tokenizer.hasMoreTokens()) {
+                setLocation(tokenizer.nextToken());
+            }
+        }
+    }
+
+
+    /**
+     * Creates a <code>PathElement</code> for path element definitions.
+     * @return an empty PathElement object.
+     */
+    public PathElement createElement() {
+        if (element == null) {
+            element = new PathElement();
+        }
+        return element;
+    }
+
+
+    /**
+     * Creates a nested path object.
+     * @return a nested path object.
+     */
+    public Path createPath() {
+        return this;
+    }
+
+
+    /**
+     * Returns all path elements defined by this and netsed path objects.
+     * @return list of path elements.
+     */
+    public File[] list() {
+        final File[] result = new File[definition.size()];
+        definition.copyInto(result);
+        return result;
+    }
+
+
+    /**
+     * 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();
+
+        // 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();
+    }
+
+
+    /**
+        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) {
+        // TODO: Improve by getting rid of temp creation of strings by only
+        //       working with characters.
+        //       Return list of strings instead of String to ease further
+        //       processing.
+
+        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();
+    }
+
+}

Reply via email to