You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by mb...@apache.org on 2006/10/11 23:26:47 UTC

svn commit: r462955 - in /ant/core/trunk/src/main/org/apache/tools/ant/types: Path.java resources/Union.java

Author: mbenson
Date: Wed Oct 11 14:26:46 2006
New Revision: 462955

URL: http://svn.apache.org/viewvc?view=rev&rev=462955
Log:
Let Path use Union by composition instead of inheritance so that third-party
code using paths built against Ant 1.7 should still run against Ant 1.6 .

Modified:
    ant/core/trunk/src/main/org/apache/tools/ant/types/Path.java
    ant/core/trunk/src/main/org/apache/tools/ant/types/resources/Union.java

Modified: ant/core/trunk/src/main/org/apache/tools/ant/types/Path.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/types/Path.java?view=diff&rev=462955&r1=462954&r2=462955
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/types/Path.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/types/Path.java Wed Oct 11 14:26:46 2006
@@ -19,10 +19,13 @@
 package org.apache.tools.ant.types;
 
 import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.Locale;
+import java.util.Stack;
 import java.util.Vector;
-import java.util.Iterator;
-import java.util.Collection;
+
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.PathTokenizer;
 import org.apache.tools.ant.Project;
@@ -33,7 +36,8 @@
 
 /**
  * This object represents a path as used by CLASSPATH or PATH
- * environment variable.
+ * environment variable. A path might also be described as a collection
+ * of unique filesystem resources.
  * <p>
  * <code>
  * &lt;sometask&gt;<br>
@@ -55,16 +59,14 @@
  * 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.
- *
  */
 
