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
23 import java.io.FileInputStream;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.LinkedHashSet;
33 import java.util.List;
35 import java.util.Properties;
38 import org.apache.archiva.metadata.model.ArtifactMetadata;
39 import org.apache.archiva.metadata.model.CiManagement;
40 import org.apache.archiva.metadata.model.Dependency;
41 import org.apache.archiva.metadata.model.IssueManagement;
42 import org.apache.archiva.metadata.model.License;
43 import org.apache.archiva.metadata.model.MailingList;
44 import org.apache.archiva.metadata.model.MetadataFacet;
45 import org.apache.archiva.metadata.model.MetadataFacetFactory;
46 import org.apache.archiva.metadata.model.Organization;
47 import org.apache.archiva.metadata.model.ProjectMetadata;
48 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
49 import org.apache.archiva.metadata.model.ProjectVersionReference;
50 import org.apache.archiva.metadata.model.Scm;
51 import org.apache.archiva.metadata.repository.MetadataRepository;
52 import org.apache.commons.io.FileUtils;
53 import org.apache.commons.io.IOUtils;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
58 * @plexus.component role="org.apache.archiva.metadata.repository.MetadataRepository"
60 public class FileMetadataRepository
61 implements MetadataRepository
64 * TODO: this isn't suitable for production use
66 * @plexus.configuration
68 private File directory = new File( System.getProperty( "user.home" ), ".archiva-metadata" );
71 * @plexus.requirement role="org.apache.archiva.metadata.model.MetadataFacetFactory"
73 private Map<String, MetadataFacetFactory> metadataFacetFactories;
75 private static final Logger log = LoggerFactory.getLogger( FileMetadataRepository.class );
77 private static final String PROJECT_METADATA_KEY = "project-metadata";
79 private static final String PROJECT_VERSION_METADATA_KEY = "version-metadata";
81 private static final String NAMESPACE_METADATA_KEY = "namespace-metadata";
83 private static final String METADATA_KEY = "metadata";
85 public void updateProject( String repoId, ProjectMetadata project )
87 updateProject( repoId, project.getNamespace(), project.getId() );
90 private void updateProject( String repoId, String namespace, String id )
92 // TODO: this is a more braindead implementation than we would normally expect, for prototyping purposes
93 updateNamespace( repoId, namespace );
97 File namespaceDirectory = new File( this.directory, repoId + "/" + namespace );
98 Properties properties = new Properties();
99 properties.setProperty( "namespace", namespace );
100 properties.setProperty( "id", id );
101 writeProperties( properties, new File( namespaceDirectory, id ), PROJECT_METADATA_KEY );
103 catch ( IOException e )
110 public void updateProjectVersion( String repoId, String namespace, String projectId,
111 ProjectVersionMetadata versionMetadata )
113 updateProject( repoId, namespace, projectId );
116 new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + versionMetadata.getId() );
118 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
119 // remove properties that are not references or artifacts
120 for ( String name : properties.stringPropertyNames() )
122 if ( !name.contains( ":" ) && !name.equals( "facetIds" ) )
124 properties.remove( name );
127 properties.setProperty( "id", versionMetadata.getId() );
128 setProperty( properties, "name", versionMetadata.getName() );
129 setProperty( properties, "description", versionMetadata.getDescription() );
130 setProperty( properties, "url", versionMetadata.getUrl() );
131 if ( versionMetadata.getScm() != null )
133 setProperty( properties, "scm.connection", versionMetadata.getScm().getConnection() );
134 setProperty( properties, "scm.developerConnection", versionMetadata.getScm().getDeveloperConnection() );
135 setProperty( properties, "scm.url", versionMetadata.getScm().getUrl() );
137 if ( versionMetadata.getCiManagement() != null )
139 setProperty( properties, "ci.system", versionMetadata.getCiManagement().getSystem() );
140 setProperty( properties, "ci.url", versionMetadata.getCiManagement().getUrl() );
142 if ( versionMetadata.getIssueManagement() != null )
144 setProperty( properties, "issue.system", versionMetadata.getIssueManagement().getSystem() );
145 setProperty( properties, "issue.url", versionMetadata.getIssueManagement().getUrl() );
147 if ( versionMetadata.getOrganization() != null )
149 setProperty( properties, "org.name", versionMetadata.getOrganization().getName() );
150 setProperty( properties, "org.url", versionMetadata.getOrganization().getUrl() );
153 for ( License license : versionMetadata.getLicenses() )
155 setProperty( properties, "license." + i + ".name", license.getName() );
156 setProperty( properties, "license." + i + ".url", license.getUrl() );
160 for ( MailingList mailingList : versionMetadata.getMailingLists() )
162 setProperty( properties, "mailingList." + i + ".archive", mailingList.getMainArchiveUrl() );
163 setProperty( properties, "mailingList." + i + ".name", mailingList.getName() );
164 setProperty( properties, "mailingList." + i + ".post", mailingList.getPostAddress() );
165 setProperty( properties, "mailingList." + i + ".unsubscribe", mailingList.getUnsubscribeAddress() );
166 setProperty( properties, "mailingList." + i + ".subscribe", mailingList.getSubscribeAddress() );
167 setProperty( properties, "mailingList." + i + ".otherArchives", join( mailingList.getOtherArchives() ) );
171 for ( Dependency dependency : versionMetadata.getDependencies() )
173 setProperty( properties, "dependency." + i + ".classifier", dependency.getClassifier() );
174 setProperty( properties, "dependency." + i + ".scope", dependency.getScope() );
175 setProperty( properties, "dependency." + i + ".systemPath", dependency.getSystemPath() );
176 setProperty( properties, "dependency." + i + ".artifactId", dependency.getArtifactId() );
177 setProperty( properties, "dependency." + i + ".groupId", dependency.getGroupId() );
178 setProperty( properties, "dependency." + i + ".version", dependency.getVersion() );
179 setProperty( properties, "dependency." + i + ".type", dependency.getType() );
182 Set<String> facetIds = new LinkedHashSet<String>( versionMetadata.getFacetIds() );
183 facetIds.addAll( Arrays.asList( properties.getProperty( "facetIds", "" ).split( "," ) ) );
184 properties.setProperty( "facetIds", join( facetIds ) );
186 for ( MetadataFacet facet : versionMetadata.getFacetList() )
188 properties.putAll( facet.toProperties() );
193 writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
195 catch ( IOException e )
198 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
202 public void updateProjectReference( String repoId, String namespace, String projectId, String projectVersion,
203 ProjectVersionReference reference )
205 File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion );
207 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
208 int i = Integer.valueOf( properties.getProperty( "ref:lastReferenceNum", "-1" ) ) + 1;
209 setProperty( properties, "ref:lastReferenceNum", Integer.toString( i ) );
210 setProperty( properties, "ref:reference." + i + ".namespace", reference.getNamespace() );
211 setProperty( properties, "ref:reference." + i + ".projectId", reference.getProjectId() );
212 setProperty( properties, "ref:reference." + i + ".projectVersion", reference.getProjectVersion() );
213 setProperty( properties, "ref:reference." + i + ".referenceType", reference.getReferenceType().toString() );
217 writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
219 catch ( IOException e )
222 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
226 public void updateNamespace( String repoId, String namespace )
230 File namespaceDirectory = new File( this.directory, repoId + "/" + namespace );
231 Properties properties = new Properties();
232 properties.setProperty( "namespace", namespace );
233 writeProperties( properties, namespaceDirectory, NAMESPACE_METADATA_KEY );
236 catch ( IOException e )
243 public List<String> getMetadataFacets( String repoId, String facetId )
245 File directory = getMetadataDirectory( repoId, facetId );
246 String[] list = directory.list();
247 return list != null ? Arrays.asList( list ) : Collections.<String>emptyList();
250 public MetadataFacet getMetadataFacet( String repositoryId, String facetId, String name )
252 Properties properties;
256 readProperties( new File( getMetadataDirectory( repositoryId, facetId ), name ), METADATA_KEY );
258 catch ( FileNotFoundException e )
262 catch ( IOException e )
265 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
268 MetadataFacet metadataFacet = null;
269 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId );
270 if ( metadataFacetFactory != null )
272 metadataFacet = metadataFacetFactory.createMetadataFacet();
273 Map<String, String> map = new HashMap<String, String>();
274 for ( String key : properties.stringPropertyNames() )
276 map.put( key, properties.getProperty( key ) );
278 metadataFacet.fromProperties( map );
280 return metadataFacet;
283 public void addMetadataFacet( String repositoryId, String facetId, String name, MetadataFacet metadataFacet )
285 Properties properties = new Properties();
286 properties.putAll( metadataFacet.toProperties() );
290 writeProperties( properties, new File( getMetadataDirectory( repositoryId, facetId ), name ),
293 catch ( IOException e )
296 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
300 public void removeMetadataFacets( String repositoryId, String facetId )
304 FileUtils.deleteDirectory( getMetadataDirectory( repositoryId, facetId ) );
306 catch ( IOException e )
309 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
313 private File getMetadataDirectory( String repositoryId, String facetId )
315 return new File( this.directory, repositoryId + "/.meta/" + facetId );
318 private String join( Collection<String> ids )
320 if ( !ids.isEmpty() )
322 StringBuilder s = new StringBuilder();
323 for ( String id : ids )
328 return s.substring( 0, s.length() - 1 );
333 private void setProperty( Properties properties, String name, String value )
337 properties.setProperty( name, value );
341 public void updateArtifact( String repoId, String namespace, String projectId, String projectVersion,
342 ArtifactMetadata artifact )
344 File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion );
346 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
348 properties.setProperty( "artifact:updated:" + artifact.getId(),
349 Long.toString( artifact.getFileLastModified().getTime() ) );
350 properties.setProperty( "artifact:whenGathered:" + artifact.getId(),
351 Long.toString( artifact.getWhenGathered().getTime() ) );
352 properties.setProperty( "artifact:size:" + artifact.getId(), Long.toString( artifact.getSize() ) );
353 properties.setProperty( "artifact:md5:" + artifact.getId(), artifact.getMd5() );
354 properties.setProperty( "artifact:sha1:" + artifact.getId(), artifact.getMd5() );
355 properties.setProperty( "artifact:version:" + artifact.getId(), artifact.getVersion() );
359 writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
361 catch ( IOException e )
364 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
368 private Properties readOrCreateProperties( File directory, String propertiesKey )
372 return readProperties( directory, propertiesKey );
374 catch ( FileNotFoundException e )
376 // ignore and return new properties
378 catch ( IOException e )
381 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
383 return new Properties();
386 private Properties readProperties( File directory, String propertiesKey )
389 Properties properties = new Properties();
390 FileInputStream in = null;
393 in = new FileInputStream( new File( directory, propertiesKey + ".properties" ) );
394 properties.load( in );
398 IOUtils.closeQuietly( in );
403 public ProjectMetadata getProject( String repoId, String namespace, String projectId )
405 File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId );
407 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
409 ProjectMetadata project = new ProjectMetadata();
410 project.setNamespace( properties.getProperty( "namespace" ) );
411 project.setId( properties.getProperty( "id" ) );
415 public ProjectVersionMetadata getProjectVersion( String repoId, String namespace, String projectId,
416 String projectVersion )
418 File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion );
420 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
421 String id = properties.getProperty( "id" );
422 ProjectVersionMetadata versionMetadata = null;
425 versionMetadata = new ProjectVersionMetadata();
426 versionMetadata.setId( id );
427 versionMetadata.setName( properties.getProperty( "name" ) );
428 versionMetadata.setDescription( properties.getProperty( "description" ) );
429 versionMetadata.setUrl( properties.getProperty( "url" ) );
431 String scmConnection = properties.getProperty( "scm.connection" );
432 String scmDeveloperConnection = properties.getProperty( "scm.developerConnection" );
433 String scmUrl = properties.getProperty( "scm.url" );
434 if ( scmConnection != null || scmDeveloperConnection != null || scmUrl != null )
437 scm.setConnection( scmConnection );
438 scm.setDeveloperConnection( scmDeveloperConnection );
439 scm.setUrl( scmUrl );
440 versionMetadata.setScm( scm );
443 String ciSystem = properties.getProperty( "ci.system" );
444 String ciUrl = properties.getProperty( "ci.url" );
445 if ( ciSystem != null || ciUrl != null )
447 CiManagement ci = new CiManagement();
448 ci.setSystem( ciSystem );
450 versionMetadata.setCiManagement( ci );
453 String issueSystem = properties.getProperty( "issue.system" );
454 String issueUrl = properties.getProperty( "issue.url" );
455 if ( issueSystem != null || issueUrl != null )
457 IssueManagement issueManagement = new IssueManagement();
458 issueManagement.setSystem( issueSystem );
459 issueManagement.setUrl( issueUrl );
460 versionMetadata.setIssueManagement( issueManagement );
463 String orgName = properties.getProperty( "org.name" );
464 String orgUrl = properties.getProperty( "org.url" );
465 if ( orgName != null || orgUrl != null )
467 Organization org = new Organization();
468 org.setName( orgName );
469 org.setUrl( orgUrl );
470 versionMetadata.setOrganization( org );
473 boolean done = false;
477 String licenseName = properties.getProperty( "license." + i + ".name" );
478 String licenseUrl = properties.getProperty( "license." + i + ".url" );
479 if ( licenseName != null || licenseUrl != null )
481 License license = new License();
482 license.setName( licenseName );
483 license.setUrl( licenseUrl );
484 versionMetadata.addLicense( license );
497 String mailingListName = properties.getProperty( "mailingList." + i + ".name" );
498 if ( mailingListName != null )
500 MailingList mailingList = new MailingList();
501 mailingList.setName( mailingListName );
502 mailingList.setMainArchiveUrl( properties.getProperty( "mailingList." + i + ".archive" ) );
503 mailingList.setOtherArchives(
504 Arrays.asList( properties.getProperty( "mailingList." + i + ".otherArchives" ).split( "," ) ) );
505 mailingList.setPostAddress( properties.getProperty( "mailingList." + i + ".post" ) );
506 mailingList.setSubscribeAddress( properties.getProperty( "mailingList." + i + ".subscribe" ) );
507 mailingList.setUnsubscribeAddress( properties.getProperty( "mailingList." + i + ".unsubscribe" ) );
508 versionMetadata.addMailingList( mailingList );
521 String dependencyArtifactId = properties.getProperty( "dependency." + i + ".artifactId" );
522 if ( dependencyArtifactId != null )
524 Dependency dependency = new Dependency();
525 dependency.setArtifactId( dependencyArtifactId );
526 dependency.setGroupId( properties.getProperty( "dependency." + i + ".groupId" ) );
527 dependency.setClassifier( properties.getProperty( "dependency." + i + ".classifier" ) );
528 dependency.setOptional(
529 Boolean.valueOf( properties.getProperty( "dependency." + i + ".optional" ) ) );
530 dependency.setScope( properties.getProperty( "dependency." + i + ".scope" ) );
531 dependency.setSystemPath( properties.getProperty( "dependency." + i + ".systemPath" ) );
532 dependency.setType( properties.getProperty( "dependency." + i + ".type" ) );
533 dependency.setVersion( properties.getProperty( "dependency." + i + ".version" ) );
534 versionMetadata.addDependency( dependency );
543 for ( String facetId : properties.getProperty( "facetIds" ).split( "," ) )
545 MetadataFacetFactory factory = metadataFacetFactories.get( facetId );
546 if ( factory == null )
548 log.error( "Attempted to load unknown metadata facet: " + facetId );
552 MetadataFacet facet = factory.createMetadataFacet();
553 Map<String, String> map = new HashMap<String, String>();
554 for ( String key : properties.stringPropertyNames() )
556 if ( key.startsWith( facet.getFacetId() ) )
558 map.put( key, properties.getProperty( key ) );
561 facet.fromProperties( map );
562 versionMetadata.addFacet( facet );
566 for ( MetadataFacet facet : versionMetadata.getFacetList() )
568 properties.putAll( facet.toProperties() );
571 return versionMetadata;
574 public Collection<String> getArtifactVersions( String repoId, String namespace, String projectId,
575 String projectVersion )
577 File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion );
579 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
581 List<String> versions = new ArrayList<String>();
582 for ( Map.Entry entry : properties.entrySet() )
584 String name = (String) entry.getKey();
585 if ( name.startsWith( "version:" ) )
587 versions.add( (String) entry.getValue() );
593 public Collection<ProjectVersionReference> getProjectReferences( String repoId, String namespace, String projectId,
594 String projectVersion )
596 File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId + "/" + projectVersion );
598 Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
599 int numberOfRefs = Integer.valueOf( properties.getProperty( "ref:lastReferenceNum", "-1" ) ) + 1;
601 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
602 for ( int i = 0; i < numberOfRefs; i++ )
604 ProjectVersionReference reference = new ProjectVersionReference();
605 reference.setProjectId( properties.getProperty( "ref:reference." + i + ".projectId" ) );
606 reference.setNamespace( properties.getProperty( "ref:reference." + i + ".namespace" ) );
607 reference.setProjectVersion( properties.getProperty( "ref:reference." + i + ".projectVersion" ) );
608 reference.setReferenceType( ProjectVersionReference.ReferenceType.valueOf(
609 properties.getProperty( "ref:reference." + i + ".referenceType" ) ) );
610 references.add( reference );
615 public Collection<String> getRootNamespaces( String repoId )
617 return getNamespaces( repoId, null );
620 public Collection<String> getNamespaces( String repoId, String baseNamespace )
622 List<String> allNamespaces = new ArrayList<String>();
623 File directory = new File( this.directory, repoId );
624 File[] files = directory.listFiles();
627 for ( File namespace : files )
629 if ( new File( namespace, NAMESPACE_METADATA_KEY + ".properties" ).exists() )
631 allNamespaces.add( namespace.getName() );
636 Set<String> namespaces = new LinkedHashSet<String>();
637 int fromIndex = baseNamespace != null ? baseNamespace.length() + 1 : 0;
638 for ( String namespace : allNamespaces )
640 if ( baseNamespace == null || namespace.startsWith( baseNamespace + "." ) )
642 int i = namespace.indexOf( '.', fromIndex );
645 namespaces.add( namespace.substring( fromIndex, i ) );
649 namespaces.add( namespace.substring( fromIndex ) );
653 return new ArrayList<String>( namespaces );
656 public Collection<String> getProjects( String repoId, String namespace )
658 List<String> projects = new ArrayList<String>();
659 File directory = new File( this.directory, repoId + "/" + namespace );
660 File[] files = directory.listFiles();
663 for ( File project : files )
665 if ( new File( project, PROJECT_METADATA_KEY + ".properties" ).exists() )
667 projects.add( project.getName() );
674 public Collection<String> getProjectVersions( String repoId, String namespace, String projectId )
676 List<String> projectVersions = new ArrayList<String>();
677 File directory = new File( this.directory, repoId + "/" + namespace + "/" + projectId );
678 File[] files = directory.listFiles();
681 for ( File projectVersion : files )
683 if ( new File( projectVersion, PROJECT_VERSION_METADATA_KEY + ".properties" ).exists() )
685 projectVersions.add( projectVersion.getName() );
689 return projectVersions;
692 private void writeProperties( Properties properties, File directory, String propertiesKey )
696 FileOutputStream os = new FileOutputStream( new File( directory, propertiesKey + ".properties" ) );
699 properties.store( os, null );
703 IOUtils.closeQuietly( os );
707 public void setDirectory( File directory )
709 this.directory = directory;
712 public void setMetadataFacetFactories( Map<String, MetadataFacetFactory> metadataFacetFactories )
714 this.metadataFacetFactories = metadataFacetFactories;