Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 325   Methods: 6
NCLOC: 180   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AntClassLoader2.java 67.4% 85.4% 100% 80.1%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 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   
 package org.apache.tools.ant.loader;
 55   
 
 56   
 import java.io.File;
 57   
 import java.io.IOException;
 58   
 import java.io.InputStream;
 59   
 import java.io.InputStreamReader;
 60   
 import java.io.Reader;
 61   
 import org.apache.tools.ant.AntClassLoader;
 62   
 import org.apache.tools.ant.Project;
 63   
 import java.util.jar.Manifest;
 64   
 import java.util.jar.JarFile;
 65   
 import java.util.zip.ZipFile;
 66   
 import java.util.jar.Attributes;
 67   
 import java.util.jar.Attributes.Name;
 68   
 import java.net.URL;
 69   
 import java.net.MalformedURLException;
 70   
 import java.util.zip.ZipEntry;
 71   
 import java.util.StringTokenizer;
 72   
 import org.apache.tools.ant.util.FileUtils;
 73   
 
 74   
 /**
 75   
  * An implementation of the AntClassLoader suitable for use on post JDK 1.1
 76   
  * platforms
 77   
  *
 78   
  * @author Conor MacNeill
 79   
  */
 80   
 public class AntClassLoader2 extends AntClassLoader {
 81   
     /** Instance of a utility class to use for file operations. */
 82   
     private FileUtils fileUtils;
 83   
     
 84   
     /**
 85   
      * Constructor
 86   
      */
 87  254
     public AntClassLoader2() {
 88  254
         fileUtils = FileUtils.newFileUtils();
 89   
     }
 90   
     
 91   
     /**
 92   
      * Define a class given its bytes
 93   
      *
 94   
      * @param container the container from which the class data has been read
 95   
      *                  may be a directory or a jar/zip file.
 96   
      *
 97   
      * @param classData the bytecode data for the class
 98   
      * @param className the name of the class
 99   
      *
 100   
      * @return the Class instance created from the given data
 101   
      *
 102   
      * @throws IOException if the class data cannot be read.
 103   
      */
 104  508
     protected Class defineClassFromData(File container, byte[] classData,
 105   
                                         String className) throws IOException {
 106   
 
 107  508
         definePackage(container, className);
 108  508
         return defineClass(className, classData, 0, classData.length,
 109   
                            Project.class.getProtectionDomain());
 110   
                                             
 111   
     }
 112   
 
 113   
     /**
 114   
      * Get the manifest from the given jar, if it is indeed a jar and it has a 
 115   
      * manifest
 116   
      *
 117   
      * @param container the File from which a manifest is required.
 118   
      *
 119   
      * @return the jar's manifest or null is the container is not a jar or it
 120   
      *         has no manifest.
 121   
      *
 122   
      * @exception IOException if the manifest cannot be read.
 123   
      */
 124  23
     private Manifest getJarManifest(File container) throws IOException {
 125  23
         if (container.isDirectory()) {
 126  22
             return null;
 127   
         }
 128  1
         JarFile jarFile = null;
 129  1
         try {
 130  1
             jarFile = new JarFile(container);
 131  1
             return jarFile.getManifest();
 132   
         } finally {
 133  1
             if (jarFile != null) {
 134  1
                 jarFile.close();
 135   
             }
 136   
         }
 137   
     }
 138   
                 
 139   
     /**
 140   
      * Define the package information associated with a class.
 141   
      *
 142   
      * @param container the file containing the class definition.
 143   
      * @param className the class name of for which the package information
 144   
      *        is to be determined.
 145   
      * 
 146   
      * @exception IOException if the package information cannot be read from the
 147   
      *            container.
 148   
      */                
 149  508
     protected void definePackage(File container, String className) 
 150   
         throws IOException {
 151  508
         int classIndex = className.lastIndexOf('.');
 152  508
         if (classIndex == -1) {
 153  0
             return;
 154   
         }
 155   
         
 156  508
         String packageName = className.substring(0, classIndex);
 157  508
         if (getPackage(packageName) != null) {
 158   
             // already defined 
 159  485
             return;
 160   
         }
 161   
         
 162   
         // define the package now 
 163  23
         Manifest manifest = getJarManifest(container);
 164   
         
 165  23
         if (manifest == null) {
 166  22
             definePackage(packageName, null, null, null, null, null, 
 167   
                           null, null);
 168   
         } else {
 169  1
             definePackage(container, packageName, manifest);
 170   
         }
 171   
     }
 172   
     
 173   
     /**
 174   
      * Define the package information when the class comes from a 
 175   
      * jar with a manifest
 176   
      *
 177   
      * @param container the jar file containing the manifest
 178   
      * @param packageName the name of the package being defined.
 179   
      * @param manifest the jar's manifest
 180   
      */
 181  1
     protected void definePackage(File container, String packageName, 
 182   
                                  Manifest manifest) {
 183  1
         String sectionName = packageName.replace('.', '/') + "/";
 184   
 
 185  1
         String specificationTitle = null;
 186  1
         String specificationVendor = null;
 187  1
         String specificationVersion = null;
 188  1
         String implementationTitle = null;
 189  1
         String implementationVendor = null;
 190  1
         String implementationVersion = null;
 191  1
         String sealedString = null;
 192  1
         URL sealBase = null;
 193   
         
 194  1
         Attributes sectionAttributes = manifest.getAttributes(sectionName);
 195  1
         if (sectionAttributes != null) {
 196  0
             specificationTitle   
 197   
                 = sectionAttributes.getValue(Name.SPECIFICATION_TITLE);
 198  0
             specificationVendor   
 199   
                 = sectionAttributes.getValue(Name.SPECIFICATION_VENDOR);
 200  0
             specificationVersion   
 201   
                 = sectionAttributes.getValue(Name.SPECIFICATION_VERSION);
 202  0
             implementationTitle   
 203   
                 = sectionAttributes.getValue(Name.IMPLEMENTATION_TITLE);
 204  0
             implementationVendor   
 205   
                 = sectionAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
 206  0
             implementationVersion   
 207   
                 = sectionAttributes.getValue(Name.IMPLEMENTATION_VERSION);
 208  0
             sealedString   
 209   
                 = sectionAttributes.getValue(Name.SEALED);
 210   
         }
 211   
         
 212  1
         Attributes mainAttributes = manifest.getMainAttributes();
 213  1
         if (mainAttributes != null) {
 214  1
             if (specificationTitle == null) {
 215  1
                 specificationTitle   
 216   
                     = mainAttributes.getValue(Name.SPECIFICATION_TITLE);
 217   
             }
 218  1
             if (specificationVendor == null) {
 219  1
                 specificationVendor   
 220   
                     = mainAttributes.getValue(Name.SPECIFICATION_VENDOR);
 221   
             }
 222  1
             if (specificationVersion == null) {
 223  1
                 specificationVersion   
 224   
                     = mainAttributes.getValue(Name.SPECIFICATION_VERSION);
 225   
             }
 226  1
             if (implementationTitle == null) {
 227  1
                 implementationTitle   
 228   
                     = mainAttributes.getValue(Name.IMPLEMENTATION_TITLE);
 229   
             }
 230  1
             if (implementationVendor == null) {
 231  1
                 implementationVendor   
 232   
                     = mainAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
 233   
             }
 234  1
             if (implementationVersion == null) {
 235  1
                 implementationVersion   
 236   
                     = mainAttributes.getValue(Name.IMPLEMENTATION_VERSION);
 237   
             }
 238  1
             if (sealedString == null) {
 239  1
                 sealedString   
 240   
                     = mainAttributes.getValue(Name.SEALED);
 241   
             }
 242   
         }
 243   
         
 244  1
         if (sealedString != null && sealedString.equalsIgnoreCase("true")) {
 245  0
             try {
 246  0
                 sealBase = new URL("file:" + container.getPath());
 247   
             } catch (MalformedURLException e) {
 248   
                 // ignore
 249   
             }
 250   
         }
 251   
         
 252  1
         definePackage(packageName, specificationTitle, specificationVersion, 
 253   
                       specificationVendor, implementationTitle, 
 254   
                       implementationVersion, implementationVendor, sealBase);
 255   
     }
 256   
     
 257   
     
 258   
     /**
 259   
      * Add a file to the path. This classloader reads the manifest, if 
 260   
      * available, and adds any additional class path jars specified in the
 261   
      * manifest.
 262   
      *
 263   
      * @param pathComponent the file which is to be added to the path for
 264   
      *                      this class loader
 265   
      *
 266   
      * @throws IOException if data needed from the file cannot be read.
 267   
      */
 268  4600
     protected void addPathFile(File pathComponent) throws IOException {
 269  4600
         super.addPathFile(pathComponent);
 270   
         
 271  4600
         if (pathComponent.isDirectory()) {
 272  590
             return;
 273   
         }
 274   
         
 275  4010
         String classpath = null;
 276  4010
         ZipFile jarFile = null;
 277  4010
         InputStream manifestStream = null;
 278  4010
         try {
 279  4010
             jarFile = new ZipFile(pathComponent);
 280  4010
             manifestStream 
 281   
                 = jarFile.getInputStream(new ZipEntry("META-INF/MANIFEST.MF"));
 282   
 
 283  4010
             if (manifestStream == null) {
 284  118
                 return;
 285   
             }                
 286  3892
             Reader manifestReader 
 287   
                 = new InputStreamReader(manifestStream, "UTF-8");
 288  3892
             org.apache.tools.ant.taskdefs.Manifest manifest
 289   
                 = new org.apache.tools.ant.taskdefs.Manifest(manifestReader);
 290  3892
             classpath 
 291   
                 = manifest.getMainSection().getAttributeValue("Class-Path");
 292   
                
 293   
         } catch (org.apache.tools.ant.taskdefs.ManifestException e) {
 294   
             // ignore
 295   
         } finally {
 296  4010
             if (manifestStream != null) {
 297  3892
                 manifestStream.close();
 298   
             }
 299  4010
             if (jarFile != null) {
 300  4010
                 jarFile.close();
 301   
             }
 302   
         }
 303   
         
 304  3892
         if (classpath != null) {
 305  118
             URL baseURL = fileUtils.getFileURL(pathComponent);
 306  118
             StringTokenizer st = new StringTokenizer(classpath);
 307  118
             while (st.hasMoreTokens()) {
 308  354
                 String classpathElement = st.nextToken();
 309  354
                 URL libraryURL = new URL(baseURL, classpathElement);
 310  354
                 if (!libraryURL.getProtocol().equals("file")) {
 311  0
                     log("Skipping jar library " + classpathElement 
 312   
                         + " since only relative URLs are supported by this"
 313   
                         + " loader", Project.MSG_VERBOSE);
 314  0
                     continue;
 315   
                 }
 316  354
                 File libraryFile = new File(libraryURL.getFile());
 317  354
                 if (libraryFile.exists() && !isInPath(libraryFile)) {
 318  0
                     addPathFile(libraryFile);
 319   
                 }
 320   
             }
 321   
         }
 322   
     }
 323   
 }
 324   
 
 325