Coverage Report - org.apache.maven.index.creator.JarFileContentsIndexCreator
 
Classes in this File Line Coverage Branch Coverage Complexity
JarFileContentsIndexCreator
95 %
64/67
80 %
37/46
3,778
 
 1  
 package org.apache.maven.index.creator;
 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.util.Arrays;
 25  
 import java.util.Collection;
 26  
 import java.util.List;
 27  
 
 28  
 import org.apache.lucene.document.Document;
 29  
 import org.apache.lucene.document.Field.Index;
 30  
 import org.apache.lucene.document.Field.Store;
 31  
 import org.apache.maven.index.ArtifactContext;
 32  
 import org.apache.maven.index.ArtifactInfo;
 33  
 import org.apache.maven.index.IndexerField;
 34  
 import org.apache.maven.index.IndexerFieldVersion;
 35  
 import org.apache.maven.index.MAVEN;
 36  
 import org.apache.maven.index.context.IndexCreator;
 37  
 import org.apache.maven.index.util.zip.ZipFacade;
 38  
 import org.apache.maven.index.util.zip.ZipHandle;
 39  
 import org.codehaus.plexus.component.annotations.Component;
 40  
 import org.codehaus.plexus.util.StringUtils;
 41  
 
 42  
 /**
 43  
  * An index creator used to index Java class names from a Maven artifact (JAR or WAR for now). Will open up the file and
 44  
  * collect all the class names from it.
 45  
  */
 46  
 @Component( role = IndexCreator.class, hint = JarFileContentsIndexCreator.ID )
 47  
 public class JarFileContentsIndexCreator
 48  
     extends AbstractIndexCreator
 49  
     implements LegacyDocumentUpdater
 50  
 {
 51  
     public static final String ID = "jarContent";
 52  
 
 53  1
     public static final IndexerField FLD_CLASSNAMES = new IndexerField( MAVEN.CLASSNAMES, IndexerFieldVersion.V3,
 54  
         "classnames", "Artifact Classes (tokenized)", Store.NO, Index.ANALYZED );
 55  
 
 56  
     /**
 57  
      * NexusAnalyzer makes exception with this field only, to keep backward compatibility with old consumers of
 58  
      * nexus-indexer. This field is here for "backward" compat only! The order is important too! FLD_CLASSNAMES must be
 59  
      * registered BEFORE FLD_CLASSNAMES_KW!
 60  
      */
 61  1
     public static final IndexerField FLD_CLASSNAMES_KW = new IndexerField( MAVEN.CLASSNAMES, IndexerFieldVersion.V1,
 62  
         "c", "Artifact Classes (tokenized on newlines only)", Store.YES, Index.ANALYZED );
 63  
 
 64  
     public JarFileContentsIndexCreator()
 65  
     {
 66  216
         super( ID );
 67  216
     }
 68  
 
 69  
     public void populateArtifactInfo( final ArtifactContext artifactContext )
 70  
         throws IOException
 71  
     {
 72  2373
         ArtifactInfo ai = artifactContext.getArtifactInfo();
 73  
 
 74  2373
         File artifactFile = artifactContext.getArtifact();
 75  
 
 76  2373
         if ( artifactFile != null && artifactFile.isFile()
 77  
             && ( artifactFile.getName().endsWith( ".jar" ) || artifactFile.getName().endsWith( ".war" ) ) )
 78  
         {
 79  2109
             updateArtifactInfo( ai, artifactFile );
 80  
         }
 81  2329
     }
 82  
 
 83  
     public void updateDocument( final ArtifactInfo ai, final Document doc )
 84  
     {
 85  2517
         if ( ai.classNames != null )
 86  
         {
 87  1091
             doc.add( FLD_CLASSNAMES_KW.toField( ai.classNames ) );
 88  1091
             doc.add( FLD_CLASSNAMES.toField( ai.classNames ) );
 89  
         }
 90  2517
     }
 91  
 
 92  
     public void updateLegacyDocument( final ArtifactInfo ai, final Document doc )
 93  
     {
 94  146
         if ( ai.classNames != null )
 95  
         {
 96  68
             String classNames = ai.classNames;
 97  
 
 98  
             // downgrade the classNames if needed
 99  68
             if ( classNames.length() > 0 && classNames.charAt( 0 ) == '/' )
 100  
             {
 101  
                 // conversion from the new format
 102  68
                 String[] lines = classNames.split( "\\n" );
 103  68
                 StringBuilder sb = new StringBuilder();
 104  3585
                 for ( String line : lines )
 105  
                 {
 106  3517
                     sb.append( line.substring( 1 ) ).append( '\n' );
 107  
                 }
 108  
 
 109  68
                 classNames = sb.toString();
 110  
             }
 111  
 
 112  68
             doc.add( FLD_CLASSNAMES_KW.toField( classNames ) );
 113  
         }
 114  146
     }
 115  
 
 116  
     public boolean updateArtifactInfo( final Document doc, final ArtifactInfo artifactInfo )
 117  
     {
 118  781
         String names = doc.get( FLD_CLASSNAMES_KW.getKey() );
 119  
 
 120  781
         if ( names != null )
 121  
         {
 122  390
             if ( names.length() == 0 || names.charAt( 0 ) == '/' )
 123  
             {
 124  348
                 artifactInfo.classNames = names;
 125  
             }
 126  
             else
 127  
             {
 128  
                 // conversion from the old format
 129  42
                 String[] lines = names.split( "\\n" );
 130  42
                 StringBuilder sb = new StringBuilder();
 131  3106
                 for ( String line : lines )
 132  
                 {
 133  3064
                     sb.append( '/' ).append( line ).append( '\n' );
 134  
                 }
 135  42
                 artifactInfo.classNames = sb.toString();
 136  
             }
 137  
 
 138  390
             return true;
 139  
         }
 140  
 
 141  391
         return false;
 142  
     }
 143  
 
 144  
     private void updateArtifactInfo( final ArtifactInfo ai, final File f )
 145  
         throws IOException
 146  
     {
 147  2109
         if ( f.getName().endsWith( ".jar" ) )
 148  
         {
 149  2106
             updateArtifactInfo( ai, f, null );
 150  
         }
 151  3
         else if ( f.getName().endsWith( ".war" ) )
 152  
         {
 153  3
             updateArtifactInfo( ai, f, "WEB-INF/classes/" );
 154  
         }
 155  2065
     }
 156  
 
 157  
     private void updateArtifactInfo( final ArtifactInfo ai, final File f, final String strippedPrefix )
 158  
         throws IOException
 159  
     {
 160  2109
         ZipHandle handle = null;
 161  
 
 162  
         try
 163  
         {
 164  2109
             handle = ZipFacade.getZipHandle( f );
 165  
 
 166  2065
             final List<String> entries = handle.getEntries();
 167  
 
 168  2065
             final StringBuilder sb = new StringBuilder();
 169  
 
 170  2065
             for ( String name : entries )
 171  
             {
 172  160915
                 if ( name.endsWith( ".class" ) )
 173  
                 {
 174  
                     // TODO verify if class is public or protected
 175  
                     // TODO skip all inner classes for now
 176  
 
 177  87786
                     int i = name.indexOf( "$" );
 178  
 
 179  87786
                     if ( i == -1 )
 180  
                     {
 181  68893
                         if ( name.charAt( 0 ) != '/' )
 182  
                         {
 183  68893
                             sb.append( '/' );
 184  
                         }
 185  
 
 186  68893
                         if ( StringUtils.isBlank( strippedPrefix ) )
 187  
                         {
 188  
                             // class name without ".class"
 189  68890
                             sb.append( name.substring( 0, name.length() - 6 ) ).append( '\n' );
 190  
                         }
 191  3
                         else if ( name.startsWith( strippedPrefix ) && (name.length() > ( strippedPrefix.length() + 6 )) )
 192  
                         {
 193  
                             // class name without ".class" and stripped prefix
 194  3
                             sb.append( name.substring( strippedPrefix.length(), name.length() - 6 ) ).append( '\n' );
 195  
                         }
 196  
                     }
 197  160915
                 }
 198  
             }
 199  
 
 200  2065
             final String fieldValue = sb.toString().trim();
 201  
 
 202  2065
             if ( fieldValue.length() != 0 )
 203  
             {
 204  1030
                 ai.classNames = fieldValue;
 205  
             }
 206  
             else
 207  
             {
 208  1035
                 ai.classNames = null;
 209  
             }
 210  
         }
 211  
         finally
 212  
         {
 213  44
             try
 214  
             {
 215  2109
                 ZipFacade.close( handle );
 216  
             }
 217  0
             catch ( Exception e )
 218  
             {
 219  0
                 getLogger().error( "Could not close jar file properly.", e );
 220  2153
             }
 221  0
         }
 222  2065
     }
 223  
 
 224  
     @Override
 225  
     public String toString()
 226  
     {
 227  7
         return ID;
 228  
     }
 229  
 
 230  
     public Collection<IndexerField> getIndexerFields()
 231  
     {
 232  136
         return Arrays.asList( FLD_CLASSNAMES, FLD_CLASSNAMES_KW );
 233  
     }
 234  
 }