Coverage Report - org.apache.maven.shared.jar.JarAnalyzer
 
Classes in this File Line Coverage Branch Coverage Complexity
JarAnalyzer
0%
0/39
0%
0/4
1.636
JarAnalyzer$1
0%
0/4
N/A
1.636
 
 1  
 package org.apache.maven.shared.jar;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.io.File;
 23  
 import java.io.IOException;
 24  
 import java.io.InputStream;
 25  
 import java.util.ArrayList;
 26  
 import java.util.Collections;
 27  
 import java.util.Comparator;
 28  
 import java.util.Iterator;
 29  
 import java.util.List;
 30  
 import java.util.jar.JarEntry;
 31  
 import java.util.jar.JarFile;
 32  
 import java.util.jar.Manifest;
 33  
 import java.util.regex.Matcher;
 34  
 import java.util.regex.Pattern;
 35  
 import java.util.zip.ZipException;
 36  
 
 37  
 /**
 38  
  * Open a JAR file to be analyzed. Note that once created, the {@link #closeQuietly()} method should be called to
 39  
  * release the associated file handle.
 40  
  * <p/>
 41  
  * Typical usage:
 42  
  * <pre>
 43  
  *  JarAnalyzer jar = new JarAnalyzer( jarFile );
 44  
  * <p/>
 45  
  *  try
 46  
  *  {
 47  
  *      // do some analysis, such as:
 48  
  *      jarClasses = jarClassAnalyzer.analyze( jar );
 49  
  *  }
 50  
  *  finally
 51  
  *  {
 52  
  *      jar.closeQuietly();
 53  
  *  }
 54  
  * <p/>
 55  
  *  // use jar.getJarData() in some way, or the data returned by the JAR analyzer. jar itself can no longer be used.
 56  
  * </pre>
 57  
  * <p/>
 58  
  * Note: that the actual data is separated from this class by design to minimise the chance of forgetting to close the
 59  
  * JAR file. The {@link org.apache.maven.shared.jar.JarData} class exposed, as well as any data returned by actual
 60  
  * analyzers that use this class, can be used safely once this class is out of scope.
 61  
  *
 62  
  * @see org.apache.maven.shared.jar.identification.JarIdentificationAnalysis#analyze(JarAnalyzer)
 63  
  * @see org.apache.maven.shared.jar.classes.JarClassesAnalysis#analyze(JarAnalyzer)
 64  
  */
 65  
 public class JarAnalyzer
 66  
 {
 67  
     /**
 68  
      * Pattern to filter JAR entries for class files.
 69  
      *
 70  
      * @todo why are inner classes and other potentially valid classes omitted? (It flukes it by finding everything after $)
 71  
      */
 72  0
     private static final Pattern CLASS_FILTER = Pattern.compile( "[A-Za-z0-9]*\\.class$" );
 73  
 
 74  
     /**
 75  
      * Pattern to filter JAR entries for Maven POM files.
 76  
      */
 77  0
     private static final Pattern MAVEN_POM_FILTER = Pattern.compile( "META-INF/maven/.*/pom\\.xml$" );
 78  
 
 79  
     /**
 80  
      * Pattern to filter JAR entries for text files that may contain a version.
 81  
      */
 82  0
     private static final Pattern VERSION_FILTER = Pattern.compile( "[Vv][Ee][Rr][Ss][Ii][Oo][Nn]" );
 83  
 
 84  
     /**
 85  
      * The associated JAR file.
 86  
      */
 87  
     private final JarFile jarFile;
 88  
 
 89  
     /**
 90  
      * Contains information about the data collected so far.
 91  
      */
 92  
     private final JarData jarData;
 93  
 
 94  
     /**
 95  
      * Constructor. Opens the JAR file, so should be matched by a call to {@link #closeQuietly()}.
 96  
      *
 97  
      * @param file the JAR file to open
 98  
      * @throws java.io.IOException if there is a problem opening the JAR file, or reading the manifest. The JAR file will be closed if this occurs.
 99  
      */
 100  
     public JarAnalyzer( File file )
 101  
         throws IOException
 102  0
     {
 103  
         try
 104  
         {
 105  0
             this.jarFile = new JarFile( file );
 106  
         }
 107  0
         catch ( ZipException e )
 108  
         {
 109  0
             ZipException ioe = new ZipException( "Failed to open file " + file + " : " + e.getMessage() );
 110  0
             ioe.initCause( e );
 111  0
             throw ioe;
 112  0
         }
 113  
 
 114  
         // Obtain entries list.
 115  0
         List entries = Collections.list( jarFile.entries() );
 116  
 
 117  
         // Sorting of list is done by name to ensure a bytecode hash is always consistent.
 118  0
         Collections.sort( entries, new Comparator()
 119  0
         {
 120  
             public int compare( Object o1, Object o2 )
 121  
             {
 122  0
                 JarEntry entry1 = (JarEntry) o1;
 123  0
                 JarEntry entry2 = (JarEntry) o2;
 124  
 
 125  0
                 return entry1.getName().compareTo( entry2.getName() );
 126  
             }
 127  
         } );
 128  
 
 129  
         Manifest manifest;
 130  
         try
 131  
         {
 132  0
             manifest = jarFile.getManifest();
 133  
         }
 134  0
         catch ( IOException e )
 135  
         {
 136  0
             closeQuietly();
 137  0
             throw e;
 138  0
         }
 139  0
         this.jarData = new JarData( file, manifest, entries );
 140  0
     }
 141  
 
 142  
     /**
 143  
      * Get the data for an individual entry in the JAR. The caller should closeQuietly the input stream, and should not retain
 144  
      * the stream as the JAR file may be closed elsewhere.
 145  
      *
 146  
      * @param entry the JAR entry to read from
 147  
      * @return the input stream of the individual JAR entry.
 148  
      * @throws java.io.IOException if there is a problem opening the individual entry
 149  
      */
 150  
     public InputStream getEntryInputStream( JarEntry entry )
 151  
         throws IOException
 152  
     {
 153  0
         return jarFile.getInputStream( entry );
 154  
     }
 155  
 
 156  
     /**
 157  
      * Close the associated JAR file, ignoring any errors that may occur.
 158  
      */
 159  
     public void closeQuietly()
 160  
     {
 161  
         try
 162  
         {
 163  0
             jarFile.close();
 164  
         }
 165  0
         catch ( IOException e )
 166  
         {
 167  
             // not much we can do about it but ignore it
 168  0
         }
 169  0
     }
 170  
 
 171  
     /**
 172  
      * Filter a list of JAR entries against the pattern.
 173  
      *
 174  
      * @param pattern the pattern to filter against
 175  
      * @return the list of files found, in {@link java.util.jar.JarEntry} elements
 176  
      */
 177  
     public List filterEntries( Pattern pattern )
 178  
     {
 179  0
         List ret = new ArrayList();
 180  
 
 181  0
         Iterator it = getEntries().iterator();
 182  0
         while ( it.hasNext() )
 183  
         {
 184  0
             JarEntry entry = (JarEntry) it.next();
 185  
 
 186  0
             Matcher mat = pattern.matcher( entry.getName() );
 187  0
             if ( mat.find() )
 188  
             {
 189  0
                 ret.add( entry );
 190  
             }
 191  0
         }
 192  0
         return ret;
 193  
     }
 194  
 
 195  
     /**
 196  
      * Get all the classes in the JAR.
 197  
      *
 198  
      * @return the list of files found, in {@link java.util.jar.JarEntry} elements
 199  
      */
 200  
     public List getClassEntries()
 201  
     {
 202  0
         return filterEntries( CLASS_FILTER );
 203  
     }
 204  
 
 205  
     /**
 206  
      * Get all the Maven POM entries in the JAR.
 207  
      *
 208  
      * @return the list of files found, in {@link java.util.jar.JarEntry} elements
 209  
      */
 210  
     public List getMavenPomEntries()
 211  
     {
 212  0
         return filterEntries( MAVEN_POM_FILTER );
 213  
     }
 214  
 
 215  
     /**
 216  
      * Get all the version text files in the JAR.
 217  
      *
 218  
      * @return the list of files found, in {@link java.util.jar.JarEntry} elements
 219  
      */
 220  
     public List getVersionEntries()
 221  
     {
 222  0
         return filterEntries( VERSION_FILTER );
 223  
     }
 224  
 
 225  
     /**
 226  
      * Get all the contained files in the JAR.
 227  
      *
 228  
      * @return the list of files found, in {@link java.util.jar.JarEntry} elements
 229  
      */
 230  
     public List getEntries()
 231  
     {
 232  0
         return jarData.getEntries();
 233  
     }
 234  
 
 235  
     /**
 236  
      * Get the file that was opened by this analyzer.
 237  
      *
 238  
      * @return the JAR file reference
 239  
      */
 240  
     public File getFile()
 241  
     {
 242  0
         return jarData.getFile();
 243  
     }
 244  
 
 245  
     public JarData getJarData()
 246  
     {
 247  0
         return jarData;
 248  
     }
 249  
 }