1 package org.apache.archiva.metadata.repository.file;
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
22 import org.apache.archiva.metadata.model.ArtifactMetadata;
23 import org.apache.archiva.metadata.model.CiManagement;
24 import org.apache.archiva.metadata.model.Dependency;
25 import org.apache.archiva.metadata.model.IssueManagement;
26 import org.apache.archiva.metadata.model.License;
27 import org.apache.archiva.metadata.model.MailingList;
28 import org.apache.archiva.metadata.model.MetadataFacet;
29 import org.apache.archiva.metadata.model.MetadataFacetFactory;
30 import org.apache.archiva.metadata.model.Organization;
31 import org.apache.archiva.metadata.model.ProjectMetadata;
32 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
33 import org.apache.archiva.metadata.model.ProjectVersionReference;
34 import org.apache.archiva.metadata.model.Scm;
35 import org.apache.archiva.metadata.repository.MetadataRepository;
36 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
37 import org.apache.commons.io.FileUtils;
38 import org.apache.commons.io.IOUtils;
39 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 import java.io.FileInputStream;
45 import java.io.FileNotFoundException;
46 import java.io.FileOutputStream;
47 import java.io.IOException;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.Comparator;
53 import java.util.Date;
54 import java.util.HashMap;
55 import java.util.HashSet;
56 import java.util.LinkedHashSet;
57 import java.util.List;
59 import java.util.Properties;
61 import java.util.StringTokenizer;
63 public class FileMetadataRepository
64 implements MetadataRepository
66 private final Map<String, MetadataFacetFactory> metadataFacetFactories;
68 private final ArchivaConfiguration configuration;
70 private static final Logger log = LoggerFactory.getLogger( FileMetadataRepository.class );
72 private static final String PROJECT_METADATA_KEY = "project-metadata";
74 private static final String PROJECT_VERSION_METADATA_KEY = "version-metadata";
76 private static final String NAMESPACE_METADATA_KEY = "namespace-metadata";
78 private static final String METADATA_KEY = "metadata";
80 public FileMetadataRepository( Map<String, MetadataFacetFactory> metadataFacetFactories,
81 ArchivaConfiguration configuration )
83 this.metadataFacetFactories = metadataFacetFactories;
84 this.configuration = configuration;
87 private File getBaseDirectory( String repoId )
89 // TODO: should be configurable, like the index
90 String basedir = configuration.getConfiguration().getManagedRepositoriesAsMap().get( repoId ).getLocation();
91 File dir = new File( basedir, ".archiva" );
95 private File getDirectory( String repoId )
97 return new File( getBaseDirectory( repoId ), "content" );
100 public void updateProject( String repoId, ProjectMetadata project )
102 updateProject( repoId, project.getNamespace(), project.getId() );
105 private void updateProject( String repoId, String namespace, String id )
107 // TODO: this is a more braindead implementation than we would normally expect, for prototyping purposes
108 updateNamespace( repoId, namespace );
112 File namespaceDirectory = new File( getDirectory( repoId ), namespace );
113 Properties properties = new Properties();
114 properties.setProperty( "namespace", namespace );
115 properties.setProperty( "id", id );
116 writeProperties( properties, new File( namespaceDirectory, id ), PROJECT_METADATA_KEY );
118 catch ( IOException e )
125 public void updateProjectVersion( String repoId, String namespace, String projectId,
126 ProjectVersionMetadata versionMetadata )
128 updateProject( repoId, namespace, projectId );
130 File directory = new File( getDirectory( repoId ),
131 namespace + "/" + projectId + "/" + versionMetadata.getId() );
133 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
134 // remove properties that are not references or artifacts
135 for ( Object key : new ArrayList<Object>( properties.keySet() ) )
137 String name = (String) key;
138 if ( !name.contains( ":" ) && !name.equals( "facetIds" ) )
140 properties.remove( name );
143 // clear the facet contents so old properties are no longer written
144 clearMetadataFacetProperties( versionMetadata.getFacetList(), properties, "" );
146 properties.setProperty( "id", versionMetadata.getId() );
147 setProperty( properties, "name", versionMetadata.getName() );
148 setProperty( properties, "description", versionMetadata.getDescription() );
149 setProperty( properties, "url", versionMetadata.getUrl() );
150 setProperty( properties, "incomplete", String.valueOf( versionMetadata.isIncomplete() ) );
151 if ( versionMetadata.getScm() != null )
153 setProperty( properties, "scm.connection", versionMetadata.getScm().getConnection() );
154 setProperty( properties, "scm.developerConnection", versionMetadata.getScm().getDeveloperConnection() );
155 setProperty( properties, "scm.url", versionMetadata.getScm().getUrl() );
157 if ( versionMetadata.getCiManagement() != null )
159 setProperty( properties, "ci.system", versionMetadata.getCiManagement().getSystem() );
160 setProperty( properties, "ci.url", versionMetadata.getCiManagement().getUrl() );
162 if ( versionMetadata.getIssueManagement() != null )
164 setProperty( properties, "issue.system", versionMetadata.getIssueManagement().getSystem() );
165 setProperty( properties, "issue.url", versionMetadata.getIssueManagement().getUrl() );
167 if ( versionMetadata.getOrganization() != null )
169 setProperty( properties, "org.name", versionMetadata.getOrganization().getName() );
170 setProperty( properties, "org.url", versionMetadata.getOrganization().getUrl() );
173 for ( License license : versionMetadata.getLicenses() )
175 setProperty( properties, "license." + i + ".name", license.getName() );
176 setProperty( properties, "license." + i + ".url", license.getUrl() );
180 for ( MailingList mailingList : versionMetadata.getMailingLists() )
182 setProperty( properties, "mailingList." + i + ".archive", mailingList.getMainArchiveUrl() );
183 setProperty( properties, "mailingList." + i + ".name", mailingList.getName() );
184 setProperty( properties, "mailingList." + i + ".post", mailingList.getPostAddress() );
185 setProperty( properties, "mailingList." + i + ".unsubscribe", mailingList.getUnsubscribeAddress() );
186 setProperty( properties, "mailingList." + i + ".subscribe", mailingList.getSubscribeAddress() );
187 setProperty( properties, "mailingList." + i + ".otherArchives", join( mailingList.getOtherArchives() ) );
191 for ( Dependency dependency : versionMetadata.getDependencies() )
193 setProperty( properties, "dependency." + i + ".classifier", dependency.getClassifier() );
194 setProperty( properties, "dependency." + i + ".scope", dependency.getScope() );
195 setProperty( properties, "dependency." + i + ".systemPath", dependency.getSystemPath() );
196 setProperty( properties, "dependency." + i + ".artifactId", dependency.getArtifactId() );
197 setProperty( properties, "dependency." + i + ".groupId", dependency.getGroupId() );
198 setProperty( properties, "dependency." + i + ".version", dependency.getVersion() );
199 setProperty( properties, "dependency." + i + ".type", dependency.getType() );
200 setProperty( properties, "dependency." + i + ".optional", String.valueOf( dependency.isOptional() ) );
203 Set<String> facetIds = new LinkedHashSet<String>( versionMetadata.getFacetIds() );
204 facetIds.addAll( Arrays.asList( properties.getProperty( "facetIds", "" ).split( "," ) ) );
205 properties.setProperty( "facetIds", join( facetIds ) );
207 updateProjectVersionFacets( versionMetadata, properties );
211 writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
213 catch ( IOException e )
216 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
220 private void updateProjectVersionFacets( ProjectVersionMetadata versionMetadata, Properties properties )
222 for ( MetadataFacet facet : versionMetadata.getFacetList() )
224 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
226 properties.setProperty( facet.getFacetId() + ":" + entry.getKey(), entry.getValue() );
231 private static void clearMetadataFacetProperties( Collection<MetadataFacet> facetList, Properties properties,
234 List<Object> propsToRemove = new ArrayList<Object>();
235 for ( MetadataFacet facet : facetList )
237 for ( Object key : properties.keySet() )
239 String keyString = (String) key;
240 if ( keyString.startsWith( prefix + facet.getFacetId() + ":" ) )
242 propsToRemove.add( key );
247 for ( Object key : propsToRemove )
249 properties.remove( key );
253 public void updateProjectReference( String repoId, String namespace, String projectId, String projectVersion,
254 ProjectVersionReference reference )
256 File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );
258 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
259 int i = Integer.parseInt( properties.getProperty( "ref:lastReferenceNum", "-1" ) ) + 1;
260 setProperty( properties, "ref:lastReferenceNum", Integer.toString( i ) );
261 setProperty( properties, "ref:reference." + i + ".namespace", reference.getNamespace() );
262 setProperty( properties, "ref:reference." + i + ".projectId", reference.getProjectId() );
263 setProperty( properties, "ref:reference." + i + ".projectVersion", reference.getProjectVersion() );
264 setProperty( properties, "ref:reference." + i + ".referenceType", reference.getReferenceType().toString() );
268 writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
270 catch ( IOException e )
273 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
277 public void updateNamespace( String repoId, String namespace )
281 File namespaceDirectory = new File( getDirectory( repoId ), namespace );
282 Properties properties = new Properties();
283 properties.setProperty( "namespace", namespace );
284 writeProperties( properties, namespaceDirectory, NAMESPACE_METADATA_KEY );
287 catch ( IOException e )
294 public List<String> getMetadataFacets( String repoId, String facetId )
296 File directory = getMetadataDirectory( repoId, facetId );
297 List<String> facets = new ArrayList<String>();
298 recurse( facets, "", directory );
302 private void recurse( List<String> facets, String prefix, File directory )
304 File[] list = directory.listFiles();
307 for ( File dir : list )
309 if ( dir.isDirectory() )
311 recurse( facets, prefix + "/" + dir.getName(), dir );
313 else if ( dir.getName().equals( METADATA_KEY + ".properties" ) )
315 facets.add( prefix.substring( 1 ) );
321 public MetadataFacet getMetadataFacet( String repositoryId, String facetId, String name )
323 Properties properties;
326 properties = readProperties( new File( getMetadataDirectory( repositoryId, facetId ), name ),
329 catch ( FileNotFoundException e )
333 catch ( IOException e )
336 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
339 MetadataFacet metadataFacet = null;
340 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId );
341 if ( metadataFacetFactory != null )
343 metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name );
344 Map<String, String> map = new HashMap<String, String>();
345 for ( Object key : new ArrayList( properties.keySet() ) )
347 String property = (String) key;
348 map.put( property, properties.getProperty( property ) );
350 metadataFacet.fromProperties( map );
352 return metadataFacet;
355 public void addMetadataFacet( String repositoryId, MetadataFacet metadataFacet )
357 Properties properties = new Properties();
358 properties.putAll( metadataFacet.toProperties() );
362 File directory = new File( getMetadataDirectory( repositoryId, metadataFacet.getFacetId() ),
363 metadataFacet.getName() );
364 writeProperties( properties, directory, METADATA_KEY );
366 catch ( IOException e )
369 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
373 public void removeMetadataFacets( String repositoryId, String facetId )
375 File dir = getMetadataDirectory( repositoryId, facetId );
376 if ( !FileUtils.deleteQuietly( dir ) )
378 log.error( "Cannot delete the metadata repository {}", dir );
382 public void removeMetadataFacet( String repoId, String facetId, String name )
384 File dir = new File( getMetadataDirectory( repoId, facetId ), name );
385 if ( !FileUtils.deleteQuietly( dir ) )
387 log.error( "Cannot delete the metadata repository {}", dir );
391 public List<ArtifactMetadata> getArtifactsByDateRange( String repoId, Date startTime, Date endTime )
393 // TODO: this is quite slow - if we are to persist with this repository implementation we should build an index
394 // of this information (eg. in Lucene, as before)
396 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
397 for ( String ns : getRootNamespaces( repoId ) )
399 getArtifactsByDateRange( artifacts, repoId, ns, startTime, endTime );
401 Collections.sort( artifacts, new ArtifactComparator() );
405 private void getArtifactsByDateRange( List<ArtifactMetadata> artifacts, String repoId, String ns, Date startTime,
408 for ( String namespace : getNamespaces( repoId, ns ) )
410 getArtifactsByDateRange( artifacts, repoId, ns + "." + namespace, startTime, endTime );
413 for ( String project : getProjects( repoId, ns ) )
415 for ( String version : getProjectVersions( repoId, ns, project ) )
417 for ( ArtifactMetadata artifact : getArtifacts( repoId, ns, project, version ) )
419 if ( startTime == null || startTime.before( artifact.getWhenGathered() ) )
421 if ( endTime == null || endTime.after( artifact.getWhenGathered() ) )
423 artifacts.add( artifact );
431 public Collection<ArtifactMetadata> getArtifacts( String repoId, String namespace, String projectId,
432 String projectVersion )
434 Map<String, ArtifactMetadata> artifacts = new HashMap<String, ArtifactMetadata>();
436 File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );
438 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
440 for ( Map.Entry entry : properties.entrySet() )
442 String name = (String) entry.getKey();
443 StringTokenizer tok = new StringTokenizer( name, ":" );
444 if ( tok.hasMoreTokens() && "artifact".equals( tok.nextToken() ) )
446 String field = tok.nextToken();
447 String id = tok.nextToken();
449 ArtifactMetadata artifact = artifacts.get( id );
450 if ( artifact == null )
452 artifact = new ArtifactMetadata();
453 artifact.setRepositoryId( repoId );
454 artifact.setNamespace( namespace );
455 artifact.setProject( projectId );
456 artifact.setProjectVersion( projectVersion );
457 artifact.setVersion( projectVersion );
458 artifact.setId( id );
459 artifacts.put( id, artifact );
462 String value = (String) entry.getValue();
463 if ( "updated".equals( field ) )
465 artifact.setFileLastModified( Long.parseLong( value ) );
467 else if ( "size".equals( field ) )
469 artifact.setSize( Long.valueOf( value ) );
471 else if ( "whenGathered".equals( field ) )
473 artifact.setWhenGathered( new Date( Long.parseLong( value ) ) );
475 else if ( "version".equals( field ) )
477 artifact.setVersion( value );
479 else if ( "md5".equals( field ) )
481 artifact.setMd5( value );
483 else if ( "sha1".equals( field ) )
485 artifact.setSha1( value );
487 else if ( "facetIds".equals( field ) )
489 if ( value.length() > 0 )
491 String propertyPrefix = "artifact:facet:" + id + ":";
492 for ( String facetId : value.split( "," ) )
494 MetadataFacetFactory factory = metadataFacetFactories.get( facetId );
495 if ( factory == null )
497 log.error( "Attempted to load unknown artifact metadata facet: " + facetId );
501 MetadataFacet facet = factory.createMetadataFacet();
502 String prefix = propertyPrefix + facet.getFacetId();
503 Map<String, String> map = new HashMap<String, String>();
504 for ( Object key : new ArrayList( properties.keySet() ) )
506 String property = (String) key;
507 if ( property.startsWith( prefix ) )
509 map.put( property.substring( prefix.length() + 1 ), properties.getProperty(
513 facet.fromProperties( map );
514 artifact.addFacet( facet );
519 updateArtifactFacets( artifact, properties );
523 return artifacts.values();
527 throws MetadataRepositoryException
529 // it's all instantly persisted
534 // nothing additional to close
538 throws MetadataRepositoryException
540 log.warn( "Attempted to revert a session, but the file-based repository storage doesn't support it" );
543 public boolean canObtainAccess( Class<?> aClass )
548 public Object obtainAccess( Class<?> aClass )
550 throw new IllegalArgumentException(
551 "Access using " + aClass + " is not supported on the file metadata storage" );
554 private void updateArtifactFacets( ArtifactMetadata artifact, Properties properties )
556 String propertyPrefix = "artifact:facet:" + artifact.getId() + ":";
557 for ( MetadataFacet facet : artifact.getFacetList() )
559 for ( Map.Entry<String, String> e : facet.toProperties().entrySet() )
561 String key = propertyPrefix + facet.getFacetId() + ":" + e.getKey();
562 properties.setProperty( key, e.getValue() );
567 public Collection<String> getRepositories()
569 return configuration.getConfiguration().getManagedRepositoriesAsMap().keySet();
572 public List<ArtifactMetadata> getArtifactsByChecksum( String repositoryId, String checksum )
574 // TODO: this is quite slow - if we are to persist with this repository implementation we should build an index
575 // of this information (eg. in Lucene, as before)
576 // alternatively, we could build a referential tree in the content repository, however it would need some levels
577 // of depth to avoid being too broad to be useful (eg. /repository/checksums/a/ab/abcdef1234567)
579 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
580 for ( String ns : getRootNamespaces( repositoryId ) )
582 getArtifactsByChecksum( artifacts, repositoryId, ns, checksum );
587 public void removeArtifact( String repoId, String namespace, String project, String version, String id )
589 File directory = new File( getDirectory( repoId ), namespace + "/" + project + "/" + version );
591 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
593 properties.remove( "artifact:updated:" + id );
594 properties.remove( "artifact:whenGathered:" + id );
595 properties.remove( "artifact:size:" + id );
596 properties.remove( "artifact:md5:" + id );
597 properties.remove( "artifact:sha1:" + id );
598 properties.remove( "artifact:version:" + id );
599 properties.remove( "artifact:facetIds:" + id );
601 String prefix = "artifact:facet:" + id + ":";
602 for ( Object key : new ArrayList<Object>( properties.keySet() ) )
604 String property = (String) key;
605 if ( property.startsWith( prefix ) )
607 properties.remove( property );
613 writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
615 catch ( IOException e )
618 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
622 public void removeRepository( String repoId )
624 File dir = getDirectory( repoId );
625 if ( !FileUtils.deleteQuietly( dir ) )
627 log.error( "Cannot delete repository {}", dir );
631 private void getArtifactsByChecksum( List<ArtifactMetadata> artifacts, String repositoryId, String ns,
634 for ( String namespace : getNamespaces( repositoryId, ns ) )
636 getArtifactsByChecksum( artifacts, repositoryId, ns + "." + namespace, checksum );
639 for ( String project : getProjects( repositoryId, ns ) )
641 for ( String version : getProjectVersions( repositoryId, ns, project ) )
643 for ( ArtifactMetadata artifact : getArtifacts( repositoryId, ns, project, version ) )
645 if ( checksum.equals( artifact.getMd5() ) || checksum.equals( artifact.getSha1() ) )
647 artifacts.add( artifact );
654 private File getMetadataDirectory( String repoId, String facetId )
656 return new File( getBaseDirectory( repoId ), "facets/" + facetId );
659 private String join( Collection<String> ids )
661 if ( ids != null && !ids.isEmpty() )
663 StringBuilder s = new StringBuilder();
664 for ( String id : ids )
669 return s.substring( 0, s.length() - 1 );
674 private void setProperty( Properties properties, String name, String value )
678 properties.setProperty( name, value );
682 public void updateArtifact( String repoId, String namespace, String projectId, String projectVersion,
683 ArtifactMetadata artifact )
685 ProjectVersionMetadata metadata = new ProjectVersionMetadata();
686 metadata.setId( projectVersion );
687 updateProjectVersion( repoId, namespace, projectId, metadata );
689 File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );
691 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
693 clearMetadataFacetProperties( artifact.getFacetList(), properties, "artifact:facet:" + artifact.getId() + ":" );
695 String id = artifact.getId();
696 properties.setProperty( "artifact:updated:" + id, Long.toString( artifact.getFileLastModified().getTime() ) );
697 properties.setProperty( "artifact:whenGathered:" + id, Long.toString( artifact.getWhenGathered().getTime() ) );
698 properties.setProperty( "artifact:size:" + id, Long.toString( artifact.getSize() ) );
699 if ( artifact.getMd5() != null )
701 properties.setProperty( "artifact:md5:" + id, artifact.getMd5() );
703 if ( artifact.getSha1() != null )
705 properties.setProperty( "artifact:sha1:" + id, artifact.getSha1() );
707 properties.setProperty( "artifact:version:" + id, artifact.getVersion() );
709 Set<String> facetIds = new LinkedHashSet<String>( artifact.getFacetIds() );
710 String property = "artifact:facetIds:" + id;
711 facetIds.addAll( Arrays.asList( properties.getProperty( property, "" ).split( "," ) ) );
712 properties.setProperty( property, join( facetIds ) );
714 updateArtifactFacets( artifact, properties );
718 writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
720 catch ( IOException e )
723 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
727 private Properties readOrCreateProperties( File directory, String propertiesKey )
731 return readProperties( directory, propertiesKey );
733 catch ( FileNotFoundException e )
735 // ignore and return new properties
737 catch ( IOException e )
740 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
742 return new Properties();
745 private Properties readProperties( File directory, String propertiesKey )
748 Properties properties = new Properties();
749 FileInputStream in = null;
752 in = new FileInputStream( new File( directory, propertiesKey + ".properties" ) );
753 properties.load( in );
757 IOUtils.closeQuietly( in );
762 public ProjectMetadata getProject( String repoId, String namespace, String projectId )
764 File directory = new File( getDirectory( repoId ), namespace + "/" + projectId );
766 Properties properties = readOrCreateProperties( directory, PROJECT_METADATA_KEY );
768 ProjectMetadata project = null;
770 String id = properties.getProperty( "id" );
773 project = new ProjectMetadata();
774 project.setNamespace( properties.getProperty( "namespace" ) );
781 public ProjectVersionMetadata getProjectVersion( String repoId, String namespace, String projectId,
782 String projectVersion )
784 File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );
786 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
787 String id = properties.getProperty( "id" );
788 ProjectVersionMetadata versionMetadata = null;
791 versionMetadata = new ProjectVersionMetadata();
792 versionMetadata.setId( id );
793 versionMetadata.setName( properties.getProperty( "name" ) );
794 versionMetadata.setDescription( properties.getProperty( "description" ) );
795 versionMetadata.setUrl( properties.getProperty( "url" ) );
796 versionMetadata.setIncomplete( Boolean.valueOf( properties.getProperty( "incomplete", "false" ) ) );
798 String scmConnection = properties.getProperty( "scm.connection" );
799 String scmDeveloperConnection = properties.getProperty( "scm.developerConnection" );
800 String scmUrl = properties.getProperty( "scm.url" );
801 if ( scmConnection != null || scmDeveloperConnection != null || scmUrl != null )
804 scm.setConnection( scmConnection );
805 scm.setDeveloperConnection( scmDeveloperConnection );
806 scm.setUrl( scmUrl );
807 versionMetadata.setScm( scm );
810 String ciSystem = properties.getProperty( "ci.system" );
811 String ciUrl = properties.getProperty( "ci.url" );
812 if ( ciSystem != null || ciUrl != null )
814 CiManagement ci = new CiManagement();
815 ci.setSystem( ciSystem );
817 versionMetadata.setCiManagement( ci );
820 String issueSystem = properties.getProperty( "issue.system" );
821 String issueUrl = properties.getProperty( "issue.url" );
822 if ( issueSystem != null || issueUrl != null )
824 IssueManagement issueManagement = new IssueManagement();
825 issueManagement.setSystem( issueSystem );
826 issueManagement.setUrl( issueUrl );
827 versionMetadata.setIssueManagement( issueManagement );
830 String orgName = properties.getProperty( "org.name" );
831 String orgUrl = properties.getProperty( "org.url" );
832 if ( orgName != null || orgUrl != null )
834 Organization org = new Organization();
835 org.setName( orgName );
836 org.setUrl( orgUrl );
837 versionMetadata.setOrganization( org );
840 boolean done = false;
844 String licenseName = properties.getProperty( "license." + i + ".name" );
845 String licenseUrl = properties.getProperty( "license." + i + ".url" );
846 if ( licenseName != null || licenseUrl != null )
848 License license = new License();
849 license.setName( licenseName );
850 license.setUrl( licenseUrl );
851 versionMetadata.addLicense( license );
864 String mailingListName = properties.getProperty( "mailingList." + i + ".name" );
865 if ( mailingListName != null )
867 MailingList mailingList = new MailingList();
868 mailingList.setName( mailingListName );
869 mailingList.setMainArchiveUrl( properties.getProperty( "mailingList." + i + ".archive" ) );
870 String p = properties.getProperty( "mailingList." + i + ".otherArchives" );
871 if ( p != null && p.length() > 0 )
873 mailingList.setOtherArchives( Arrays.asList( p.split( "," ) ) );
877 mailingList.setOtherArchives( Collections.<String>emptyList() );
879 mailingList.setPostAddress( properties.getProperty( "mailingList." + i + ".post" ) );
880 mailingList.setSubscribeAddress( properties.getProperty( "mailingList." + i + ".subscribe" ) );
881 mailingList.setUnsubscribeAddress( properties.getProperty( "mailingList." + i + ".unsubscribe" ) );
882 versionMetadata.addMailingList( mailingList );
895 String dependencyArtifactId = properties.getProperty( "dependency." + i + ".artifactId" );
896 if ( dependencyArtifactId != null )
898 Dependency dependency = new Dependency();
899 dependency.setArtifactId( dependencyArtifactId );
900 dependency.setGroupId( properties.getProperty( "dependency." + i + ".groupId" ) );
901 dependency.setClassifier( properties.getProperty( "dependency." + i + ".classifier" ) );
902 dependency.setOptional( Boolean.valueOf( properties.getProperty(
903 "dependency." + i + ".optional" ) ) );
904 dependency.setScope( properties.getProperty( "dependency." + i + ".scope" ) );
905 dependency.setSystemPath( properties.getProperty( "dependency." + i + ".systemPath" ) );
906 dependency.setType( properties.getProperty( "dependency." + i + ".type" ) );
907 dependency.setVersion( properties.getProperty( "dependency." + i + ".version" ) );
908 dependency.setOptional( Boolean.valueOf( properties.getProperty(
909 "dependency." + i + ".optional" ) ) );
910 versionMetadata.addDependency( dependency );
919 String facetIds = properties.getProperty( "facetIds", "" );
920 if ( facetIds.length() > 0 )
922 for ( String facetId : facetIds.split( "," ) )
924 MetadataFacetFactory factory = metadataFacetFactories.get( facetId );
925 if ( factory == null )
927 log.error( "Attempted to load unknown project version metadata facet: " + facetId );
931 MetadataFacet facet = factory.createMetadataFacet();
932 Map<String, String> map = new HashMap<String, String>();
933 for ( Object key : new ArrayList( properties.keySet() ) )
935 String property = (String) key;
936 if ( property.startsWith( facet.getFacetId() ) )
938 map.put( property.substring( facet.getFacetId().length() + 1 ), properties.getProperty(
942 facet.fromProperties( map );
943 versionMetadata.addFacet( facet );
948 updateProjectVersionFacets( versionMetadata, properties );
950 return versionMetadata;
953 public Collection<String> getArtifactVersions( String repoId, String namespace, String projectId,
954 String projectVersion )
956 File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );
958 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
960 Set<String> versions = new HashSet<String>();
961 for ( Map.Entry entry : properties.entrySet() )
963 String name = (String) entry.getKey();
964 if ( name.startsWith( "artifact:version:" ) )
966 versions.add( (String) entry.getValue() );
972 public Collection<ProjectVersionReference> getProjectReferences( String repoId, String namespace, String projectId,
973 String projectVersion )
975 File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );
977 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
978 int numberOfRefs = Integer.parseInt( properties.getProperty( "ref:lastReferenceNum", "-1" ) ) + 1;
980 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
981 for ( int i = 0; i < numberOfRefs; i++ )
983 ProjectVersionReference reference = new ProjectVersionReference();
984 reference.setProjectId( properties.getProperty( "ref:reference." + i + ".projectId" ) );
985 reference.setNamespace( properties.getProperty( "ref:reference." + i + ".namespace" ) );
986 reference.setProjectVersion( properties.getProperty( "ref:reference." + i + ".projectVersion" ) );
987 reference.setReferenceType( ProjectVersionReference.ReferenceType.valueOf( properties.getProperty(
988 "ref:reference." + i + ".referenceType" ) ) );
989 references.add( reference );
994 public Collection<String> getRootNamespaces( String repoId )
996 return getNamespaces( repoId, null );
999 public Collection<String> getNamespaces( String repoId, String baseNamespace )
1001 List<String> allNamespaces = new ArrayList<String>();
1002 File directory = getDirectory( repoId );
1003 File[] files = directory.listFiles();
1004 if ( files != null )
1006 for ( File namespace : files )
1008 if ( new File( namespace, NAMESPACE_METADATA_KEY + ".properties" ).exists() )
1010 allNamespaces.add( namespace.getName() );
1015 Set<String> namespaces = new LinkedHashSet<String>();
1016 int fromIndex = baseNamespace != null ? baseNamespace.length() + 1 : 0;
1017 for ( String namespace : allNamespaces )
1019 if ( baseNamespace == null || namespace.startsWith( baseNamespace + "." ) )
1021 int i = namespace.indexOf( '.', fromIndex );
1024 namespaces.add( namespace.substring( fromIndex, i ) );
1028 namespaces.add( namespace.substring( fromIndex ) );
1032 return new ArrayList<String>( namespaces );
1035 public Collection<String> getProjects( String repoId, String namespace )
1037 List<String> projects = new ArrayList<String>();
1038 File directory = new File( getDirectory( repoId ), namespace );
1039 File[] files = directory.listFiles();
1040 if ( files != null )
1042 for ( File project : files )
1044 if ( new File( project, PROJECT_METADATA_KEY + ".properties" ).exists() )
1046 projects.add( project.getName() );
1053 public Collection<String> getProjectVersions( String repoId, String namespace, String projectId )
1055 List<String> projectVersions = new ArrayList<String>();
1056 File directory = new File( getDirectory( repoId ), namespace + "/" + projectId );
1057 File[] files = directory.listFiles();
1058 if ( files != null )
1060 for ( File projectVersion : files )
1062 if ( new File( projectVersion, PROJECT_VERSION_METADATA_KEY + ".properties" ).exists() )
1064 projectVersions.add( projectVersion.getName() );
1068 return projectVersions;
1071 private void writeProperties( Properties properties, File directory, String propertiesKey )
1075 FileOutputStream os = new FileOutputStream( new File( directory, propertiesKey + ".properties" ) );
1078 properties.store( os, null );
1082 IOUtils.closeQuietly( os );
1086 private static class ArtifactComparator
1087 implements Comparator<ArtifactMetadata>
1089 public int compare( ArtifactMetadata artifact1, ArtifactMetadata artifact2 )
1091 if ( artifact1.getWhenGathered() == artifact2.getWhenGathered() )
1095 if ( artifact1.getWhenGathered() == null )
1099 if ( artifact2.getWhenGathered() == null )
1103 return artifact1.getWhenGathered().compareTo( artifact2.getWhenGathered() );
1107 public List<ArtifactMetadata> getArtifacts( String repoId )
1109 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
1110 for ( String ns : getRootNamespaces( repoId ) )
1112 getArtifacts( artifacts, repoId, ns );
1117 private void getArtifacts( List<ArtifactMetadata> artifacts, String repoId, String ns )
1119 for ( String namespace : getNamespaces( repoId, ns ) )
1121 getArtifacts( artifacts, repoId, ns + "." + namespace );
1124 for ( String project : getProjects( repoId, ns ) )
1126 for ( String version : getProjectVersions( repoId, ns, project ) )
1128 for ( ArtifactMetadata artifact : getArtifacts( repoId, ns, project, version ) )
1130 artifacts.add( artifact );