]> source.dussan.org Git - archiva.git/blob
27748050bc465071f1fa14a4d5fc24bf2ffb5969
[archiva.git] /
1 package org.apache.maven.archiva.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.archiva.digest.Digester;
20 import org.apache.maven.archiva.indexing.RepositoryIndexException;
21 import org.apache.maven.artifact.Artifact;
22 import org.apache.maven.artifact.factory.ArtifactFactory;
23 import org.apache.maven.artifact.repository.ArtifactRepository;
24 import org.apache.maven.model.Model;
25 import org.apache.maven.project.MavenProject;
26 import org.apache.maven.project.MavenProjectBuilder;
27 import org.apache.maven.project.ProjectBuildingException;
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.archiva.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", "ejb", "par", "sar", "war", "ear", "rar"} ) );
63
64     /**
65      * @plexus.requirement
66      */
67     private ArtifactFactory artifactFactory;
68
69     /**
70      * @plexus.requirement
71      */
72     private MavenProjectBuilder projectBuilder;
73
74     /**
75      * @plexus.requirement role-hint="sha1"
76      */
77     protected Digester sha1Digester;
78
79     /**
80      * @plexus.requirement role-hint="md5"
81      */
82     protected Digester md5Digester;
83
84     private static final String PLUGIN_METADATA_NAME = "META-INF/maven/plugin.xml";
85
86     private static final String ARCHETYPE_METADATA_NAME = "META-INF/maven/archetype.xml";
87
88     // some current/old archetypes have the archetype.xml at different location.
89     private static final String ARCHETYPE_METADATA_NAME_OLD = "META-INF/archetype.xml";
90
91     public RepositoryIndexRecord createRecord( Artifact artifact )
92         throws RepositoryIndexException
93     {
94         StandardArtifactIndexRecord record = null;
95
96         File file = artifact.getFile();
97
98         // TODO: is this condition really a possibility?
99         if ( file != null && file.exists() )
100         {
101             String md5 = readChecksum( file, md5Digester );
102             String sha1 = readChecksum( file, sha1Digester );
103
104             List files = null;
105             boolean archive = ARCHIVE_TYPES.contains( artifact.getType() );
106             try
107             {
108                 if ( archive )
109                 {
110                     files = readFilesInArchive( file );
111                 }
112             }
113             catch ( IOException e )
114             {
115                 getLogger().error( "Error reading artifact file, omitting from index: " + e.getMessage() );
116             }
117
118             // If it's an archive with no files, don't create a record
119             if ( !archive || files != null )
120             {
121                 record = new StandardArtifactIndexRecord();
122
123                 record.setGroupId( artifact.getGroupId() );
124                 record.setArtifactId( artifact.getArtifactId() );
125                 record.setBaseVersion( artifact.getBaseVersion() );
126                 record.setVersion( artifact.getVersion() );
127                 record.setClassifier( artifact.getClassifier() );
128                 record.setType( artifact.getType() );
129                 record.setMd5Checksum( md5 );
130                 record.setSha1Checksum( sha1 );
131                 record.setFilename( artifact.getRepository().pathOf( artifact ) );
132                 record.setLastModified( file.lastModified() );
133                 record.setSize( file.length() );
134                 record.setRepository( artifact.getRepository().getId() );
135                 if ( files != null )
136                 {
137                     populateArchiveEntries( files, record, artifact.getFile() );
138                 }
139
140                 if ( !"pom".equals( artifact.getType() ) )
141                 {
142                     Artifact pomArtifact = artifactFactory.createProjectArtifact( artifact.getGroupId(),
143                                                                                   artifact.getArtifactId(),
144                                                                                   artifact.getVersion() );
145                     pomArtifact.isSnapshot(); // gross hack around bug in maven-artifact
146                     File pomFile = new File( artifact.getRepository().getBasedir(),
147                                              artifact.getRepository().pathOf( pomArtifact ) );
148                     if ( pomFile.exists() )
149                     {
150                         try
151                         {
152                             populatePomEntries( readPom( pomArtifact, artifact.getRepository() ), record );
153                         }
154                         catch ( ProjectBuildingException e )
155                         {
156                             getLogger().error( "Error reading POM file, not populating in index: " + e.getMessage() );
157                         }
158                     }
159                 }
160                 else
161                 {
162                     Model model;
163                     try
164                     {
165                         model = readPom( artifact, artifact.getRepository() );
166
167                         if ( !"pom".equals( model.getPackaging() ) )
168                         {
169                             // Don't return a record for a POM that is does not belong on its own
170                             record = null;
171                         }
172                         else
173                         {
174                             populatePomEntries( model, record );
175                         }
176                     }
177                     catch ( ProjectBuildingException e )
178                     {
179                         getLogger().error( "Error reading POM file, not populating in index: " + e.getMessage() );
180                     }
181                 }
182             }
183         }
184
185         return record;
186     }
187
188     private void populatePomEntries( Model pom, StandardArtifactIndexRecord record )
189     {
190         record.setPackaging( pom.getPackaging() );
191         record.setProjectName( pom.getName() );
192         record.setProjectDescription( pom.getDescription() );
193         record.setInceptionYear( pom.getInceptionYear() );
194
195 /* TODO: fields for later
196                 indexPlugins( doc, FLD_PLUGINS_BUILD, pom.getBuild().getPlugins().iterator() );
197                 indexReportPlugins( doc, FLD_PLUGINS_REPORT, pom.getReporting().getPlugins().iterator() );
198                 record.setDependencies( dependencies );
199                 record.setLicenses( licenses );
200 */
201     }
202
203     private Model readPom( Artifact artifact, ArtifactRepository repository )
204         throws RepositoryIndexException, ProjectBuildingException
205     {
206         // TODO: this can create a -SNAPSHOT.pom when it didn't exist and a timestamped one did. This is harmless, but should be avoided
207         // TODO: will this pollute with local repo metadata?
208         MavenProject project = projectBuilder.buildFromRepository( artifact, Collections.EMPTY_LIST, repository );
209         return project.getModel();
210     }
211
212     private void populateArchiveEntries( List files, StandardArtifactIndexRecord record, File artifactFile )
213         throws RepositoryIndexException
214     {
215         List classes = new ArrayList();
216         List fileList = new ArrayList();
217
218         for ( Iterator i = files.iterator(); i.hasNext(); )
219         {
220             String name = (String) i.next();
221
222             // ignore directories
223             if ( !name.endsWith( "/" ) )
224             {
225                 fileList.add( name );
226
227                 if ( isClass( name ) )
228                 {
229                     classes.add( name.substring( 0, name.length() - 6 ).replace( '/', '.' ) );
230                 }
231                 else if ( PLUGIN_METADATA_NAME.equals( name ) )
232                 {
233                     populatePluginEntries( readXmlMetadataFileInJar( artifactFile, PLUGIN_METADATA_NAME ), record );
234                 }
235                 else if ( ARCHETYPE_METADATA_NAME.equals( name ) || ARCHETYPE_METADATA_NAME_OLD.equals( name ) )
236                 {
237                     populateArchetypeEntries( record );
238                 }
239             }
240         }
241
242         if ( !classes.isEmpty() )
243         {
244             record.setClasses( classes );
245         }
246         if ( !fileList.isEmpty() )
247         {
248             record.setFiles( fileList );
249         }
250     }
251
252     private void populateArchetypeEntries( StandardArtifactIndexRecord record )
253     {
254         // Typically discovered as a JAR
255         record.setType( "maven-archetype" );
256     }
257
258     private Xpp3Dom readXmlMetadataFileInJar( File file, String name )
259         throws RepositoryIndexException
260     {
261         // TODO: would be more efficient with original ZipEntry still around
262
263         Xpp3Dom xpp3Dom;
264         ZipFile zipFile = null;
265         try
266         {
267             zipFile = new ZipFile( file );
268             ZipEntry entry = zipFile.getEntry( name );
269             xpp3Dom = Xpp3DomBuilder.build( new InputStreamReader( zipFile.getInputStream( entry ) ) );
270         }
271         catch ( ZipException e )
272         {
273             throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
274         }
275         catch ( IOException e )
276         {
277             throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
278         }
279         catch ( XmlPullParserException e )
280         {
281             throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
282         }
283         finally
284         {
285             closeQuietly( zipFile );
286         }
287         return xpp3Dom;
288     }
289
290     public void populatePluginEntries( Xpp3Dom metadata, StandardArtifactIndexRecord record )
291     {
292         // Typically discovered as a JAR
293         record.setType( "maven-plugin" );
294
295         Xpp3Dom prefix = metadata.getChild( "goalPrefix" );
296
297         if ( prefix != null )
298         {
299             record.setPluginPrefix( prefix.getValue() );
300         }
301     }
302 }