1 package org.apache.archiva.metadata.repository.storage.maven2;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
23 import java.io.FilenameFilter;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.List;
30 import org.apache.archiva.metadata.model.ProjectMetadata;
31 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
32 import org.apache.archiva.metadata.model.ProjectVersionReference;
33 import org.apache.archiva.metadata.repository.MetadataResolverException;
34 import org.apache.archiva.metadata.repository.filter.AllFilter;
35 import org.apache.archiva.metadata.repository.filter.Filter;
36 import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
37 import org.apache.archiva.metadata.repository.storage.StorageMetadataResolver;
38 import org.apache.maven.archiva.common.utils.VersionUtil;
39 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
40 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
41 import org.apache.maven.archiva.xml.XMLException;
42 import org.apache.maven.model.CiManagement;
43 import org.apache.maven.model.Dependency;
44 import org.apache.maven.model.IssueManagement;
45 import org.apache.maven.model.License;
46 import org.apache.maven.model.MailingList;
47 import org.apache.maven.model.Model;
48 import org.apache.maven.model.Organization;
49 import org.apache.maven.model.Scm;
50 import org.apache.maven.model.building.DefaultModelBuildingRequest;
51 import org.apache.maven.model.building.ModelBuilder;
52 import org.apache.maven.model.building.ModelBuildingException;
53 import org.apache.maven.model.building.ModelBuildingRequest;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
58 * @plexus.component role="org.apache.archiva.metadata.repository.storage.StorageMetadataResolver" role-hint="maven2"
60 public class Maven2RepositoryMetadataResolver
61 implements StorageMetadataResolver
66 private ModelBuilder builder;
71 private ArchivaConfiguration archivaConfiguration;
74 * @plexus.requirement role-hint="maven2"
76 private RepositoryPathTranslator pathTranslator;
78 private final static Logger log = LoggerFactory.getLogger( Maven2RepositoryMetadataResolver.class );
80 private static final String METADATA_FILENAME = "maven-metadata.xml";
82 private static final Filter<String> ALL = new AllFilter<String>();
84 public ProjectMetadata getProject( String repoId, String namespace, String projectId )
86 // TODO: could natively implement the "shared model" concept from the browse action to avoid needing it there?
90 public ProjectVersionMetadata getProjectVersion( String repoId, String namespace, String projectId,
91 String projectVersion )
92 throws MetadataResolverException
94 ManagedRepositoryConfiguration repositoryConfiguration =
95 archivaConfiguration.getConfiguration().findManagedRepositoryById( repoId );
97 String artifactVersion = projectVersion;
99 File basedir = new File( repositoryConfiguration.getLocation() );
100 if ( VersionUtil.isSnapshot( projectVersion ) )
103 pathTranslator.toFile( basedir, namespace, projectId, projectVersion, METADATA_FILENAME );
106 MavenRepositoryMetadata metadata = MavenRepositoryMetadataReader.read( metadataFile );
108 // re-adjust to timestamp if present, otherwise retain the original -SNAPSHOT filename
109 MavenRepositoryMetadata.Snapshot snapshotVersion = metadata.getSnapshotVersion();
110 if ( snapshotVersion != null )
113 artifactVersion.substring( 0, artifactVersion.length() - 8 ); // remove SNAPSHOT from end
115 artifactVersion + snapshotVersion.getTimestamp() + "-" + snapshotVersion.getBuildNumber();
118 catch ( XMLException e )
120 // unable to parse metadata - log it, and continue with the version as the original SNAPSHOT version
121 log.warn( "Invalid metadata: " + metadataFile + " - " + e.getMessage() );
125 File file = pathTranslator.toFile( basedir, namespace, projectId, projectVersion,
126 projectId + "-" + artifactVersion + ".pom" );
128 if ( !file.exists() )
130 // metadata could not be resolved
134 ModelBuildingRequest req = new DefaultModelBuildingRequest();
135 req.setProcessPlugins( false );
136 req.setPomFile( file );
137 req.setModelResolver( new RepositoryModelResolver( basedir, pathTranslator ) );
138 req.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
143 model = builder.build( req ).getEffectiveModel();
145 catch ( ModelBuildingException e )
147 throw new MetadataResolverException( "Unable to build Maven POM to derive metadata from: " + e.getMessage(),
151 ProjectVersionMetadata metadata = new ProjectVersionMetadata();
152 metadata.setCiManagement( convertCiManagement( model.getCiManagement() ) );
153 metadata.setDescription( model.getDescription() );
154 metadata.setId( projectVersion );
155 metadata.setIssueManagement( convertIssueManagement( model.getIssueManagement() ) );
156 metadata.setLicenses( convertLicenses( model.getLicenses() ) );
157 metadata.setMailingLists( convertMailingLists( model.getMailingLists() ) );
158 metadata.setDependencies( convertDependencies( model.getDependencies() ) );
159 metadata.setName( model.getName() );
160 metadata.setOrganization( convertOrganization( model.getOrganization() ) );
161 metadata.setScm( convertScm( model.getScm() ) );
162 metadata.setUrl( model.getUrl() );
164 MavenProjectFacet facet = new MavenProjectFacet();
165 facet.setGroupId( model.getGroupId() != null ? model.getGroupId() : model.getParent().getGroupId() );
166 facet.setArtifactId( model.getArtifactId() );
167 facet.setPackaging( model.getPackaging() );
168 if ( model.getParent() != null )
170 MavenProjectParent parent = new MavenProjectParent();
171 parent.setGroupId( model.getParent().getGroupId() );
172 parent.setArtifactId( model.getParent().getArtifactId() );
173 parent.setVersion( model.getParent().getVersion() );
174 facet.setParent( parent );
176 metadata.addFacet( facet );
181 private List<org.apache.archiva.metadata.model.Dependency> convertDependencies( List<Dependency> dependencies )
183 List<org.apache.archiva.metadata.model.Dependency> l =
184 new ArrayList<org.apache.archiva.metadata.model.Dependency>();
185 for ( Dependency dependency : dependencies )
187 org.apache.archiva.metadata.model.Dependency newDependency =
188 new org.apache.archiva.metadata.model.Dependency();
189 newDependency.setArtifactId( dependency.getArtifactId() );
190 newDependency.setClassifier( dependency.getClassifier() );
191 newDependency.setGroupId( dependency.getGroupId() );
192 newDependency.setOptional( dependency.isOptional() );
193 newDependency.setScope( dependency.getScope() );
194 newDependency.setSystemPath( dependency.getSystemPath() );
195 newDependency.setType( dependency.getType() );
196 newDependency.setVersion( dependency.getVersion() );
197 l.add( newDependency );
202 private org.apache.archiva.metadata.model.Scm convertScm( Scm scm )
204 org.apache.archiva.metadata.model.Scm newScm = null;
207 newScm = new org.apache.archiva.metadata.model.Scm();
208 newScm.setConnection( scm.getConnection() );
209 newScm.setDeveloperConnection( scm.getDeveloperConnection() );
210 newScm.setUrl( scm.getUrl() );
215 private org.apache.archiva.metadata.model.Organization convertOrganization( Organization organization )
217 org.apache.archiva.metadata.model.Organization org = null;
218 if ( organization != null )
220 org = new org.apache.archiva.metadata.model.Organization();
221 org.setName( organization.getName() );
222 org.setUrl( organization.getUrl() );
227 private List<org.apache.archiva.metadata.model.License> convertLicenses( List<License> licenses )
229 List<org.apache.archiva.metadata.model.License> l = new ArrayList<org.apache.archiva.metadata.model.License>();
230 for ( License license : licenses )
232 org.apache.archiva.metadata.model.License newLicense = new org.apache.archiva.metadata.model.License();
233 newLicense.setName( license.getName() );
234 newLicense.setUrl( license.getUrl() );
240 private List<org.apache.archiva.metadata.model.MailingList> convertMailingLists( List<MailingList> mailingLists )
242 List<org.apache.archiva.metadata.model.MailingList> l =
243 new ArrayList<org.apache.archiva.metadata.model.MailingList>();
244 for ( MailingList mailingList : mailingLists )
246 org.apache.archiva.metadata.model.MailingList newMailingList =
247 new org.apache.archiva.metadata.model.MailingList();
248 newMailingList.setName( mailingList.getName() );
249 newMailingList.setMainArchiveUrl( mailingList.getArchive() );
250 newMailingList.setPostAddress( mailingList.getPost() );
251 newMailingList.setSubscribeAddress( mailingList.getSubscribe() );
252 newMailingList.setUnsubscribeAddress( mailingList.getUnsubscribe() );
253 newMailingList.setOtherArchives( mailingList.getOtherArchives() );
254 l.add( newMailingList );
259 private org.apache.archiva.metadata.model.IssueManagement convertIssueManagement( IssueManagement issueManagement )
261 org.apache.archiva.metadata.model.IssueManagement im = null;
262 if ( issueManagement != null )
264 im = new org.apache.archiva.metadata.model.IssueManagement();
265 im.setSystem( issueManagement.getSystem() );
266 im.setUrl( issueManagement.getUrl() );
271 private org.apache.archiva.metadata.model.CiManagement convertCiManagement( CiManagement ciManagement )
273 org.apache.archiva.metadata.model.CiManagement ci = null;
274 if ( ciManagement != null )
276 ci = new org.apache.archiva.metadata.model.CiManagement();
277 ci.setSystem( ciManagement.getSystem() );
278 ci.setUrl( ciManagement.getUrl() );
283 public Collection<String> getArtifactVersions( String repoId, String namespace, String projectId,
284 String projectVersion )
286 // TODO: useful, but not implemented yet, not called from DefaultMetadataResolver
287 throw new UnsupportedOperationException();
290 public Collection<ProjectVersionReference> getProjectReferences( String repoId, String namespace, String projectId,
291 String projectVersion )
293 // Can't be determined on a Maven 2 repository
294 throw new UnsupportedOperationException();
297 public Collection<String> getRootNamespaces( String repoId )
299 return getRootNamespaces( repoId, ALL );
302 public Collection<String> getRootNamespaces( String repoId, Filter<String> filter )
304 File dir = getRepositoryBasedir( repoId );
306 String[] files = dir.list( new DirectoryFilter( filter ) );
307 return files != null ? Arrays.asList( files ) : Collections.<String>emptyList();
310 private File getRepositoryBasedir( String repoId )
312 ManagedRepositoryConfiguration repositoryConfiguration =
313 archivaConfiguration.getConfiguration().findManagedRepositoryById( repoId );
315 return new File( repositoryConfiguration.getLocation() );
318 public Collection<String> getNamespaces( String repoId, String namespace )
320 return getNamespaces( repoId, namespace, ALL );
323 public Collection<String> getNamespaces( String repoId, String namespace, Filter<String> filter )
325 File dir = pathTranslator.toFile( getRepositoryBasedir( repoId ), namespace );
327 // scan all the directories which are potential namespaces. Any directories known to be projects are excluded
328 Collection<String> namespaces = new ArrayList<String>();
329 File[] files = dir.listFiles( new DirectoryFilter( filter ) );
332 for ( File file : files )
334 if ( !isProject( file, filter ) )
336 namespaces.add( file.getName() );
343 public Collection<String> getProjects( String repoId, String namespace )
345 return getProjects( repoId, namespace, ALL );
348 public Collection<String> getProjects( String repoId, String namespace, Filter<String> filter )
350 File dir = pathTranslator.toFile( getRepositoryBasedir( repoId ), namespace );
352 // scan all directories in the namespace, and only include those that are known to be projects
353 Collection<String> projects = new ArrayList<String>();
354 File[] files = dir.listFiles( new DirectoryFilter( filter ) );
357 for ( File file : files )
359 if ( isProject( file, filter ) )
361 projects.add( file.getName() );
368 public Collection<String> getProjectVersions( String repoId, String namespace, String projectId )
370 return getProjectVersions( repoId, namespace, projectId, ALL );
373 public Collection<String> getProjectVersions( String repoId, String namespace, String projectId,
374 Filter<String> filter )
376 File dir = pathTranslator.toFile( getRepositoryBasedir( repoId ), namespace, projectId );
378 // all directories in a project directory can be considered a version
379 String[] files = dir.list( new DirectoryFilter( filter ) );
380 return files != null ? Arrays.asList( files ) : Collections.<String>emptyList();
383 private boolean isProject( File dir, Filter<String> filter )
385 // scan directories for a valid project version subdirectory, meaning this must be a project directory
386 File[] files = dir.listFiles( new DirectoryFilter( filter ) );
389 for ( File file : files )
391 if ( isProjectVersion( file ) )
398 // if a metadata file is present, check if this is the "artifactId" directory, marking it as a project
399 MavenRepositoryMetadata metadata = readMetadata( dir );
400 if ( metadata != null && dir.getName().equals( metadata.getArtifactId() ) )
408 private boolean isProjectVersion( File dir )
410 final String artifactId = dir.getParentFile().getName();
411 final String projectVersion = dir.getName();
413 // check if there is a POM artifact file to ensure it is a version directory
415 if ( VersionUtil.isSnapshot( projectVersion ) )
417 files = dir.listFiles( new FilenameFilter()
419 public boolean accept( File dir, String name )
421 if ( name.startsWith( artifactId + "-" ) && name.endsWith( ".pom" ) )
423 String v = name.substring( artifactId.length() + 1, name.length() - 4 );
424 v = VersionUtil.getBaseVersion( v );
425 if ( v.equals( projectVersion ) )
436 final String pomFile = artifactId + "-" + projectVersion + ".pom";
437 files = dir.listFiles( new FilenameFilter()
439 public boolean accept( File dir, String name )
441 return pomFile.equals( name );
445 if ( files != null && files.length > 0 )
450 // if a metadata file is present, check if this is the "version" directory, marking it as a project version
451 MavenRepositoryMetadata metadata = readMetadata( dir );
452 if ( metadata != null && projectVersion.equals( metadata.getVersion() ) )
460 private MavenRepositoryMetadata readMetadata( File directory )
462 MavenRepositoryMetadata metadata = null;
463 File metadataFile = new File( directory, METADATA_FILENAME );
464 if ( metadataFile.exists() )
468 metadata = MavenRepositoryMetadataReader.read( metadataFile );
470 catch ( XMLException e )
472 // ignore missing or invalid metadata
478 private static class DirectoryFilter
479 implements FilenameFilter
481 private final Filter<String> filter;
483 public DirectoryFilter( Filter<String> filter )
485 this.filter = filter;
488 public boolean accept( File dir, String name )
490 if ( !filter.accept( name ) )
494 else if ( name.startsWith( "." ) )
498 else if ( !new File( dir, name ).isDirectory() )