Coverage Report - org.apache.maven.plugins.shade.filter.MinijarFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
MinijarFilter
0 %
0/70
0 %
0/26
2,75
 
 1  
 package org.apache.maven.plugins.shade.filter;
 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 org.apache.maven.artifact.Artifact;
 23  
 import org.apache.maven.plugin.logging.Log;
 24  
 import org.apache.maven.project.MavenProject;
 25  
 import org.codehaus.plexus.util.IOUtil;
 26  
 import org.vafer.jdependency.Clazz;
 27  
 import org.vafer.jdependency.Clazzpath;
 28  
 import org.vafer.jdependency.ClazzpathUnit;
 29  
 
 30  
 import java.io.File;
 31  
 import java.io.FileInputStream;
 32  
 import java.io.IOException;
 33  
 import java.io.InputStream;
 34  
 import java.util.Collections;
 35  
 import java.util.HashSet;
 36  
 import java.util.Iterator;
 37  
 import java.util.List;
 38  
 import java.util.Set;
 39  
 
 40  
 /**
 41  
  * A filter that prevents the inclusion of classes not required in the final jar.
 42  
  *
 43  
  * @author Torsten Curdt
 44  
  */
 45  
 public class MinijarFilter
 46  
     implements Filter
 47  
 {
 48  
 
 49  
     private Log log;
 50  
 
 51  
     private Set removable;
 52  
 
 53  
     private int classesKept;
 54  
 
 55  
     private int classesRemoved;
 56  
 
 57  
     public MinijarFilter( MavenProject project, Log log )
 58  
         throws IOException
 59  
     {
 60  0
         this( project, log, Collections.<SimpleFilter>emptyList() );
 61  0
     }
 62  
 
 63  
     /**
 64  
      *
 65  
      * @since 1.6
 66  
      */
 67  
     public MinijarFilter( MavenProject project, Log log, List<SimpleFilter> simpleFilters )
 68  
         throws IOException
 69  0
     {
 70  
 
 71  0
         this.log = log;
 72  
 
 73  0
         Clazzpath cp = new Clazzpath();
 74  
 
 75  0
         ClazzpathUnit artifactUnit =
 76  
             cp.addClazzpathUnit( new FileInputStream( project.getArtifact().getFile() ), project.toString() );
 77  
 
 78  0
         for ( Iterator it = project.getArtifacts().iterator(); it.hasNext(); )
 79  
         {
 80  0
             Artifact dependency = (Artifact) it.next();
 81  
 
 82  0
             InputStream is = null;
 83  
             try
 84  
             {
 85  0
                 is = new FileInputStream( dependency.getFile() );
 86  0
                 cp.addClazzpathUnit( is, dependency.toString() );
 87  
             }
 88  
             finally
 89  
             {
 90  0
                 IOUtil.close( is );
 91  0
             }
 92  0
         }
 93  
 
 94  0
         removable = cp.getClazzes();
 95  0
         removePackages( artifactUnit );
 96  0
         removable.removeAll( artifactUnit.getClazzes() );
 97  0
         removable.removeAll( artifactUnit.getTransitiveDependencies() );
 98  0
         removeSpecificallyIncludedClasses( project, simpleFilters == null
 99  
             ? Collections.<SimpleFilter>emptyList()
 100  
             : simpleFilters );
 101  0
     }
 102  
 
 103  
     private void removePackages( ClazzpathUnit artifactUnit )
 104  
     {
 105  0
         Set packageNames = new HashSet();
 106  0
         removePackages( artifactUnit.getClazzes(), packageNames );
 107  0
         removePackages( artifactUnit.getTransitiveDependencies(), packageNames );
 108  0
     }
 109  
 
 110  
     private void removePackages( Set clazzes, Set packageNames )
 111  
     {
 112  0
         Iterator it = clazzes.iterator();
 113  0
         while ( it.hasNext() )
 114  
         {
 115  0
             Clazz clazz = (Clazz) it.next();
 116  0
             String name = clazz.getName();
 117  0
             while ( name.contains( "." ) )
 118  
             {
 119  0
                 name = name.substring( 0, name.lastIndexOf( '.' ) );
 120  0
                 if ( packageNames.add( name ) )
 121  
                 {
 122  0
                     removable.remove( new Clazz( name + ".package-info" ) );
 123  
                 }
 124  
             }
 125  0
         }
 126  0
     }
 127  
 
 128  
     private void removeSpecificallyIncludedClasses( MavenProject project, List<SimpleFilter> simpleFilters )
 129  
         throws IOException
 130  
     {
 131  
         //remove classes specifically included in filters
 132  0
         Clazzpath checkCp = new Clazzpath();
 133  0
         for ( Iterator it = project.getArtifacts().iterator(); it.hasNext(); )
 134  
         {
 135  0
             Artifact dependency = (Artifact) it.next();
 136  0
             File jar = dependency.getFile();
 137  
 
 138  0
             for ( Iterator<SimpleFilter> i = simpleFilters.iterator(); i.hasNext(); )
 139  
             {
 140  0
                 SimpleFilter simpleFilter = i.next();
 141  0
                 if ( simpleFilter.canFilter( jar ) )
 142  
                 {
 143  0
                     InputStream is = null;
 144  0
                     ClazzpathUnit depClazzpathUnit = null;
 145  
                     try
 146  
                     {
 147  0
                         is = new FileInputStream( dependency.getFile() );
 148  0
                         depClazzpathUnit = checkCp.addClazzpathUnit( is, dependency.toString() );
 149  
                     }
 150  
                     finally
 151  
                     {
 152  0
                         IOUtil.close( is );
 153  0
                     }
 154  
 
 155  0
                     if ( depClazzpathUnit != null )
 156  
                     {
 157  0
                         Iterator<Clazz> j = removable.iterator();
 158  0
                         while ( j.hasNext() )
 159  
                         {
 160  0
                             Clazz clazz = j.next();
 161  
 
 162  0
                             if ( depClazzpathUnit.getClazzes().contains( clazz ) && simpleFilter.isSpecificallyIncluded(
 163  
                                 clazz.getName().replace( '.', '/' ) ) )
 164  
                             {
 165  0
                                 log.info( clazz.getName() + " not removed because it was specifically included" );
 166  0
                                 j.remove();
 167  
                             }
 168  0
                         }
 169  
                     }
 170  
                 }
 171  0
             }
 172  0
         }
 173  0
     }
 174  
 
 175  
     public boolean canFilter( File jar )
 176  
     {
 177  0
         return true;
 178  
     }
 179  
 
 180  
     public boolean isFiltered( String classFile )
 181  
     {
 182  0
         String className = classFile.replace( '/', '.' ).replaceFirst( "\\.class$", "" );
 183  0
         Clazz clazz = new Clazz( className );
 184  
 
 185  0
         if ( removable.contains( clazz ) )
 186  
         {
 187  0
             log.debug( "Removing " + className );
 188  0
             classesRemoved += 1;
 189  0
             return true;
 190  
         }
 191  
 
 192  0
         classesKept += 1;
 193  0
         return false;
 194  
     }
 195  
 
 196  
     public void finished()
 197  
     {
 198  0
         int classes_total = classesRemoved + classesKept;
 199  0
         log.info(
 200  
             "Minimized " + classes_total + " -> " + classesKept + " (" + (int) ( 100 * classesKept / classes_total )
 201  
                 + "%)" );
 202  0
     }
 203  
 }