Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 322   Methods: 14
NCLOC: 113   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AbstractAnalyzer.java 38.5% 56.2% 71.4% 53.4%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2002 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   
 package org.apache.tools.ant.util.depend;
 55   
 import java.io.File;
 56   
 import java.io.IOException;
 57   
 import java.util.Enumeration;
 58   
 import java.util.Vector;
 59   
 import java.util.zip.ZipFile;
 60   
 import org.apache.tools.ant.types.Path;
 61   
 
 62   
 /**
 63   
  * An abstract implementation of the analyzer interface providing support
 64   
  * for the bulk of interface methods.
 65   
  *
 66   
  * @author Conor MacNeill
 67   
  */
 68   
 public abstract class AbstractAnalyzer implements DependencyAnalyzer {
 69   
     /** Maximum number of loops for looking for indirect dependencies. */
 70   
     public static final int MAX_LOOPS = 1000;
 71   
 
 72   
     /** The source path for the source files */
 73   
     private Path sourcePath = new Path(null);
 74   
 
 75   
     /** The classpath containg dirs and jars of class files */
 76   
     private Path classPath = new Path(null);
 77   
 
 78   
     /** The list of root classes */
 79   
     private Vector rootClasses = new Vector();
 80   
 
 81   
     /** true if dependencies have been determined */
 82   
     private boolean determined = false;
 83   
 
 84   
     /** the list of File objects that the root classes depend upon */
 85   
     private Vector fileDependencies;
 86   
     /** the list of java classes the root classes depend upon */
 87   
     private Vector classDependencies;
 88   
 
 89   
     /** true if indirect dependencies should be gathered */
 90   
     private boolean closure = true;
 91   
 
 92   
     /** Setup the analyzer */
 93  37
     protected AbstractAnalyzer() {
 94  37
         reset();
 95   
     }
 96   
 
 97   
     /**
 98   
      * Set the closure flag. If this flag is true the analyzer will traverse
 99   
      * all class relationships until it has collected the entire set of
 100   
      * direct and indirect dependencies
 101   
      *
 102   
      * @param closure true if dependencies should be traversed to determine
 103   
      *      indirect dependencies.
 104   
      */
 105  27
     public void setClosure(boolean closure) {
 106  27
         this.closure = closure;
 107   
     }
 108   
 
 109   
     /**
 110   
      * Get the list of files in the file system upon which the root classes
 111   
      * depend. The files will be either the classfiles or jar files upon
 112   
      * which the root classes depend.
 113   
      *
 114   
      * @return an enumeration of File instances.
 115   
      */
 116  0
     public Enumeration getFileDependencies() {
 117  0
         if (!supportsFileDependencies()) {
 118  0
             throw new RuntimeException("File dependencies are not supported " 
 119   
                 + "by this analyzer");
 120   
         }
 121  0
         if (!determined) {
 122  0
             determineDependencies(fileDependencies, classDependencies);
 123   
         }
 124  0
         return fileDependencies.elements();
 125   
     }
 126   
 
 127   
     /**
 128   
      * Get the list of classes upon which root classes depend. This is a
 129   
      * list of Java classnames in dot notation.
 130   
      *
 131   
      * @return an enumeration of Strings, each being the name of a Java
 132   
      *      class in dot notation.
 133   
      */
 134  37
     public Enumeration getClassDependencies() {
 135  37
         if (!determined) {
 136  37
             determineDependencies(fileDependencies, classDependencies);
 137   
         }
 138  37
         return classDependencies.elements();
 139   
     }
 140   
 
 141   
     /**
 142   
      * Get the file that contains the class definition
 143   
      *
 144   
      * @param classname the name of the required class
 145   
      * @return the file instance, zip or class, containing the 
 146   
      *         class or null if the class could not be found.
 147   
      * @exception IOException if the files in the classpath cannot be read.
 148   
      */
 149  83
     public File getClassContainer(String classname) throws IOException {
 150  83
         String classLocation = classname.replace('.', '/') + ".class";
 151   
         // we look through the classpath elements. If the element is a dir
 152   
         // we look for the file. IF it is a zip, we look for the zip entry
 153  83
         return getResourceContainer(classLocation, classPath.list());
 154   
     }
 155   
 
 156   
     /**
 157   
      * Get the file that contains the class source.
 158   
      *
 159   
      * @param classname the name of the required class
 160   
      * @return the file instance, zip or java, containing the 
 161   
      *         source or null if the source for the class could not be found.
 162   
      * @exception IOException if the files in the sourcepath cannot be read.
 163   
      */
 164  0
     public File getSourceContainer(String classname) throws IOException {
 165  0
         String sourceLocation = classname.replace('.', '/') + ".java";
 166   
 
 167   
         // we look through the source path elements. If the element is a dir
 168   
         // we look for the file. If it is a zip, we look for the zip entry.
 169   
         // This isn't normal for source paths but we get it for free
 170  0
         return getResourceContainer(sourceLocation, sourcePath.list());
 171   
     }
 172   
 
 173   
     /**
 174   
      * Add a source path to the source path used by this analyzer. The
 175   
      * elements in the given path contain the source files for the classes
 176   
      * being analyzed. Not all analyzers will use this information.
 177   
      *
 178   
      * @param sourcePath The Path instance specifying the source path
 179   
      *      elements.
 180   
      */
 181  0
     public void addSourcePath(Path sourcePath) {
 182  0
         if (sourcePath == null) {
 183  0
             return;
 184   
         }
 185  0
         this.sourcePath.append(sourcePath);
 186  0
         this.sourcePath.setProject(sourcePath.getProject());
 187   
     }
 188   
 
 189   
     /**
 190   
      * Add a classpath to the classpath being used by the analyzer. The
 191   
      * classpath contains the binary classfiles for the classes being
 192   
      * analyzed The elements may either be the directories or jar files.Not
 193   
      * all analyzers will use this information.
 194   
      *
 195   
      * @param classPath the Path instance specifying the classpath elements
 196   
      */
 197  37
     public void addClassPath(Path classPath) {
 198  37
         if (classPath == null) {
 199  0
             return;
 200   
         }
 201   
 
 202  37
         this.classPath.append(classPath);
 203  37
         this.classPath.setProject(classPath.getProject());
 204   
     }
 205   
 
 206   
     /**
 207   
      * Add a root class. The root classes are used to drive the
 208   
      * determination of dependency information. The analyzer will start at
 209   
      * the root classes and add dependencies from there.
 210   
      *
 211   
      * @param className the name of the class in Java dot notation.
 212   
      */
 213  37
     public void addRootClass(String className) {
 214  37
         if (className == null) {
 215  0
             return;
 216   
         }
 217  37
         if (!rootClasses.contains(className)) {
 218  37
             rootClasses.addElement(className);
 219   
         }
 220   
     }
 221   
 
 222   
     /**
 223   
      * Configure an aspect of the analyzer. The set of aspects that are
 224   
      * supported is specific to each analyzer instance.
 225   
      *
 226   
      * @param name the name of the aspect being configured
 227   
      * @param info the configuration info.
 228   
      */
 229  0
     public void config(String name, Object info) {
 230   
         // do nothing by default
 231   
     }
 232   
 
 233   
     /**
 234   
      * Reset the dependency list. This will reset the determined
 235   
      * dependencies and the also list of root classes.
 236   
      */
 237  37
     public void reset() {
 238  37
         rootClasses.removeAllElements();
 239  37
         determined = false;
 240  37
         fileDependencies = new Vector();
 241  37
         classDependencies = new Vector();
 242   
     }
 243   
 
 244   
     /**
 245   
      * Get an enumeration of the root classes
 246   
      *
 247   
      * @return an enumeration of Strings, each of which is a class name 
 248   
      *         for a root class.
 249   
      */
 250  37
     protected Enumeration getRootClasses() {
 251  37
         return rootClasses.elements();
 252   
     }
 253   
 
 254   
     /**
 255   
      * Indicate if the analyzer is required to follow 
 256   
      * indirect class relationships.
 257   
      *
 258   
      * @return true if indirect relationships should be followed.
 259   
      */
 260  37
     protected boolean isClosureRequired() {
 261  37
         return closure;
 262   
     }
 263   
 
 264   
     /**
 265   
      * Determine the dependencies of the current set of root classes
 266   
      *
 267   
      * @param files a vector into which Files upon which the root classes
 268   
      *      depend should be placed.
 269   
      * @param classes a vector of Strings into which the names of classes
 270   
      *      upon which the root classes depend should be placed.
 271   
      */
 272   
     protected abstract void determineDependencies(Vector files, Vector classes);
 273   
 
 274   
     /**
 275   
      * Indicate if the particular subclass supports file dependency
 276   
      * information.
 277   
      *
 278   
      * @return true if file dependencies are supported.
 279   
      */
 280   
     protected abstract boolean supportsFileDependencies();
 281   
 
 282   
     /**
 283   
      * Get the file that contains the resource
 284   
      *
 285   
      * @param resourceLocation the name of the required resource.
 286   
      * @param paths the paths which will be searched for the resource.
 287   
      * @return the file instance, zip or class, containing the 
 288   
      *         class or null if the class could not be found.
 289   
      * @exception IOException if the files in the given paths cannot be read.
 290   
      */
 291  83
     private File getResourceContainer(String resourceLocation, String[] paths)
 292   
          throws IOException {
 293  83
         for (int i = 0; i < paths.length; ++i) {
 294  83
             File element = new File(paths[i]);
 295  83
             if (!element.exists()) {
 296  0
                 continue;
 297   
             }
 298  83
             if (element.isDirectory()) {
 299  83
                 File resource = new File(element, resourceLocation);
 300  83
                 if (resource.exists()) {
 301  61
                     return resource;
 302   
                 }
 303   
             } else {
 304   
                 // must be a zip of some sort
 305  0
                 ZipFile zipFile = null;
 306  0
                 try {
 307  0
                     zipFile = new ZipFile(element);
 308  0
                     if (zipFile.getEntry(resourceLocation) != null) {
 309  0
                         return element;
 310   
                     }
 311   
                 } finally {
 312  0
                     if (zipFile != null) {
 313  0
                         zipFile.close();
 314   
                     }
 315   
                 }
 316   
             }
 317   
         }
 318  22
         return null;
 319   
     }
 320   
 }
 321   
 
 322