Home » apache-ant-1.7.1-src » org.apache.tools » ant » types » [javadoc | source]
    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    *
   17    */
   18   
   19   package org.apache.tools.ant.types;
   20   
   21   import java.io.File;
   22   import java.lang.reflect.Method;
   23   import java.util.Collections;
   24   import java.util.Iterator;
   25   import java.util.Locale;
   26   import java.util.Stack;
   27   import java.util.Vector;
   28   
   29   import org.apache.tools.ant.BuildException;
   30   import org.apache.tools.ant.PathTokenizer;
   31   import org.apache.tools.ant.Project;
   32   import org.apache.tools.ant.types.resources.Union;
   33   import org.apache.tools.ant.types.resources.FileResourceIterator;
   34   import org.apache.tools.ant.util.FileUtils;
   35   import org.apache.tools.ant.util.JavaEnvUtils;
   36   
   37   /**
   38    * This object represents a path as used by CLASSPATH or PATH
   39    * environment variable. A path might also be described as a collection
   40    * of unique filesystem resources.
   41    * <p>
   42    * <code>
   43    * &lt;sometask&gt;<br>
   44    * &nbsp;&nbsp;&lt;somepath&gt;<br>
   45    * &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location="/path/to/file.jar" /&gt;<br>
   46    * &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement
   47    *  path="/path/to/file2.jar:/path/to/class2;/path/to/class3" /&gt;
   48    * <br>
   49    * &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location="/path/to/file3.jar" /&gt;<br>
   50    * &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location="/path/to/file4.jar" /&gt;<br>
   51    * &nbsp;&nbsp;&lt;/somepath&gt;<br>
   52    * &lt;/sometask&gt;<br>
   53    * </code>
   54    * <p>
   55    * The object implemention <code>sometask</code> must provide a method called
   56    * <code>createSomepath</code> which returns an instance of <code>Path</code>.
   57    * Nested path definitions are handled by the Path object and must be labeled
   58    * <code>pathelement</code>.<p>
   59    *
   60    * The path element takes a parameter <code>path</code> which will be parsed
   61    * and split into single elements. It will usually be used
   62    * to define a path from an environment variable.
   63    */
   64   
   65   public class Path extends DataType implements Cloneable, ResourceCollection {
   66       // CheckStyle:VisibilityModifier OFF - bc
   67   
   68       /** The system classpath as a Path object */
   69       public static Path systemClasspath =
   70           new Path(null, System.getProperty("java.class.path"));
   71   
   72   
   73       /**
   74        * The system bootclasspath as a Path object.
   75        *
   76        * @since Ant 1.6.2
   77        */
   78       public static Path systemBootClasspath =
   79           new Path(null, System.getProperty("sun.boot.class.path"));
   80   
   81       private static final Iterator EMPTY_ITERATOR
   82           = Collections.EMPTY_SET.iterator();
   83   
   84       // CheckStyle:VisibilityModifier OFF - bc
   85   
   86       /**
   87        * Helper class, holds the nested <code>&lt;pathelement&gt;</code> values.
   88        */
   89       public class PathElement implements ResourceCollection {
   90           private String[] parts;
   91   
   92           /**
   93            * Set the location.
   94            *
   95            * @param loc a <code>File</code> value
   96            */
   97           public void setLocation(File loc) {
   98               parts = new String[] {translateFile(loc.getAbsolutePath())};
   99           }
  100   
  101           /**
  102            * Set the path.
  103            *
  104            * @param path a <code>String</code> value
  105            */
  106           public void setPath(String path) {
  107               parts = Path.translatePath(getProject(), path);
  108           }
  109   
  110           /**
  111            * Return the converted pathelements.
  112            *
  113            * @return a <code>String[]</code> value
  114            */
  115           public String[] getParts() {
  116               return parts;
  117           }
  118   
  119           /**
  120            * Create an iterator.
  121            * @return an iterator.
  122            */
  123           public Iterator iterator() {
  124               return new FileResourceIterator(null, parts);
  125           }
  126   
  127           /**
  128            * Check if this resource is only for filesystems.
  129            * @return true.
  130            */
  131           public boolean isFilesystemOnly() {
  132               return true;
  133           }
  134   
  135           /**
  136            * Get the number of resources.
  137            * @return the number of parts.
  138            */
  139           public int size() {
  140               return parts == null ? 0 : parts.length;
  141           }
  142   
  143       }
  144   
  145       private Boolean preserveBC;
  146   
  147       private Union union = null;
  148   
  149       /**
  150        * Invoked by IntrospectionHelper for <code>setXXX(Path p)</code>
  151        * attribute setters.
  152        * @param p the <code>Project</code> for this path.
  153        * @param path the <code>String</code> path definition.
  154        */
  155       public Path(Project p, String path) {
  156           this(p);
  157           createPathElement().setPath(path);
  158       }
  159   
  160       /**
  161        * Construct an empty <code>Path</code>.
  162        * @param project the <code>Project</code> for this path.
  163        */
  164       public Path(Project project) {
  165           setProject(project);
  166       }
  167   
  168       /**
  169        * Adds a element definition to the path.
  170        * @param location the location of the element to add (must not be
  171        * <code>null</code> nor empty.
  172        * @throws BuildException on error
  173        */
  174       public void setLocation(File location) throws BuildException {
  175           checkAttributesAllowed();
  176           createPathElement().setLocation(location);
  177       }
  178   
  179       /**
  180        * Parses a path definition and creates single PathElements.
  181        * @param path the <code>String</code> path definition.
  182        * @throws BuildException on error
  183        */
  184       public void setPath(String path) throws BuildException {
  185           checkAttributesAllowed();
  186           createPathElement().setPath(path);
  187       }
  188   
  189       /**
  190        * Makes this instance in effect a reference to another Path instance.
  191        *
  192        * <p>You must not set another attribute or nest elements inside
  193        * this element if you make it a reference.</p>
  194        * @param r the reference to another Path
  195        * @throws BuildException on error
  196        */
  197       public void setRefid(Reference r) throws BuildException {
  198           if (union != null) {
  199               throw tooManyAttributes();
  200           }
  201           super.setRefid(r);
  202       }
  203   
  204       /**
  205        * Creates the nested <code>&lt;pathelement&gt;</code> element.
  206        * @return the <code>PathElement</code> to be configured
  207        * @throws BuildException on error
  208        */
  209       public PathElement createPathElement() throws BuildException {
  210           if (isReference()) {
  211               throw noChildrenAllowed();
  212           }
  213           PathElement pe = new PathElement();
  214           add(pe);
  215           return pe;
  216       }
  217   
  218       /**
  219        * Adds a nested <code>&lt;fileset&gt;</code> element.
  220        * @param fs a <code>FileSet</code> to be added to the path
  221        * @throws BuildException on error
  222        */
  223       public void addFileset(FileSet fs) throws BuildException {
  224           if (fs.getProject() == null) {
  225               fs.setProject(getProject());
  226           }
  227           add(fs);
  228       }
  229   
  230       /**
  231        * Adds a nested <code>&lt;filelist&gt;</code> element.
  232        * @param fl a <code>FileList</code> to be added to the path
  233        * @throws BuildException on error
  234        */
  235       public void addFilelist(FileList fl) throws BuildException {
  236           if (fl.getProject() == null) {
  237               fl.setProject(getProject());
  238           }
  239           add(fl);
  240       }
  241   
  242       /**
  243        * Adds a nested <code>&lt;dirset&gt;</code> element.
  244        * @param dset a <code>DirSet</code> to be added to the path
  245        * @throws BuildException on error
  246        */
  247       public void addDirset(DirSet dset) throws BuildException {
  248           if (dset.getProject() == null) {
  249               dset.setProject(getProject());
  250           }
  251           add(dset);
  252       }
  253   
  254       /**
  255        * Adds a nested path
  256        * @param path a <code>Path</code> to be added to the path
  257        * @throws BuildException on error
  258        * @since Ant 1.6
  259        */
  260       public void add(Path path) throws BuildException {
  261           if (path == this) {
  262               throw circularReference();
  263           }
  264           if (path.getProject() == null) {
  265               path.setProject(getProject());
  266           }
  267           add((ResourceCollection) path);
  268       }
  269   
  270       /**
  271        * Add a nested <code>ResourceCollection</code>.
  272        * @param c the ResourceCollection to add.
  273        * @since Ant 1.7
  274        */
  275       public void add(ResourceCollection c) {
  276           checkChildrenAllowed();
  277           if (c == null) {
  278               return;
  279           }
  280           if (union == null) {
  281               union = new Union();
  282               union.setProject(getProject());
  283               union.setCache(false);
  284           }
  285           union.add(c);
  286           setChecked(false);
  287       }
  288   
  289       /**
  290        * Creates a nested <code>&lt;path&gt;</code> element.
  291        * @return a <code>Path</code> to be configured
  292        * @throws BuildException on error
  293        */
  294       public Path createPath() throws BuildException {
  295           Path p = new Path(getProject());
  296           add(p);
  297           return p;
  298       }
  299   
  300       /**
  301        * Append the contents of the other Path instance to this.
  302        * @param other a <code>Path</code> to be added to the path
  303        */
  304       public void append(Path other) {
  305           if (other == null) {
  306               return;
  307           }
  308           add(other);
  309       }
  310   
  311       /**
  312        * Adds the components on the given path which exist to this
  313        * Path. Components that don't exist aren't added.
  314        *
  315        * @param source - source path whose components are examined for existence
  316        */
  317        public void addExisting(Path source) {
  318            addExisting(source, false);
  319        }
  320   
  321       /**
  322        * Same as addExisting, but support classpath behavior if tryUserDir
  323        * is true. Classpaths are relative to user dir, not the project base.
  324        * That used to break jspc test
  325        *
  326        * @param source the source path
  327        * @param tryUserDir  if true try the user directory if the file is not present
  328        */
  329       public void addExisting(Path source, boolean tryUserDir) {
  330           String[] list = source.list();
  331           File userDir = (tryUserDir) ? new File(System.getProperty("user.dir"))
  332                   : null;
  333   
  334           for (int i = 0; i < list.length; i++) {
  335               File f = resolveFile(getProject(), list[i]);
  336   
  337               // probably not the best choice, but it solves the problem of
  338               // relative paths in CLASSPATH
  339               if (tryUserDir && !f.exists()) {
  340                   f = new File(userDir, list[i]);
  341               }
  342               if (f.exists()) {
  343                   setLocation(f);
  344               } else {
  345                   log("dropping " + f + " from path as it doesn't exist",
  346                       Project.MSG_VERBOSE);
  347               }
  348           }
  349       }
  350   
  351       /**
  352        * Returns all path elements defined by this and nested path objects.
  353        * @return list of path elements.
  354        */
  355       public String[] list() {
  356           if (isReference()) {
  357               return ((Path) getCheckedRef()).list();
  358           }
  359           return assertFilesystemOnly(union) == null
  360               ? new String[0] : union.list();
  361       }
  362   
  363       /**
  364        * Returns a textual representation of the path, which can be used as
  365        * CLASSPATH or PATH environment variable definition.
  366        * @return a textual representation of the path.
  367        */
  368       public String toString() {
  369           return isReference() ? getCheckedRef().toString()
  370               : union == null ? "" : union.toString();
  371       }
  372   
  373       /**
  374        * Splits a PATH (with : or ; as separators) into its parts.
  375        * @param project the project to use
  376        * @param source a <code>String</code> value
  377        * @return an array of strings, one for each path element
  378        */
  379       public static String[] translatePath(Project project, String source) {
  380           final Vector result = new Vector();
  381           if (source == null) {
  382               return new String[0];
  383           }
  384           PathTokenizer tok = new PathTokenizer(source);
  385           StringBuffer element = new StringBuffer();
  386           while (tok.hasMoreTokens()) {
  387               String pathElement = tok.nextToken();
  388               try {
  389                   element.append(resolveFile(project, pathElement).getPath());
  390               } catch (BuildException e) {
  391                   project.log("Dropping path element " + pathElement
  392                       + " as it is not valid relative to the project",
  393                       Project.MSG_VERBOSE);
  394               }
  395               for (int i = 0; i < element.length(); i++) {
  396                   translateFileSep(element, i);
  397               }
  398               result.addElement(element.toString());
  399               element = new StringBuffer();
  400           }
  401           String[] res = new String[result.size()];
  402           result.copyInto(res);
  403           return res;
  404       }
  405   
  406       /**
  407        * Returns its argument with all file separator characters
  408        * replaced so that they match the local OS conventions.
  409        * @param source the path to convert
  410        * @return the converted path
  411        */
  412       public static String translateFile(String source) {
  413           if (source == null) {
  414             return "";
  415           }
  416           final StringBuffer result = new StringBuffer(source);
  417           for (int i = 0; i < result.length(); i++) {
  418               translateFileSep(result, i);
  419           }
  420           return result.toString();
  421       }
  422   
  423       /**
  424        * Translates occurrences at a position of / or \ to correct separator of the
  425        * current platform and returns whether it had to do a
  426        * replacement.
  427        * @param buffer a buffer containing a string
  428        * @param pos the position in the string buffer to convert
  429        * @return true if the character was a / or \
  430        */
  431       protected static boolean translateFileSep(StringBuffer buffer, int pos) {
  432           if (buffer.charAt(pos) == '/' || buffer.charAt(pos) == '\\') {
  433               buffer.setCharAt(pos, File.separatorChar);
  434               return true;
  435           }
  436           return false;
  437       }
  438   
  439       /**
  440        * Fulfill the ResourceCollection contract.
  441        * @return number of elements as int.
  442        */
  443       public synchronized int size() {
  444           if (isReference()) {
  445               return ((Path) getCheckedRef()).size();
  446           }
  447           dieOnCircularReference();
  448           return union == null ? 0 : assertFilesystemOnly(union).size();
  449       }
  450   
  451       /**
  452        * Clone this Path.
  453        * @return Path with shallowly cloned Resource children.
  454        */
  455       public Object clone() {
  456           try {
  457               Path result = (Path) super.clone();
  458               result.union = union == null ? union : (Union) union.clone();
  459               return result;
  460           } catch (CloneNotSupportedException e) {
  461               throw new BuildException(e);
  462           }
  463       }
  464   
  465       /**
  466        * Overrides the version of DataType to recurse on all DataType
  467        * child elements that may have been added.
  468        * @param stk the stack of data types to use (recursively).
  469        * @param p   the project to use to dereference the references.
  470        * @throws BuildException on error.
  471        */
  472       protected synchronized void dieOnCircularReference(Stack stk, Project p)
  473           throws BuildException {
  474           if (isChecked()) {
  475               return;
  476           }
  477           if (isReference()) {
  478               super.dieOnCircularReference(stk, p);
  479           } else {
  480               if (union != null) {
  481                   stk.push(union);
  482                   invokeCircularReferenceCheck(union, stk, p);
  483                   stk.pop();
  484               }
  485               setChecked(true);
  486           }
  487       }
  488   
  489       /**
  490        * Resolve a filename with Project's help - if we know one that is.
  491        */
  492       private static File resolveFile(Project project, String relativeName) {
  493           return FileUtils.getFileUtils().resolveFile(
  494               (project == null) ? null : project.getBaseDir(), relativeName);
  495       }
  496   
  497       /**
  498        * Concatenates the system class path in the order specified by
  499        * the ${build.sysclasspath} property - using &quot;last&quot; as
  500        * default value.
  501        * @return the concatenated path
  502        */
  503       public Path concatSystemClasspath() {
  504           return concatSystemClasspath("last");
  505       }
  506   
  507       /**
  508        * Concatenates the system class path in the order specified by
  509        * the ${build.sysclasspath} property - using the supplied value
  510        * if ${build.sysclasspath} has not been set.
  511        * @param defValue the order ("first", "last", "only")
  512        * @return the concatenated path
  513        */
  514       public Path concatSystemClasspath(String defValue) {
  515           return concatSpecialPath(defValue, Path.systemClasspath);
  516       }
  517   
  518       /**
  519        * Concatenates the system boot class path in the order specified
  520        * by the ${build.sysclasspath} property - using the supplied
  521        * value if ${build.sysclasspath} has not been set.
  522        * @param defValue the order ("first", "last", "only")
  523        * @return the concatenated path
  524        */
  525       public Path concatSystemBootClasspath(String defValue) {
  526           return concatSpecialPath(defValue, Path.systemBootClasspath);
  527       }
  528   
  529       /**
  530        * Concatenates a class path in the order specified by the
  531        * ${build.sysclasspath} property - using the supplied value if
  532        * ${build.sysclasspath} has not been set.
  533        */
  534       private Path concatSpecialPath(String defValue, Path p) {
  535           Path result = new Path(getProject());
  536   
  537           String order = defValue;
  538           if (getProject() != null) {
  539               String o = getProject().getProperty("build.sysclasspath");
  540               if (o != null) {
  541                   order = o;
  542               }
  543           }
  544           if (order.equals("only")) {
  545               // only: the developer knows what (s)he is doing
  546               result.addExisting(p, true);
  547   
  548           } else if (order.equals("first")) {
  549               // first: developer could use a little help
  550               result.addExisting(p, true);
  551               result.addExisting(this);
  552   
  553           } else if (order.equals("ignore")) {
  554               // ignore: don't trust anyone
  555               result.addExisting(this);
  556   
  557           } else {
  558               // last: don't trust the developer
  559               if (!order.equals("last")) {
  560                   log("invalid value for build.sysclasspath: " + order,
  561                       Project.MSG_WARN);
  562               }
  563               result.addExisting(this);
  564               result.addExisting(p, true);
  565           }
  566           return result;
  567       }
  568   
  569       /**
  570        * Add the Java Runtime classes to this Path instance.
  571        */
  572       public void addJavaRuntime() {
  573           if (JavaEnvUtils.isKaffe()) {
  574               // newer versions of Kaffe (1.1.1+) won't have this,
  575               // but this will be sorted by FileSet anyway.
  576               File kaffeShare = new File(System.getProperty("java.home")
  577                                          + File.separator + "share"
  578                                          + File.separator + "kaffe");
  579               if (kaffeShare.isDirectory()) {
  580                   FileSet kaffeJarFiles = new FileSet();
  581                   kaffeJarFiles.setDir(kaffeShare);
  582                   kaffeJarFiles.setIncludes("*.jar");
  583                   addFileset(kaffeJarFiles);
  584               }
  585           } else if ("GNU libgcj".equals(System.getProperty("java.vm.name"))) {
  586               addExisting(systemBootClasspath);
  587           }
  588   
  589           if (System.getProperty("java.vendor").toLowerCase(Locale.US).indexOf("microsoft") >= 0) {
  590               // XXX is this code still necessary? is there any 1.2+ port?
  591               // Pull in *.zip from packages directory
  592               FileSet msZipFiles = new FileSet();
  593               msZipFiles.setDir(new File(System.getProperty("java.home")
  594                   + File.separator + "Packages"));
  595               msZipFiles.setIncludes("*.ZIP");
  596               addFileset(msZipFiles);
  597           } else {
  598               // JDK 1.2+ seems to set java.home to the JRE directory.
  599               addExisting(new Path(null,
  600                                    System.getProperty("java.home")
  601                                    + File.separator + "lib"
  602                                    + File.separator + "rt.jar"));
  603               // Just keep the old version as well and let addExisting
  604               // sort it out.
  605               addExisting(new Path(null,
  606                                    System.getProperty("java.home")
  607                                    + File.separator + "jre"
  608                                    + File.separator + "lib"
  609                                    + File.separator + "rt.jar"));
  610   
  611               // Sun's and Apple's 1.4 have JCE and JSSE in separate jars.
  612               String[] secJars = {"jce", "jsse"};
  613               for (int i = 0; i < secJars.length; i++) {
  614                   addExisting(new Path(null,
  615                                        System.getProperty("java.home")
  616                                        + File.separator + "lib"
  617                                        + File.separator + secJars[i] + ".jar"));
  618                   addExisting(new Path(null,
  619                                        System.getProperty("java.home")
  620                                        + File.separator + ".."
  621                                        + File.separator + "Classes"
  622                                        + File.separator + secJars[i] + ".jar"));
  623               }
  624   
  625               // IBM's 1.4 has rt.jar split into 4 smaller jars and a combined
  626               // JCE/JSSE in security.jar.
  627               String[] ibmJars
  628                   = {"core", "graphics", "security", "server", "xml"};
  629               for (int i = 0; i < ibmJars.length; i++) {
  630                   addExisting(new Path(null,
  631                                        System.getProperty("java.home")
  632                                        + File.separator + "lib"
  633                                        + File.separator + ibmJars[i] + ".jar"));
  634               }
  635   
  636               // Added for MacOS X
  637               addExisting(new Path(null,
  638                                    System.getProperty("java.home")
  639                                    + File.separator + ".."
  640                                    + File.separator + "Classes"
  641                                    + File.separator + "classes.jar"));
  642               addExisting(new Path(null,
  643                                    System.getProperty("java.home")
  644                                    + File.separator + ".."
  645                                    + File.separator + "Classes"
  646                                    + File.separator + "ui.jar"));
  647           }
  648       }
  649   
  650       /**
  651        * Emulation of extdirs feature in java >= 1.2.
  652        * This method adds all files in the given
  653        * directories (but not in sub-directories!) to the classpath,
  654        * so that you don't have to specify them all one by one.
  655        * @param extdirs - Path to append files to
  656        */
  657       public void addExtdirs(Path extdirs) {
  658           if (extdirs == null) {
  659               String extProp = System.getProperty("java.ext.dirs");
  660               if (extProp != null) {
  661                   extdirs = new Path(getProject(), extProp);
  662               } else {
  663                   return;
  664               }
  665           }
  666   
  667           String[] dirs = extdirs.list();
  668           for (int i = 0; i < dirs.length; i++) {
  669               File dir = resolveFile(getProject(), dirs[i]);
  670               if (dir.exists() && dir.isDirectory()) {
  671                   FileSet fs = new FileSet();
  672                   fs.setDir(dir);
  673                   fs.setIncludes("*");
  674                   addFileset(fs);
  675               }
  676           }
  677       }
  678   
  679       /**
  680        * Fulfill the ResourceCollection contract. The Iterator returned
  681        * will throw ConcurrentModificationExceptions if ResourceCollections
  682        * are added to this container while the Iterator is in use.
  683        * @return a "fail-fast" Iterator.
  684        */
  685       public final synchronized Iterator iterator() {
  686           if (isReference()) {
  687               return ((Path) getCheckedRef()).iterator();
  688           }
  689           dieOnCircularReference();
  690           if (getPreserveBC()) {
  691               return new FileResourceIterator(null, list());
  692           }
  693           return union == null ? EMPTY_ITERATOR
  694               : assertFilesystemOnly(union).iterator();
  695       }
  696   
  697       /**
  698        * Fulfill the ResourceCollection contract.
  699        * @return whether this is a filesystem-only resource collection.
  700        */
  701       public synchronized boolean isFilesystemOnly() {
  702           if (isReference()) {
  703               return ((Path) getCheckedRef()).isFilesystemOnly();
  704           }
  705           dieOnCircularReference();
  706           assertFilesystemOnly(union);
  707           return true;
  708       }
  709   
  710       /**
  711        * Verify the specified ResourceCollection is filesystem-only.
  712        * @param rc the ResourceCollection to check.
  713        * @throws BuildException if <code>rc</code> is not filesystem-only.
  714        * @return the passed in ResourceCollection.
  715        */
  716       protected ResourceCollection assertFilesystemOnly(ResourceCollection rc) {
  717           if (rc != null && !(rc.isFilesystemOnly())) {
  718               throw new BuildException(getDataTypeName()
  719                   + " allows only filesystem resources.");
  720           }
  721           return rc;
  722       }
  723   
  724       /**
  725        * Helps determine whether to preserve BC by calling <code>list()</code> on subclasses.
  726        * The default behavior of this method is to return <code>true</code> for any subclass
  727        * that implements <code>list()</code>; this can, of course, be avoided by overriding
  728        * this method to return <code>false</code>. It is not expected that the result of this
  729        * method should change over time, thus it is called only once.
  730        * @return <code>true</code> if <code>iterator()</code> should delegate to <code>list()</code>.
  731        */
  732       protected boolean delegateIteratorToList() {
  733           if (getClass().equals(Path.class)) {
  734               return false;
  735           }
  736           try {
  737               Method listMethod = getClass().getMethod("list", (Class[]) null);
  738               return !listMethod.getDeclaringClass().equals(Path.class);
  739           } catch (Exception e) {
  740               //shouldn't happen, but
  741               return false;
  742           }
  743       }
  744   
  745       private synchronized boolean getPreserveBC() {
  746           if (preserveBC == null) {
  747               preserveBC = delegateIteratorToList() ? Boolean.TRUE : Boolean.FALSE;
  748           }
  749           return preserveBC.booleanValue();
  750       }
  751   }

Save This Page
Home » apache-ant-1.7.1-src » org.apache.tools » ant » types » [javadoc | source]