]> source.dussan.org Git - archiva.git/blob
9d6ba7014331fffa92e264874a2caa81a9120f8a
[archiva.git] /
1 package org.apache.maven.repository.indexing.record;
2
3 /*
4  * Copyright 2005-2006 The Apache Software Foundation.
5  *
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
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;
31
32 import java.io.File;
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;
41 import java.util.Set;
42 import java.util.zip.ZipEntry;
43 import java.util.zip.ZipException;
44 import java.util.zip.ZipFile;
45
46 /**
47  * An index record type for the standard index.
48  *
49  * @author Edwin Punzalan
50  * @author Brett Porter
51  * @plexus.component role="org.apache.maven.repository.indexing.record.RepositoryIndexRecordFactory" role-hint="standard"
52  */
53 public class StandardArtifactIndexRecordFactory
54     extends AbstractArtifactIndexRecordFactory
55 {
56     /**
57      * A list of artifact types to treat as a zip archive.
58      *
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.
60      */
61     private static final Set ARCHIVE_TYPES =
62         new HashSet( Arrays.asList( new String[]{"jar", "zip", "ejb", "par", "sar", "war", "ear"} ) );
63
64     /**
65      * @plexus.requirement
66      */
67     private ArtifactFactory artifactFactory;
68
69     /**
70      * @plexus.requirement
71      */
72     private MavenProjectBuilder projectBuilder;
73
74     private static final String PLUGIN_METADATA_NAME = "META-INF/maven/plugin.xml";
75
76     private static final String ARCHETYPE_METADATA_NAME = "META-INF/maven/archetype.xml";
77
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";
80
81     public RepositoryIndexRecord createRecord( Artifact artifact )
82         throws RepositoryIndexException
83     {
84         StandardArtifactIndexRecord record = null;
85
86         File file = artifact.getFile();
87         // TODO: is this condition really a possibility?
88         if ( file != null && file.exists() )
89         {
90             String md5 = readChecksum( file, Digester.MD5 );
91             String sha1 = readChecksum( file, Digester.SHA1 );
92
93             List files = null;
94             boolean archive = ARCHIVE_TYPES.contains( artifact.getType() );
95             try
96             {
97                 if ( archive )
98                 {
99                     files = readFilesInArchive( file );
100                 }
101             }
102             catch ( IOException e )
103             {
104                 getLogger().error( "Error reading artifact file, omitting from index: " + e.getMessage() );
105             }
106
107             // If it's an archive with no files, don't create a record
108             if ( !archive || files != null )
109             {
110                 record = new StandardArtifactIndexRecord();
111
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() );
124                 if ( files != null )
125                 {
126                     populateArchiveEntries( files, record, artifact.getFile() );
127                 }
128
129                 if ( !"pom".equals( artifact.getType() ) )
130                 {
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() )
138                     {
139                         try
140                         {
141                             populatePomEntries( readPom( pomArtifact, artifact.getRepository() ), record );
142                         }
143                         catch ( ProjectBuildingException e )
144                         {
145                             getLogger().error( "Error reading POM file, not populating in index: " + e.getMessage() );
146                         }
147                     }
148                 }
149                 else
150                 {
151                     Model model;
152                     try
153                     {
154                         model = readPom( artifact, artifact.getRepository() );
155
156                         if ( !"pom".equals( model.getPackaging() ) )
157                         {
158                             // Don't return a record for a POM that is does not belong on its own
159                             record = null;
160                         }
161                         else
162                         {
163                             populatePomEntries( model, record );
164                         }
165                     }
166                     catch ( ProjectBuildingException e )
167                     {
168                         getLogger().error( "Error reading POM file, not populating in index: " + e.getMessage() );
169                     }
170                 }
171             }
172         }
173
174         return record;
175     }
176
177     private void populatePomEntries( Model pom, StandardArtifactIndexRecord record )
178     {
179         record.setPackaging( pom.getPackaging() );
180         record.setProjectName( pom.getName() );
181         record.setProjectDescription( pom.getDescription() );
182         record.setInceptionYear( pom.getInceptionYear() );
183
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 );
189 */
190     }
191
192     private Model readPom( Artifact artifact, ArtifactRepository repository )
193         throws RepositoryIndexException, ProjectBuildingException
194     {
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();
199     }
200
201     private void populateArchiveEntries( List files, StandardArtifactIndexRecord record, File artifactFile )
202         throws RepositoryIndexException
203     {
204         List classes = new ArrayList();
205         List fileList = new ArrayList();
206
207         for ( Iterator i = files.iterator(); i.hasNext(); )
208         {
209             String name = (String) i.next();
210
211             // ignore directories
212             if ( !name.endsWith( "/" ) )
213             {
214                 fileList.add( name );
215
216                 if ( isClass( name ) )
217                 {
218                     classes.add( name.substring( 0, name.length() - 6 ).replace( '/', '.' ) );
219                 }
220                 else if ( PLUGIN_METADATA_NAME.equals( name ) )
221                 {
222                     populatePluginEntries( readXmlMetadataFileInJar( artifactFile, PLUGIN_METADATA_NAME ), record );
223                 }
224                 else if ( ARCHETYPE_METADATA_NAME.equals( name ) || ARCHETYPE_METADATA_NAME_OLD.equals( name ) )
225                 {
226                     populateArchetypeEntries( record );
227                 }
228             }
229         }
230
231         if ( !classes.isEmpty() )
232         {
233             record.setClasses( classes );
234         }
235         if ( !fileList.isEmpty() )
236         {
237             record.setFiles( fileList );
238         }
239     }
240
241     private void populateArchetypeEntries( StandardArtifactIndexRecord record )
242     {
243         // Typically discovered as a JAR
244         record.setType( "maven-archetype" );
245     }
246
247     private Xpp3Dom readXmlMetadataFileInJar( File file, String name )
248         throws RepositoryIndexException
249     {
250         // TODO: would be more efficient with original ZipEntry still around
251
252         Xpp3Dom xpp3Dom;
253         ZipFile zipFile = null;
254         try
255         {
256             zipFile = new ZipFile( file );
257             ZipEntry entry = zipFile.getEntry( name );
258             xpp3Dom = Xpp3DomBuilder.build( new InputStreamReader( zipFile.getInputStream( entry ) ) );
259         }
260         catch ( ZipException e )
261         {
262             throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
263         }
264         catch ( IOException e )
265         {
266             throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
267         }
268         catch ( XmlPullParserException e )
269         {
270             throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
271         }
272         finally
273         {
274             closeQuietly( zipFile );
275         }
276         return xpp3Dom;
277     }
278
279     public void populatePluginEntries( Xpp3Dom metadata, StandardArtifactIndexRecord record )
280     {
281         // Typically discovered as a JAR
282         record.setType( "maven-plugin" );
283
284         Xpp3Dom prefix = metadata.getChild( "goalPrefix" );
285
286         if ( prefix != null )
287         {
288             record.setPluginPrefix( prefix.getValue() );
289         }
290     }
291 }