]> source.dussan.org Git - archiva.git/blob
965adfe1c3ad5303502ea932500665f1714fb397
[archiva.git] /
1 package org.apache.maven.archiva.indexer.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.indexer.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.Dependency;
25 import org.apache.maven.model.Developer;
26 import org.apache.maven.model.Model;
27 import org.apache.maven.project.MavenProject;
28 import org.apache.maven.project.MavenProjectBuilder;
29 import org.apache.maven.project.ProjectBuildingException;
30 import org.codehaus.plexus.util.xml.Xpp3Dom;
31 import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
32 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
33
34 import java.io.File;
35 import java.io.IOException;
36 import java.io.InputStreamReader;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.Collections;
40 import java.util.HashSet;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Set;
44 import java.util.zip.ZipEntry;
45 import java.util.zip.ZipException;
46 import java.util.zip.ZipFile;
47
48 /**
49  * An index record type for the standard index.
50  *
51  * @author Edwin Punzalan
52  * @author Brett Porter
53  * @plexus.component role="org.apache.maven.archiva.indexer.record.RepositoryIndexRecordFactory" role-hint="standard"
54  */
55 public class StandardArtifactIndexRecordFactory
56     extends AbstractArtifactIndexRecordFactory
57 {
58     /**
59      * A list of artifact types to treat as a zip archive.
60      *
61      * @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.
62      */
63     private static final Set ARCHIVE_TYPES =
64         new HashSet( Arrays.asList( new String[]{"jar", "ejb", "par", "sar", "war", "ear", "rar"} ) );
65
66     /**
67      * @plexus.requirement
68      */
69     private ArtifactFactory artifactFactory;
70
71     /**
72      * @plexus.requirement
73      */
74     private MavenProjectBuilder projectBuilder;
75
76     /**
77      * @plexus.requirement role-hint="sha1"
78      */
79     protected Digester sha1Digester;
80
81     /**
82      * @plexus.requirement role-hint="md5"
83      */
84     protected Digester md5Digester;
85
86     private static final String SITE_TEMPLATE_NAME = "META-INF/maven/site.vm";
87
88     private static final String SITE_CSS_NAME = "css/maven-theme.css";
89
90     private static final String PLUGIN_METADATA_NAME = "META-INF/maven/plugin.xml";
91
92     private static final String ARCHETYPE_METADATA_NAME = "META-INF/maven/archetype.xml";
93
94     // some current/old archetypes have the archetype.xml at different location.
95     private static final String ARCHETYPE_METADATA_NAME_OLD = "META-INF/archetype.xml";
96
97     public RepositoryIndexRecord createRecord( Artifact artifact )
98         throws RepositoryIndexException
99     {
100         StandardArtifactIndexRecord record = null;
101
102         File file = artifact.getFile();
103
104         // TODO: is this condition really a possibility?
105         if ( file != null && file.exists() )
106         {
107             String md5 = readChecksum( file, md5Digester );
108             String sha1 = readChecksum( file, sha1Digester );
109
110             List files = null;
111             boolean archive = ARCHIVE_TYPES.contains( artifact.getType() );
112             try
113             {
114                 if ( archive )
115                 {
116                     files = readFilesInArchive( file );
117                 }
118             }
119             catch ( IOException e )
120             {
121                 getLogger().error( "Error reading artifact file, omitting from index: " + e.getMessage() );
122             }
123
124             // If it's an archive with no files, don't create a record
125             if ( !archive || files != null )
126             {
127                 record = new StandardArtifactIndexRecord();
128
129                 record.setGroupId( artifact.getGroupId() );
130                 record.setArtifactId( artifact.getArtifactId() );
131                 record.setBaseVersion( artifact.getBaseVersion() );
132                 record.setVersion( artifact.getVersion() );
133                 record.setClassifier( artifact.getClassifier() );
134                 record.setType( artifact.getType() );
135                 record.setMd5Checksum( md5 );
136                 record.setSha1Checksum( sha1 );
137                 record.setFilename( artifact.getRepository().pathOf( artifact ) );
138                 record.setLastModified( file.lastModified() );
139                 record.setSize( file.length() );
140                 record.setRepository( artifact.getRepository().getId() );
141
142                 if ( files != null )
143                 {
144                     populateArchiveEntries( files, record, artifact.getFile() );
145                 }
146
147                 if ( !"pom".equals( artifact.getType() ) )
148                 {
149                     Artifact pomArtifact = artifactFactory.createProjectArtifact( artifact.getGroupId(),
150                                                                                   artifact.getArtifactId(),
151                                                                                   artifact.getVersion() );
152                     pomArtifact.isSnapshot(); // gross hack around bug in maven-artifact
153                     File pomFile = new File( artifact.getRepository().getBasedir(),
154                                              artifact.getRepository().pathOf( pomArtifact ) );
155                     if ( pomFile.exists() )
156                     {
157                         try
158                         {
159                             populatePomEntries( readPom( pomArtifact, artifact.getRepository() ), record );
160                         }
161                         catch ( ProjectBuildingException e )
162                         {
163                             getLogger().error( "Error reading POM file, not populating in index: " + e.getMessage() );
164                         }
165                     }
166                 }
167                 else
168                 {
169                     Model model;
170                     try
171                     {
172                         model = readPom( artifact, artifact.getRepository() );
173
174                         if ( !"pom".equals( model.getPackaging() ) )
175                         {
176                             // Don't return a record for a POM that is does not belong on its own
177                             record = null;
178                         }
179                         else
180                         {
181                             populatePomEntries( model, record );
182                         }
183                     }
184                     catch ( ProjectBuildingException e )
185                     {
186                         getLogger().error( "Error reading POM file, not populating in index: " + e.getMessage() );
187                     }
188                 }
189             }
190         }
191
192         return record;
193     }
194
195     private void populatePomEntries( Model pom, StandardArtifactIndexRecord record )
196     {
197         record.setPackaging( pom.getPackaging() );
198         record.setProjectName( pom.getName() );
199         record.setProjectDescription( pom.getDescription() );
200         record.setInceptionYear( pom.getInceptionYear() );
201
202         List dependencies = populateDependencies( pom.getDependencies() );
203         if ( !dependencies.isEmpty() )
204         {
205             record.setDependencies( dependencies );
206         }
207         List developers = populateDevelopers( pom.getDevelopers() );
208         if ( !developers.isEmpty() )
209         {
210             record.setDevelopers( developers );
211         }
212
213 /* TODO: fields for later
214                 indexPlugins( doc, FLD_PLUGINS_BUILD, pom.getBuild().getPlugins().iterator() );
215                 indexReportPlugins( doc, FLD_PLUGINS_REPORT, pom.getReporting().getPlugins().iterator() );
216                 record.setLicenses( licenses );
217 */
218     }
219
220     private List populateDependencies( List dependencies )
221     {
222         List convertedDependencies = new ArrayList();
223
224         for ( Iterator i = dependencies.iterator(); i.hasNext(); )
225         {
226             Dependency dependency = (Dependency) i.next();
227
228             convertedDependencies.add(
229                 dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion() );
230         }
231
232         return convertedDependencies;
233     }
234
235     private List populateDevelopers( List developers )
236     {
237         List convertedDevelopers = new ArrayList();
238
239         for ( Iterator i = developers.iterator(); i.hasNext(); )
240         {
241             Developer developer = (Developer) i.next();
242
243             convertedDevelopers.add( developer.getId() + ":" + developer.getName() + ":" + developer.getEmail() );
244         }
245
246         return convertedDevelopers;
247     }
248
249     private Model readPom( Artifact artifact, ArtifactRepository repository )
250         throws RepositoryIndexException, ProjectBuildingException
251     {
252         // TODO: this can create a -SNAPSHOT.pom when it didn't exist and a timestamped one did. This is harmless, but should be avoided
253         // TODO: will this pollute with local repo metadata?
254         MavenProject project = projectBuilder.buildFromRepository( artifact, Collections.EMPTY_LIST, repository );
255         return project.getModel();
256     }
257
258     private void populateArchiveEntries( List files, StandardArtifactIndexRecord record, File artifactFile )
259         throws RepositoryIndexException
260     {
261         List classes = new ArrayList();
262         List fileList = new ArrayList();
263
264         for ( Iterator i = files.iterator(); i.hasNext(); )
265         {
266             String name = (String) i.next();
267
268             // ignore directories
269             if ( !name.endsWith( "/" ) )
270             {
271                 fileList.add( name );
272
273                 if ( isClass( name ) )
274                 {
275                     classes.add( name.substring( 0, name.length() - 6 ).replace( '/', '.' ) );
276                 }
277                 else if ( PLUGIN_METADATA_NAME.equals( name ) )
278                 {
279                     populatePluginEntries( readXmlMetadataFileInJar( artifactFile, PLUGIN_METADATA_NAME ), record );
280                 }
281                 else if ( ARCHETYPE_METADATA_NAME.equals( name ) || ARCHETYPE_METADATA_NAME_OLD.equals( name ) )
282                 {
283                     populateArchetypeEntries( record );
284                 }
285                 else if ( SITE_TEMPLATE_NAME.equals( name ) || SITE_CSS_NAME.equals( name ) )
286                 {
287                     populateSkinEntries( record );
288                 }
289             }
290         }
291
292         if ( !classes.isEmpty() )
293         {
294             record.setClasses( classes );
295         }
296         if ( !fileList.isEmpty() )
297         {
298             record.setFiles( fileList );
299         }
300     }
301
302     private void populateArchetypeEntries( StandardArtifactIndexRecord record )
303     {
304         // Typically discovered as a JAR
305         record.setType( "maven-archetype" );
306     }
307
308     private void populateSkinEntries( StandardArtifactIndexRecord record )
309     {
310         // Typically discovered as a JAR
311         record.setType( "maven-skin" );
312     }
313
314     private Xpp3Dom readXmlMetadataFileInJar( File file, String name )
315         throws RepositoryIndexException
316     {
317         // TODO: would be more efficient with original ZipEntry still around
318
319         Xpp3Dom xpp3Dom;
320         ZipFile zipFile = null;
321         try
322         {
323             zipFile = new ZipFile( file );
324             ZipEntry entry = zipFile.getEntry( name );
325             xpp3Dom = Xpp3DomBuilder.build( new InputStreamReader( zipFile.getInputStream( entry ) ) );
326         }
327         catch ( ZipException e )
328         {
329             throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
330         }
331         catch ( IOException e )
332         {
333             throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
334         }
335         catch ( XmlPullParserException e )
336         {
337             throw new RepositoryIndexException( "Unable to read plugin metadata: " + e.getMessage(), e );
338         }
339         finally
340         {
341             closeQuietly( zipFile );
342         }
343         return xpp3Dom;
344     }
345
346     public void populatePluginEntries( Xpp3Dom metadata, StandardArtifactIndexRecord record )
347     {
348         // Typically discovered as a JAR
349         record.setType( "maven-plugin" );
350
351         Xpp3Dom prefix = metadata.getChild( "goalPrefix" );
352
353         if ( prefix != null )
354         {
355             record.setPluginPrefix( prefix.getValue() );
356         }
357     }
358 }