1 package org.apache.maven.repository.indexing.record;
4 * Copyright 2005-2006 The Apache Software Foundation.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 import org.apache.maven.artifact.Artifact;
20 import org.apache.maven.artifact.factory.ArtifactFactory;
21 import org.apache.maven.artifact.repository.ArtifactRepository;
22 import org.apache.maven.model.Model;
23 import org.apache.maven.project.MavenProject;
24 import org.apache.maven.project.MavenProjectBuilder;
25 import org.apache.maven.project.ProjectBuildingException;
26 import org.apache.maven.repository.digest.Digester;
27 import org.apache.maven.repository.indexing.RepositoryIndexException;
28 import org.codehaus.plexus.util.xml.Xpp3Dom;
29 import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
30 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
33 import java.io.IOException;
34 import java.io.InputStreamReader;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.Collections;
38 import java.util.HashSet;
39 import java.util.Iterator;
40 import java.util.List;
42 import java.util.zip.ZipEntry;
43 import java.util.zip.ZipException;
44 import java.util.zip.ZipFile;
47 * An index record type for the standard index.
49 * @author Edwin Punzalan
50 * @author Brett Porter
51 * @plexus.component role="org.apache.maven.repository.indexing.record.RepositoryIndexRecordFactory" role-hint="standard"
53 public class StandardArtifactIndexRecordFactory
54 extends AbstractArtifactIndexRecordFactory
57 * A list of artifact types to treat as a zip archive.
59 * @todo this should be smarter (perhaps use plexus archiver to look for an unarchiver, and make the ones for zip configurable since sar, par, etc can be added at random.
61 private static final Set ARCHIVE_TYPES =
62 new HashSet( Arrays.asList( new String[]{"jar", "zip", "ejb", "par", "sar", "war", "ear"} ) );
67 private ArtifactFactory artifactFactory;
72 private MavenProjectBuilder projectBuilder;
74 private static final String PLUGIN_METADATA_NAME = "META-INF/maven/plugin.xml";
76 private static final String ARCHETYPE_METADATA_NAME = "META-INF/maven/archetype.xml";
78 // some current/old archetypes have the archetype.xml at different location.
79 private static final String ARCHETYPE_METADATA_NAME_OLD = "META-INF/archetype.xml";
81 public RepositoryIndexRecord createRecord( Artifact artifact )
82 throws RepositoryIndexException
84 StandardArtifactIndexRecord record = null;
86 File file = artifact.getFile();
87 // TODO: is this condition really a possibility?
88 if ( file != null && file.exists() )
90 String md5 = readChecksum( file, Digester.MD5 );
91 String sha1 = readChecksum( file, Digester.SHA1 );
94 boolean archive = ARCHIVE_TYPES.contains( artifact.getType() );
99 files = readFilesInArchive( file );
102 catch ( IOException e )
104 getLogger().error( "Error reading artifact file, omitting from index: " + e.getMessage() );
107 // If it's an archive with no files, don't create a record
108 if ( !archive || files != null )
110 record = new StandardArtifactIndexRecord();
112 record.setGroupId( artifact.getGroupId() );
113 record.setArtifactId( artifact.getArtifactId() );
114 record.setBaseVersion( artifact.getBaseVersion() );
115 record.setVersion( artifact.getVersion() );
116 record.setClassifier( artifact.getClassifier() );
117 record.setType( artifact.getType() );
118 record.setMd5Checksum( md5 );
119 record.setSha1Checksum( sha1 );
120 record.setFilename( artifact.getRepository().pathOf( artifact ) );
121 record.setLastModified( file.lastModified() );
122 record.setSize( file.length() );
123 record.setRepository( artifact.getRepository().getId() );
126 populateArchiveEntries( files, record, artifact.getFile() );
129 if ( !"pom".equals( artifact.getType() ) )
131 Artifact pomArtifact = artifactFactory.createProjectArtifact( artifact.getGroupId(),
132 artifact.getArtifactId(),
133 artifact.getVersion() );
134 pomArtifact.isSnapshot(); // gross hack around bug in maven-artifact
135 File pomFile = new File( artifact.getRepository().getBasedir(),
136 artifact.getRepository().pathOf( pomArtifact ) );
137 if ( pomFile.exists() )
141 populatePomEntries( readPom( pomArtifact, artifact.getRepository() ), record );
143 catch ( ProjectBuildingException e )
145 getLogger().error( "Error reading POM file, not populating in index: " + e.getMessage() );
154 model = readPom( artifact, artifact.getRepository() );
156 if ( !"pom".equals( model.getPackaging() ) )
158 // Don't return a record for a POM that is does not belong on its own
163 populatePomEntries( model, record );
166 catch ( ProjectBuildingException e )
168 getLogger().error( "Error reading POM file, not populating in index: " + e.getMessage() );
177 private void populatePomEntries( Model pom, StandardArtifactIndexRecord record )
179 record.setPackaging( pom.getPackaging() );
180 record.setProjectName( pom.getName() );
181 record.setProjectDescription( pom.getDescription() );
182 record.setInceptionYear( pom.getInceptionYear() );
184 /* TODO: fields for later
185 indexPlugins( doc, FLD_PLUGINS_BUILD, pom.getBuild().getPlugins().iterator() );
186 indexReportPlugins( doc, FLD_PLUGINS_REPORT, pom.getReporting().getPlugins().iterator() );
187 record.setDependencies( dependencies );
188 record.setLicenses( licenses );
192 private Model readPom( Artifact artifact, ArtifactRepository repository )
193 throws RepositoryIndexException, ProjectBuildingException
195 // TODO: this can create a -SNAPSHOT.pom when it didn't exist and a timestamped one did. This is harmless, but should be avoided
196 // TODO: will this pollute with local repo metadata?
197 MavenProject project = projectBuilder.buildFromRepository( artifact, Collections.EMPTY_LIST, repository );
198 return project.getModel();
201 private void populateArchiveEntries( List files, StandardArtifactIndexRecord record, File artifactFile )
202 throws RepositoryIndexException
204 List classes = new ArrayList();
205 List fileList = new ArrayList();
207 for ( Iterator i = files.iterator(); i.hasNext(); )
209 String name = (String) i.next();
211 // ignore directories
212 if ( !name.endsWith( "/" ) )
214 fileList.add( name );
216 if ( isClass( name ) )
218 classes.add( name.substring( 0, name.length() - 6 ).replace( '/', '.' ) );
220 else if ( PLUGIN_METADATA_NAME.equals( name ) )
222 populatePluginEntries( readXmlMetadataFileInJar( artifactFile, PLUGIN_METADATA_NAME ), record );
224 else if ( ARCHETYPE_METADATA_NAME.equals( name ) || ARCHETYPE_METADATA_NAME_OLD.equals( name ) )
226 populateArchetypeEntries( record );
231 if ( !classes.isEmpty() )
233 record.setClasses( classes );
235 if ( !fileList.isEmpty() )
237 record.setFiles( fileList );
241 private void populateArchetypeEntries( StandardArtifactIndexRecord record )
243 // Typically discovered as a JAR
244 record.setType( "maven-archetype" );
247 private Xpp3Dom readXmlMetadataFileInJar( File file, String name )
248 throws RepositoryIndexException
250 // TODO: would be more efficient with original ZipEntry still around
253 ZipFile zipFile = null;
256 zipFile = new ZipFile( file );
257 ZipEntry entry = zipFile.getEntry( name );
258 xpp3Dom = Xpp3DomBuilder.build( new InputStreamReader( zipFile.getInputStream( entry ) ) );
260 catch ( ZipException e )
262 throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
264 catch ( IOException e )
266 throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
268 catch ( XmlPullParserException e )
270 throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
274 closeQuietly( zipFile );
279 public void populatePluginEntries( Xpp3Dom metadata, StandardArtifactIndexRecord record )
281 // Typically discovered as a JAR
282 record.setType( "maven-plugin" );
284 Xpp3Dom prefix = metadata.getChild( "goalPrefix" );
286 if ( prefix != null )
288 record.setPluginPrefix( prefix.getValue() );