Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 543   Methods: 22
NCLOC: 292   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
Available.java 71.1% 78.9% 95.5% 77.6%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.ant.taskdefs;
 56   
 
 57   
 import java.io.File;
 58   
 import org.apache.tools.ant.AntClassLoader;
 59   
 import org.apache.tools.ant.BuildException;
 60   
 import org.apache.tools.ant.Project;
 61   
 import org.apache.tools.ant.Task;
 62   
 import org.apache.tools.ant.taskdefs.condition.Condition;
 63   
 import org.apache.tools.ant.types.EnumeratedAttribute;
 64   
 import org.apache.tools.ant.types.Path;
 65   
 import org.apache.tools.ant.types.Reference;
 66   
 import org.apache.tools.ant.util.FileUtils;
 67   
 import org.apache.tools.ant.util.StringUtils;
 68   
 
 69   
 /**
 70   
  * Will set the given property if the requested resource is available at
 71   
  * runtime. This task may also be used as a condition by the condition task.
 72   
  *
 73   
  * @author Stefano Mazzocchi
 74   
  *         <a href="mailto:stefano@apache.org">stefano@apache.org</a>
 75   
  * @author Magesh Umasankar
 76   
  *
 77   
  * @since Ant 1.1
 78   
  *
 79   
  * @ant.task category="control"
 80   
  */
 81   
 public class Available extends Task implements Condition {
 82   
 
 83   
     private String property;
 84   
     private String classname;
 85   
     private String file;
 86   
     private Path filepath;
 87   
     private String resource;
 88   
     private FileDir type;
 89   
     private Path classpath;
 90   
     private AntClassLoader loader;
 91   
     private String value = "true";
 92   
     private boolean isTask = false;
 93   
     private boolean ignoreSystemclasses = false;
 94   
 
 95   
     /**
 96   
      * Set the classpath to be used when searching for classes and resources.
 97   
      *
 98   
      * @param classpath an Ant Path object containing the search path.
 99   
      */
 100  1
     public void setClasspath(Path classpath) {
 101  1
         createClasspath().append(classpath);
 102   
     }
 103   
 
 104   
     /**
 105   
      * Classpath to be used when searching for classes and resources.
 106   
      *
 107   
      * @return an empty Path instance to be configured by Ant.
 108   
      */
 109  39
     public Path createClasspath() {
 110  39
         if (this.classpath == null) {
 111  39
             this.classpath = new Path(getProject());
 112   
         }
 113  39
         return this.classpath.createPath();
 114   
     }
 115   
 
 116   
     /**
 117   
      * Set the classpath by reference.
 118   
      *
 119   
      * @param r a Reference to a Path instance to be used as the classpath
 120   
      *          value.
 121   
      */
 122  37
     public void setClasspathRef(Reference r) {
 123  37
         createClasspath().setRefid(r);
 124   
     }
 125   
 
 126   
     /**
 127   
      * Set the path to use when looking for a file.
 128   
      *
 129   
      * @param filepath a Path instance containing the search path for files.
 130   
      */
 131  8
     public void setFilepath(Path filepath) {
 132  8
         createFilepath().append(filepath);
 133   
     }
 134   
 
 135   
     /**
 136   
      * Path to search for file resources.
 137   
      *
 138   
      * @return a new Path instance which Ant will configure with a file search
 139   
      *         path.
 140   
      */
 141  8
     public Path createFilepath() {
 142  8
         if (this.filepath == null) {
 143  8
             this.filepath = new Path(getProject());
 144   
         }
 145  8
         return this.filepath.createPath();
 146   
     }
 147   
 
 148   
     /**
 149   
      * Set the name of the property which will be set if the particular resource
 150   
      * is available.
 151   
      *
 152   
      * @param property the name of the property to set.
 153   
      */
 154  103
     public void setProperty(String property) {
 155  103
         this.property = property;
 156   
     }
 157   
 
 158   
     /**
 159   
      * Set the value to be given to the property if the desired resource is
 160   
      * available.
 161   
      *
 162   
      * @param value the value to be given.
 163   
      */
 164  8
     public void setValue(String value) {
 165  8
         this.value = value;
 166   
     }
 167   
 
 168   
     /**
 169   
      * Set a classname of a class which must be available to set the given
 170   
      * property.
 171   
      *
 172   
      * @param classname the name of the class required.
 173   
      */
 174  56
     public void setClassname(String classname) {
 175  56
         if (!"".equals(classname)) {
 176  56
             this.classname = classname;
 177   
         }
 178   
     }
 179   
 
 180   
     /**
 181   
      * Set the file which must be present in the file system to set the given
 182   
      * property.
 183   
      *
 184   
      * @param file the name of the file which is required.
 185   
      */
 186  64
     public void setFile(File file) {
 187  64
         this.file = FileUtils.newFileUtils()
 188   
             .removeLeadingPath(getProject().getBaseDir(), file);
 189   
     }
 190   
 
 191   
     /**
 192   
      * Set the name of a Java resource which is required to set the property.
 193   
      *
 194   
      * @param resource the name of a resource which is required to be available.
 195   
      */
 196  5
     public void setResource(String resource) {
 197  5
         this.resource = resource;
 198   
     }
 199   
 
 200   
     /**
 201   
      * @deprecated setType(String) is deprecated and is replaced with
 202   
      *             setType(Available.FileDir) to make Ant's Introspection
 203   
      *             mechanism do the work and also to encapsulate operations on
 204   
      *             the type in its own class.
 205   
      */
 206  0
     public void setType(String type) {
 207  0
         log("DEPRECATED - The setType(String) method has been deprecated."
 208   
             + " Use setType(Available.FileDir) instead.");
 209  0
         this.type = new FileDir();
 210  0
         this.type.setValue(type);
 211   
     }
 212   
 
 213   
     /**
 214   
      * Set what type of file is required - either directory or file.
 215   
      *
 216   
      * @param type an instance of the FileDir enumeratedAttribute indicating
 217   
      *             whether the file required is to be a directory or a plain
 218   
      *             file.
 219   
      */
 220  10
     public void setType(FileDir type) {
 221  10
         this.type = type;
 222   
     }
 223   
 
 224   
     /**
 225   
      * Set whether the search for classes should ignore the runtime classes and
 226   
      * just use the given classpath.
 227   
      *
 228   
      * @param ignore true if system classes are to be ignored.
 229   
      */
 230  3
     public void setIgnoresystemclasses(boolean ignore) {
 231  3
         this.ignoreSystemclasses = ignore;
 232   
     }
 233   
 
 234   
     /**
 235   
      * Entry point when operating as a task.
 236   
      *
 237   
      * @exception BuildException if the task is not configured correctly.
 238   
      */
 239  104
     public void execute() throws BuildException {
 240  104
         if (property == null) {
 241  2
             throw new BuildException("property attribute is required",
 242   
                                      getLocation());
 243   
         }
 244   
 
 245  102
         isTask = true;
 246  102
         try {
 247  102
             if (eval()) {
 248  77
                 String oldvalue = getProject().getProperty(property);
 249  77
                 if (null != oldvalue && !oldvalue.equals(value)) {
 250  1
                     log("DEPRECATED - <available> used to override an existing"
 251   
                         + " property."
 252   
                         + StringUtils.LINE_SEP
 253   
                         + "  Build file should not reuse the same property"
 254   
                         + " name for different values.");
 255   
                 }
 256  77
                 getProject().setProperty(property, value);
 257   
             }
 258   
         } finally {
 259  102
             isTask = false;
 260   
         }
 261   
     }
 262   
 
 263   
     /**
 264   
      * Evaluate the availability of a resource.
 265   
      *
 266   
      * @return boolean is the resource is available.
 267   
      * @exception BuildException if the condition is not configured correctly
 268   
      */
 269  118
     public boolean eval() throws BuildException {
 270  118
         if (classname == null && file == null && resource == null) {
 271  1
             throw new BuildException("At least one of (classname|file|"
 272   
                                      + "resource) is required", getLocation());
 273   
         }
 274   
 
 275  117
         if (type != null) {
 276  10
             if (file == null) {
 277  0
                 throw new BuildException("The type attribute is only valid "
 278   
                                          + "when specifying the file "
 279   
                                          + "attribute.", getLocation());
 280   
             }
 281   
         }
 282   
 
 283  117
         if (classpath != null) {
 284  37
             classpath.setProject(getProject());
 285  37
             this.loader = getProject().createClassLoader(classpath);
 286   
         }
 287   
 
 288  117
         String appendix = "";
 289  117
         if (isTask) {
 290  101
             appendix = " to set property " + property;
 291   
         } else {
 292  16
             setTaskName("available");
 293   
         }
 294   
 
 295  117
         if ((classname != null) && !checkClass(classname)) {
 296  11
             log("Unable to load class " + classname + appendix,
 297   
                 Project.MSG_VERBOSE);
 298  11
             return false;
 299   
         }
 300   
 
 301  106
         if ((file != null) && !checkFile()) {
 302  18
             if (type != null) {
 303  2
                 log("Unable to find " + type + " " + file + appendix,
 304   
                     Project.MSG_VERBOSE);
 305   
             } else {
 306  16
                 log("Unable to find " + file + appendix, Project.MSG_VERBOSE);
 307   
             }
 308  18
             return false;
 309   
         }
 310   
 
 311  88
         if ((resource != null) && !checkResource(resource)) {
 312  1
             log("Unable to load resource " + resource + appendix,
 313   
                 Project.MSG_VERBOSE);
 314  1
             return false;
 315   
         }
 316   
 
 317  87
         if (loader != null) {
 318  31
             loader.cleanup();
 319  31
             loader = null;
 320   
         }
 321   
 
 322  87
         if (!isTask) {
 323  10
             setTaskName(null);
 324   
         }
 325   
 
 326  87
         return true;
 327   
     }
 328   
 
 329   
     /**
 330   
      * Search for file/directory either either relative to project's
 331   
      * basedir or in the path given as filepath.
 332   
      *
 333   
      * <p>filepath can be a list of directory and/or file names (gen'd
 334   
      * via <fileset>)</p>
 335   
      *
 336   
      * <p>look for:</p><ul>
 337   
      *   <li>full-pathname specified == path in list</li>
 338   
      *   <li>full-pathname specified == parent dir of path in list</li>
 339   
      *   <li>simple name specified   == path in list</li>
 340   
      *   <li>simple name specified   == path in list + name</li>
 341   
      *   <li>simple name specified   == parent dir + name</li>
 342   
      *   <li>simple name specified   == parent of parent dir + name</li>
 343   
      * </ul>
 344   
      */
 345  61
     private boolean checkFile() {
 346  61
         if (filepath == null) {
 347  53
             return checkFile(getProject().resolveFile(file), file);
 348   
         } else {
 349  8
             String[] paths = filepath.list();
 350  8
             for (int i = 0; i < paths.length; ++i) {
 351  38
                 log("Searching " + paths[i], Project.MSG_DEBUG);
 352  38
                 File path = new File(paths[i]);
 353   
 
 354   
                 // **   full-pathname specified == path in list
 355   
                 // **   simple name specified   == path in list
 356  38
                 if (path.exists() && file.equals(paths[i])) {
 357  0
                     if (type == null) {
 358  0
                         log("Found: " + path, Project.MSG_VERBOSE);
 359  0
                         return true;
 360  0
                     } else if (type.isDir()
 361   
                                && path.isDirectory()) {
 362  0
                         log("Found directory: " + path, Project.MSG_VERBOSE);
 363  0
                         return true;
 364  0
                     } else if (type.isFile()
 365   
                                && path.isFile()) {
 366  0
                         log("Found file: " + path, Project.MSG_VERBOSE);
 367  0
                         return true;
 368   
                     }
 369   
                     // not the requested type
 370  0
                     return false;
 371   
                 }
 372   
 
 373  38
                 FileUtils fileUtils = FileUtils.newFileUtils();
 374  38
                 File parent = fileUtils.getParentFile(path);
 375   
                 // **   full-pathname specified == parent dir of path in list
 376  38
                 if (parent != null && parent.exists()
 377   
                     && file.equals(parent.getAbsolutePath())) {
 378  0
                     if (type == null) {
 379  0
                         log("Found: " + parent, Project.MSG_VERBOSE);
 380  0
                         return true;
 381  0
                     } else if (type.isDir()) {
 382  0
                         log("Found directory: " + parent, Project.MSG_VERBOSE);
 383  0
                         return true;
 384   
                     }
 385   
                     // not the requested type
 386  0
                     return false;
 387   
                 }
 388   
 
 389   
                 // **   simple name specified   == path in list + name
 390  38
                 if (path.exists() && path.isDirectory()) {
 391  36
                     if (checkFile(new File(path, file),
 392   
                                   file + " in " + path)) {
 393  1
                         return true;
 394   
                     }
 395   
                 }
 396   
 
 397   
                 // **   simple name specified   == parent dir + name
 398  37
                 if (parent != null && parent.exists()) {
 399  37
                     if (checkFile(new File(parent, file),
 400   
                                   file + " in " + parent)) {
 401  0
                         return true;
 402   
                     }
 403   
                 }
 404   
 
 405   
                 // **   simple name specified   == parent of parent dir + name
 406  37
                 if (parent != null) {
 407  37
                     File grandParent = fileUtils.getParentFile(parent);
 408  37
                     if (grandParent != null && grandParent.exists()) {
 409  33
                         if (checkFile(new File(grandParent, file),
 410   
                                       file + " in " + grandParent)) {
 411  0
                             return true;
 412   
                         }
 413   
                     }
 414   
                 }
 415   
             }
 416   
         }
 417  7
         return false;
 418   
     }
 419   
 
 420   
     /**
 421   
      * Check if a given file exists and matches the required type.
 422   
      */
 423  159
     private boolean checkFile(File f, String text) {
 424  159
         if (type != null) {
 425  10
             if (type.isDir()) {
 426  9
                 if (f.isDirectory()) {
 427  8
                     log("Found directory: " + text, Project.MSG_VERBOSE);
 428   
                 }
 429  9
                 return f.isDirectory();
 430  1
             } else if (type.isFile()) {
 431  1
                 if (f.isFile()) {
 432  0
                     log("Found file: " + text, Project.MSG_VERBOSE);
 433   
                 }
 434  1
                 return f.isFile();
 435   
             }
 436   
         }
 437  149
         if (f.exists()) {
 438  35
             log("Found: " + text, Project.MSG_VERBOSE);
 439   
         }
 440  149
         return f.exists();
 441   
     }
 442   
 
 443   
     /**
 444   
      * Check if a given resource can be loaded.
 445   
      */
 446  4
     private boolean checkResource(String resource) {
 447  4
         if (loader != null) {
 448  0
             return (loader.getResourceAsStream(resource) != null);
 449   
         } else {
 450  4
             ClassLoader cL = this.getClass().getClassLoader();
 451  4
             if (cL != null) {
 452  4
                 return (cL.getResourceAsStream(resource) != null);
 453   
             } else {
 454  0
                 return
 455   
                     (ClassLoader.getSystemResourceAsStream(resource) != null);
 456   
             }
 457   
         }
 458   
     }
 459   
 
 460   
     /**
 461   
      * Check if a given class can be loaded.
 462   
      */
 463  54
     private boolean checkClass(String classname) {
 464  54
         try {
 465  54
             Class requiredClass = null;
 466  54
             if (ignoreSystemclasses) {
 467  2
                 loader = getProject().createClassLoader(classpath);
 468  2
                 loader.setParentFirst(false);
 469  2
                 loader.addJavaLibraries();
 470  2
                 if (loader != null) {
 471  2
                     try {
 472  2
                         requiredClass = loader.findClass(classname);
 473   
                     } catch (SecurityException se) {
 474   
                         // class found but restricted name; this is
 475   
                         // actually the case we're looking for in JDK 1.3+,
 476   
                         // so catch the exception and return
 477  1
                         return true;
 478   
                     }
 479   
                 } else {
 480  0
                     return false;
 481   
                 }
 482  52
             } else if (loader != null) {
 483  36
                 requiredClass = loader.loadClass(classname);
 484   
             } else {
 485  16
                 ClassLoader l = this.getClass().getClassLoader();
 486   
                 // Can return null to represent the bootstrap class loader.
 487   
                 // see API docs of Class.getClassLoader.
 488  16
                 if (l != null) {
 489  16
                     requiredClass = l.loadClass(classname);
 490   
                 } else {
 491  0
                     requiredClass = Class.forName(classname);
 492   
                 }
 493   
             }
 494  42
             AntClassLoader.initializeClass(requiredClass);
 495  42
             return true;
 496   
         } catch (ClassNotFoundException e) {
 497  11
             log("class \"" + classname + "\" was not found",
 498   
                 Project.MSG_DEBUG);
 499  11
             return false;
 500   
         } catch (NoClassDefFoundError e) {
 501  0
             log("Could not load dependent class \"" + e.getMessage()
 502   
                 + "\" for class \"" + classname + "\"",
 503   
                 Project.MSG_DEBUG);
 504  0
             return false;
 505   
         }
 506   
     }
 507   
 
 508   
     /**
 509   
      * EnumeratedAttribute covering the file types to be checked for, either
 510   
      * file or dir.
 511   
      */
 512   
     public static class FileDir extends EnumeratedAttribute {
 513   
 
 514   
         private static final String[] values = {"file", "dir"};
 515   
 
 516   
         /**
 517   
          * @see EnumeratedAttribute#getValues
 518   
          */
 519  11
         public String[] getValues() {
 520  11
             return values;
 521   
         }
 522   
 
 523   
         /**
 524   
          * Indicate if the value specifies a directory.
 525   
          *
 526   
          * @return true if the value specifies a directory.
 527   
          */
 528  10
         public boolean isDir() {
 529  10
             return "dir".equalsIgnoreCase(getValue());
 530   
         }
 531   
 
 532   
         /**
 533   
          * Indicate if the value specifies a file.
 534   
          *
 535   
          * @return true if the value specifies a file.
 536   
          */
 537  1
         public boolean isFile() {
 538  1
             return "file".equalsIgnoreCase(getValue());
 539   
         }
 540   
 
 541   
     }
 542   
 }
 543