| package org.apache.maven.index.creator; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import javax.inject.Named; |
| import javax.inject.Singleton; |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.Collection; |
| |
| import org.apache.lucene.document.Document; |
| import org.apache.lucene.document.Field; |
| import org.apache.lucene.document.Field.Index; |
| import org.apache.lucene.document.Field.Store; |
| import org.apache.maven.index.ArtifactAvailability; |
| import org.apache.maven.index.ArtifactContext; |
| import org.apache.maven.index.ArtifactInfo; |
| import org.apache.maven.index.IndexerField; |
| import org.apache.maven.index.IndexerFieldVersion; |
| import org.apache.maven.index.MAVEN; |
| import org.apache.maven.index.NEXUS; |
| import org.apache.maven.index.artifact.Gav; |
| import org.apache.maven.index.locator.JavadocLocator; |
| import org.apache.maven.index.locator.Locator; |
| import org.apache.maven.index.locator.Sha1Locator; |
| import org.apache.maven.index.locator.SignatureLocator; |
| import org.apache.maven.index.locator.SourcesLocator; |
| import org.apache.maven.model.Model; |
| import org.codehaus.plexus.util.FileUtils; |
| import org.codehaus.plexus.util.StringUtils; |
| |
| /** |
| * A minimal index creator used to provide basic information about Maven artifact. This creator will create the index |
| * fast, will not open any file to be fastest as possible but it has some drawbacks: The information gathered by this |
| * creator are sometimes based on "best-effort" only, and does not reflect the reality (ie. maven archetype packaging @see |
| * {@link MavenArchetypeArtifactInfoIndexCreator}). |
| * |
| * @author cstamas |
| */ |
| @Singleton |
| @Named( MinimalArtifactInfoIndexCreator.ID ) |
| public class MinimalArtifactInfoIndexCreator |
| extends AbstractIndexCreator |
| implements LegacyDocumentUpdater |
| { |
| public static final String ID = "min"; |
| |
| /** |
| * Info: packaging, lastModified, size, sourcesExists, javadocExists, signatureExists. Stored, not indexed. |
| */ |
| public static final IndexerField FLD_INFO = new IndexerField( NEXUS.INFO, IndexerFieldVersion.V1, "i", |
| "Artifact INFO (not indexed, stored)", Store.YES, Index.NO ); |
| |
| public static final IndexerField FLD_GROUP_ID_KW = new IndexerField( MAVEN.GROUP_ID, IndexerFieldVersion.V1, "g", |
| "Artifact GroupID (as keyword)", Store.NO, Index.NOT_ANALYZED ); |
| |
| public static final IndexerField FLD_GROUP_ID = new IndexerField( MAVEN.GROUP_ID, IndexerFieldVersion.V3, |
| "groupId", "Artifact GroupID (tokenized)", Store.NO, Index.ANALYZED ); |
| |
| public static final IndexerField FLD_ARTIFACT_ID_KW = new IndexerField( MAVEN.ARTIFACT_ID, IndexerFieldVersion.V1, |
| "a", "Artifact ArtifactID (as keyword)", Store.NO, Index.NOT_ANALYZED ); |
| |
| public static final IndexerField FLD_ARTIFACT_ID = new IndexerField( MAVEN.ARTIFACT_ID, IndexerFieldVersion.V3, |
| "artifactId", "Artifact ArtifactID (tokenized)", Store.NO, Index.ANALYZED ); |
| |
| public static final IndexerField FLD_VERSION_KW = new IndexerField( MAVEN.VERSION, IndexerFieldVersion.V1, "v", |
| "Artifact Version (as keyword)", Store.NO, Index.NOT_ANALYZED ); |
| |
| public static final IndexerField FLD_VERSION = new IndexerField( MAVEN.VERSION, IndexerFieldVersion.V3, "version", |
| "Artifact Version (tokenized)", Store.NO, Index.ANALYZED ); |
| |
| public static final IndexerField FLD_PACKAGING = new IndexerField( MAVEN.PACKAGING, IndexerFieldVersion.V1, "p", |
| "Artifact Packaging (as keyword)", Store.NO, Index.NOT_ANALYZED ); |
| |
| public static final IndexerField FLD_EXTENSION = new IndexerField( MAVEN.EXTENSION, IndexerFieldVersion.V1, "e", |
| "Artifact extension (as keyword)", Store.NO, Index.NOT_ANALYZED ); |
| |
| public static final IndexerField FLD_CLASSIFIER = new IndexerField( MAVEN.CLASSIFIER, IndexerFieldVersion.V1, "l", |
| "Artifact classifier (as keyword)", Store.NO, Index.NOT_ANALYZED ); |
| |
| public static final IndexerField FLD_NAME = new IndexerField( MAVEN.NAME, IndexerFieldVersion.V1, "n", |
| "Artifact name (tokenized, stored)", Store.YES, Index.ANALYZED ); |
| |
| public static final IndexerField FLD_DESCRIPTION = new IndexerField( MAVEN.DESCRIPTION, IndexerFieldVersion.V1, |
| "d", "Artifact description (tokenized, stored)", Store.YES, Index.ANALYZED ); |
| |
| public static final IndexerField FLD_LAST_MODIFIED = new IndexerField( MAVEN.LAST_MODIFIED, IndexerFieldVersion.V1, |
| "m", "Artifact last modified (not indexed, stored)", Store.YES, Index.NO ); |
| |
| public static final IndexerField FLD_SHA1 = new IndexerField( MAVEN.SHA1, IndexerFieldVersion.V1, "1", |
| "Artifact SHA1 checksum (as keyword, stored)", Store.YES, Index.NOT_ANALYZED ); |
| |
| private Locator jl = new JavadocLocator(); |
| |
| private Locator sl = new SourcesLocator(); |
| |
| private Locator sigl = new SignatureLocator(); |
| |
| private Locator sha1l = new Sha1Locator(); |
| |
| public MinimalArtifactInfoIndexCreator() |
| { |
| super( ID ); |
| } |
| |
| public void populateArtifactInfo( ArtifactContext ac ) |
| { |
| File artifact = ac.getArtifact(); |
| |
| File pom = ac.getPom(); |
| |
| ArtifactInfo ai = ac.getArtifactInfo(); |
| |
| if ( pom != null && pom.isFile() ) |
| { |
| ai.setLastModified( pom.lastModified() ); |
| |
| ai.setFileExtension( "pom" ); |
| } |
| |
| // TODO handle artifacts without poms |
| if ( pom != null && pom.isFile() ) |
| { |
| if ( ai.getClassifier() != null ) |
| { |
| ai.setSourcesExists( ArtifactAvailability.NOT_AVAILABLE ); |
| |
| ai.setJavadocExists( ArtifactAvailability.NOT_AVAILABLE ); |
| } |
| else |
| { |
| File sources = sl.locate( pom ); |
| if ( !sources.exists() ) |
| { |
| ai.setSourcesExists( ArtifactAvailability.NOT_PRESENT ); |
| } |
| else |
| { |
| ai.setSourcesExists( ArtifactAvailability.PRESENT ); |
| } |
| |
| File javadoc = jl.locate( pom ); |
| if ( !javadoc.exists() ) |
| { |
| ai.setJavadocExists( ArtifactAvailability.NOT_PRESENT ); |
| } |
| else |
| { |
| ai.setJavadocExists( ArtifactAvailability.PRESENT ); |
| } |
| } |
| } |
| |
| Model model = ac.getPomModel(); |
| |
| if ( model != null ) |
| { |
| ai.setName( model.getName() ); |
| |
| ai.setDescription( model.getDescription() ); |
| |
| // for main artifacts (without classifier) only: |
| if ( ai.getClassifier() == null ) |
| { |
| // only when this is not a classified artifact |
| if ( model.getPackaging() != null ) |
| { |
| // set the read value that is coming from POM |
| ai.setPackaging( model.getPackaging() ); |
| } |
| else |
| { |
| // default it, since POM is present, is read, but does not contain explicit packaging |
| // TODO: this change breaks junit tests, but not sure why is "null" expected value? |
| ai.setPackaging( "jar" ); |
| } |
| } |
| } |
| |
| if ( "pom".equals( ai.getPackaging() ) ) |
| { |
| // special case, the POM _is_ the artifact |
| artifact = pom; |
| } |
| |
| if ( artifact != null ) |
| { |
| File signature = sigl.locate( artifact ); |
| |
| ai.setSignatureExists( signature.exists() ? ArtifactAvailability.PRESENT |
| : ArtifactAvailability.NOT_PRESENT ); |
| |
| File sha1 = sha1l.locate( artifact ); |
| |
| if ( sha1.exists() ) |
| { |
| try |
| { |
| ai.setSha1( StringUtils.chomp( FileUtils.fileRead( sha1 ) ).trim().split( " " )[0] ); |
| } |
| catch ( IOException e ) |
| { |
| ac.addError( e ); |
| } |
| } |
| |
| ai.setLastModified( artifact.lastModified() ); |
| |
| ai.setSize( artifact.length() ); |
| |
| ai.setFileExtension( getExtension( artifact, ac.getGav() ) ); |
| } |
| } |
| |
| private String getExtension( File artifact, Gav gav ) |
| { |
| if ( gav != null && StringUtils.isNotBlank( gav.getExtension() ) ) |
| { |
| return gav.getExtension(); |
| } |
| |
| // last resort, the extension of the file |
| String artifactFileName = artifact.getName().toLowerCase(); |
| |
| // tar.gz? and other "special" combinations |
| if ( artifactFileName.endsWith( "tar.gz" ) ) |
| { |
| return "tar.gz"; |
| } |
| else if ( artifactFileName.equals( "tar.bz2" ) ) |
| { |
| return "tar.bz2"; |
| } |
| |
| // get the part after the last dot |
| return FileUtils.getExtension( artifactFileName ); |
| } |
| |
| public void updateDocument( ArtifactInfo ai, Document doc ) |
| { |
| String info = |
| new StringBuilder().append( ArtifactInfo.nvl( ai.getPackaging() ) ) |
| .append( ArtifactInfo.FS ).append( Long.toString( ai.getLastModified() ) ) |
| .append( ArtifactInfo.FS ).append( Long.toString( ai.getSize() ) ) |
| .append( ArtifactInfo.FS ).append( ai.getSourcesExists().toString() ) |
| .append( ArtifactInfo.FS ).append( ai.getJavadocExists().toString() ) |
| .append( ArtifactInfo.FS ).append( ai.getSignatureExists().toString() ) |
| .append( ArtifactInfo.FS ).append( ai.getFileExtension() ).toString(); |
| |
| doc.add( FLD_INFO.toField( info ) ); |
| |
| doc.add( FLD_GROUP_ID_KW.toField( ai.getGroupId() ) ); |
| doc.add( FLD_ARTIFACT_ID_KW.toField( ai.getArtifactId() ) ); |
| doc.add( FLD_VERSION_KW.toField( ai.getVersion() ) ); |
| |
| // V3 |
| doc.add( FLD_GROUP_ID.toField( ai.getGroupId() ) ); |
| doc.add( FLD_ARTIFACT_ID.toField( ai.getArtifactId() ) ); |
| doc.add( FLD_VERSION.toField( ai.getVersion() ) ); |
| doc.add( FLD_EXTENSION.toField( ai.getFileExtension() ) ); |
| |
| if ( ai.getName() != null ) |
| { |
| doc.add( FLD_NAME.toField( ai.getName() ) ); |
| } |
| |
| if ( ai.getDescription() != null ) |
| { |
| doc.add( FLD_DESCRIPTION.toField( ai.getDescription() ) ); |
| } |
| |
| if ( ai.getPackaging() != null ) |
| { |
| doc.add( FLD_PACKAGING.toField( ai.getPackaging() ) ); |
| } |
| |
| if ( ai.getClassifier() != null ) |
| { |
| doc.add( FLD_CLASSIFIER.toField( ai.getClassifier() ) ); |
| } |
| |
| if ( ai.getSha1() != null ) |
| { |
| doc.add( FLD_SHA1.toField( ai.getSha1() ) ); |
| } |
| } |
| |
| public void updateLegacyDocument( ArtifactInfo ai, Document doc ) |
| { |
| updateDocument( ai, doc ); |
| |
| // legacy! |
| if ( ai.getPrefix() != null ) |
| { |
| doc.add( new Field( ArtifactInfo.PLUGIN_PREFIX, ai.getPrefix(), Field.Store.YES, |
| Field.Index.NOT_ANALYZED ) ); |
| } |
| |
| if ( ai.getGoals() != null ) |
| { |
| doc.add( new Field( ArtifactInfo.PLUGIN_GOALS, ArtifactInfo.lst2str( ai.getGoals() ), Field.Store.YES, |
| Field.Index.NO ) ); |
| } |
| |
| doc.removeField( ArtifactInfo.GROUP_ID ); |
| doc.add( new Field( ArtifactInfo.GROUP_ID, ai.getGroupId(), Field.Store.NO, Field.Index.NOT_ANALYZED ) ); |
| } |
| |
| public boolean updateArtifactInfo( Document doc, ArtifactInfo ai ) |
| { |
| boolean res = false; |
| |
| String uinfo = doc.get( ArtifactInfo.UINFO ); |
| |
| if ( uinfo != null ) |
| { |
| String[] r = ArtifactInfo.FS_PATTERN.split( uinfo ); |
| |
| ai.setGroupId( r[0] ); |
| |
| ai.setArtifactId( r[1] ); |
| |
| ai.setVersion( r[2] ); |
| |
| ai.setClassifier( ArtifactInfo.renvl( r[3] ) ); |
| |
| if ( r.length > 4 ) |
| { |
| ai.setFileExtension( r[4] ); |
| } |
| |
| res = true; |
| } |
| |
| String info = doc.get( ArtifactInfo.INFO ); |
| |
| if ( info != null ) |
| { |
| String[] r = ArtifactInfo.FS_PATTERN.split( info ); |
| |
| ai.setPackaging( ArtifactInfo.renvl( r[0] ) ); |
| |
| ai.setLastModified( Long.parseLong( r[1] ) ); |
| |
| ai.setSize( Long.parseLong( r[2] ) ); |
| |
| ai.setSourcesExists( ArtifactAvailability.fromString( r[ 3 ] ) ); |
| |
| ai.setJavadocExists( ArtifactAvailability.fromString( r[ 4 ] ) ); |
| |
| ai.setSignatureExists( ArtifactAvailability.fromString( r[ 5 ] ) ); |
| |
| if ( r.length > 6 ) |
| { |
| ai.setFileExtension( r[6] ); |
| } |
| else |
| { |
| if ( ai.getClassifier() != null // |
| || "pom".equals( ai.getPackaging() ) // |
| || "war".equals( ai.getPackaging() ) // |
| || "ear".equals( ai.getPackaging() ) ) |
| { |
| ai.setFileExtension( ai.getPackaging() ); |
| } |
| else |
| { |
| ai.setFileExtension( "jar" ); // best guess |
| } |
| } |
| |
| res = true; |
| } |
| |
| String name = doc.get( ArtifactInfo.NAME ); |
| |
| if ( name != null ) |
| { |
| ai.setName( name ); |
| |
| res = true; |
| } |
| |
| String description = doc.get( ArtifactInfo.DESCRIPTION ); |
| |
| if ( description != null ) |
| { |
| ai.setDescription( description ); |
| |
| res = true; |
| } |
| |
| // sometimes there's a pom without packaging(default to jar), but no artifact, then the value will be a "null" |
| // String |
| if ( "null".equals( ai.getPackaging() ) ) |
| { |
| ai.setPackaging( null ); |
| } |
| |
| String sha1 = doc.get( ArtifactInfo.SHA1 ); |
| |
| if ( sha1 != null ) |
| { |
| ai.setSha1( sha1 ); |
| } |
| |
| return res; |
| |
| // artifactInfo.fname = ??? |
| } |
| |
| // == |
| |
| @Override |
| public String toString() |
| { |
| return ID; |
| } |
| |
| public Collection<IndexerField> getIndexerFields() |
| { |
| return Arrays.asList( FLD_INFO, FLD_GROUP_ID_KW, FLD_GROUP_ID, FLD_ARTIFACT_ID_KW, FLD_ARTIFACT_ID, |
| FLD_VERSION_KW, FLD_VERSION, FLD_PACKAGING, FLD_CLASSIFIER, FLD_NAME, FLD_DESCRIPTION, FLD_LAST_MODIFIED, |
| FLD_SHA1 ); |
| } |
| } |