-public class Path extends Union {
+public class Path extends DataType implements Cloneable, ResourceCollection {
 
     /** The system classpath as a Path object */
     public static Path systemClasspath =
         new Path(null, System.getProperty("java.class.path"));
 
-
     /**
      * The system bootclasspath as a Path object.
      *
@@ -73,6 +75,8 @@
     public static Path systemBootClasspath =
         new Path(null, System.getProperty("sun.boot.class.path"));
 
+    private static Iterator EMPTY_ITERATOR = Collections.EMPTY_SET.iterator();
+
     /**
      * Helper class, holds the nested <code>&lt;pathelement&gt;</code> values.
      */
@@ -120,6 +124,8 @@
 
     }
 
+    private Union union = null;
+
     /**
      * Invoked by IntrospectionHelper for <code>setXXX(Path p)</code>
      * attribute setters.
@@ -169,7 +175,7 @@
      * @throws BuildException on error
      */
     public void setRefid(Reference r) throws BuildException {
-        if (!getResourceCollections().isEmpty()) {
+        if (union != null) {
             throw tooManyAttributes();
         }
         super.setRefid(r);
@@ -227,6 +233,23 @@
     }
 
     /**
+     * Add a nested <code>ResourceCollection</code>.
+     * @param c the ResourceCollection to add.
+     * @since Ant 1.7
+     */
+    public void add(ResourceCollection c) {
+        checkChildrenAllowed();
+        if (c == null) {
+            return;
+        }
+        if (union == null) {
+            union = new Union();
+            union.setProject(getProject());
+        }
+        union.add(c);
+    }
+
+    /**
      * Creates a nested <code>&lt;path&gt;</code> element.
      * @return a <code>Path</code> to be configured
      * @throws BuildException on error
@@ -258,7 +281,8 @@
          addExisting(source, false);
      }
 
-    /** Same as addExisting, but support classpath behavior if tryUserDir
+    /**
+     * Same as addExisting, but support classpath behavior if tryUserDir
      * is true. Classpaths are relative to user dir, not the project base.
      * That used to break jspc test
      *
@@ -288,29 +312,24 @@
     }
 
     /**
-     * Override <code>Union.getCollection()</code>
-     * so we can check our children first.
-     * @return a Collection.
-     */
-    protected Collection getCollection() {
-        for (Iterator i = getResourceCollections().iterator(); i.hasNext();) {
-            ResourceCollection rc = (ResourceCollection) i.next();
-            if (!(rc.isFilesystemOnly())) {
-                throw new BuildException(getDataTypeName()
-                    + " allows only filesystem resources.");
-            }
-            if (rc instanceof PathElement
-                && ((PathElement) rc).getParts() == null) {
-                throw new BuildException(
-                    "Either location or path must be set on a pathelement.");
-            } else if (rc instanceof Path) {
-                Path p = (Path) rc;
-                if (p.getProject() == null) {
-                    p.setProject(getProject());
-                }
-            }
+     * Returns all path elements defined by this and nested path objects.
+     * @return list of path elements.
+     */
+    public String[] list() {
+        if (isReference()) {
+            return ((Path) getCheckedRef()).list();
         }
-        return super.getCollection();
+        return union == null ? new String[0] : union.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() {
+        return isReference() ? getCheckedRef().toString() :
+            union == null ? "" : union.toString();
     }
 
     /**
@@ -324,7 +343,6 @@
         if (source == null) {
             return new String[0];
         }
-
         PathTokenizer tok = new PathTokenizer(source);
         StringBuffer element = new StringBuffer();
         while (tok.hasMoreTokens()) {
@@ -357,12 +375,10 @@
         if (source == null) {
           return "";
         }
-
         final StringBuffer result = new StringBuffer(source);
         for (int i = 0; i < result.length(); i++) {
             translateFileSep(result, i);
         }
-
         return result.toString();
     }
 
@@ -383,6 +399,54 @@
     }
 
     /**
+     * Fulfill the ResourceCollection contract.
+     * @return number of elements as int.
+     */
+    public synchronized int size() {
+        if (isReference()) {
+            return ((Path) getCheckedRef()).size();
+        }
+        dieOnCircularReference();
+        return union == null ? 0 : assertFilesystemOnly(union).size();
+    }
+
+    /**
+     * Clone this Path.
+     * @return Path with shallowly cloned Resource children.
+     */
+    public Object clone() {
+        try {
+            Path result = (Path) super.clone();
+            result.union = union == null ? union : (Union) union.clone();
+            return result;
+        } catch (CloneNotSupportedException e) {
+            throw new BuildException(e);
+        }
+    }
+
+    /**
+     * Overrides the version of DataType to recurse on all DataType
+     * child elements that may have been added.
+     * @param stk the stack of data types to use (recursively).
+     * @param p   the project to use to dereference the references.
+     * @throws BuildException on error.
+     */
+    protected synchronized void dieOnCircularReference(Stack stk, Project p)
+        throws BuildException {
+        if (isChecked()) {
+            return;
+        }
+        if (isReference()) {
+            super.dieOnCircularReference(stk, p);
+        } else {
+            if (union != null) {
+                invokeCircularReferenceCheck(union, stk, p);
+            }
+            setChecked(true);
+        }
+    }
+
+    /**
      * Resolve a filename with Project's help - if we know one that is.
      */
     private static File resolveFile(Project project, String relativeName) {
@@ -437,7 +501,6 @@
                 order = o;
             }
         }
-
         if (order.equals("only")) {
             // only: the developer knows what (s)he is doing
             result.addExisting(p, true);
@@ -457,14 +520,10 @@
                 log("invalid value for build.sysclasspath: " + order,
                     Project.MSG_WARN);
             }
-
             result.addExisting(this);
             result.addExisting(p, true);
         }
-
-
         return result;
-
     }
 
     /**
@@ -577,4 +636,45 @@
         }
     }
 
+    /**
+     * Fulfill the ResourceCollection contract. The Iterator returned
+     * will throw ConcurrentModificationExceptions if ResourceCollections
+     * are added to this container while the Iterator is in use.
+     * @return a "fail-fast" Iterator.
+     */
+    public synchronized final Iterator iterator() {
+        if (isReference()) {
+            return ((Path) getCheckedRef()).iterator();
+        }
+        dieOnCircularReference();
+        return union == null ? EMPTY_ITERATOR
+            : assertFilesystemOnly(union).iterator();
+    }
+
+    /**
+     * Fulfill the ResourceCollection contract.
+     * @return whether this is a filesystem-only resource collection.
+     */
+    public synchronized boolean isFilesystemOnly() {
+        if (isReference()) {
+            return ((Path) getCheckedRef()).isFilesystemOnly();
+        }
+        dieOnCircularReference();
+        assertFilesystemOnly(union);
+        return true;
+    }
+
+    /**
+     * Verify the specified ResourceCollection is filesystem-only.
+     * @param rc the ResourceCollection to check.
+     * @throws BuildException if <code>rc</code> is not filesystem-only.
+     * @return the passed in ResourceCollection.
+     */
+    protected ResourceCollection assertFilesystemOnly(ResourceCollection rc) {
+        if (rc != null && !(rc.isFilesystemOnly())) {
+            throw new BuildException(getDataTypeName()
+                + " allows only filesystem resources.");
+        }
+        return rc;
+    }
 }

Modified: ant/core/trunk/src/main/org/apache/tools/ant/types/resources/Union.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/types/resources/Union.java?view=diff&rev=462955&r1=462954&r2=462955
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/types/resources/Union.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/types/resources/Union.java Wed Oct 11 14:26:46 2006
@@ -56,8 +56,8 @@
     }
 
     /**
-     * Returns all Resources in String format. Moved up from
-     * Path for convenience.
+     * Returns all Resources in String format. Provided for
+     * convenience in implementing Path.
      * @return String array of Resources.
      */
     public String[] list() {



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org