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