1 package org.apache.archiva.metadata.repository.jcr;
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.archiva.metadata.repository.MetadataResolutionException;
38 import org.apache.jackrabbit.commons.JcrUtils;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Calendar;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.Date;
48 import java.util.HashMap;
49 import java.util.LinkedHashSet;
50 import java.util.List;
53 import javax.jcr.NamespaceRegistry;
54 import javax.jcr.Node;
55 import javax.jcr.NodeIterator;
56 import javax.jcr.PathNotFoundException;
57 import javax.jcr.Property;
58 import javax.jcr.Repository;
59 import javax.jcr.RepositoryException;
60 import javax.jcr.Session;
61 import javax.jcr.SimpleCredentials;
62 import javax.jcr.ValueFactory;
63 import javax.jcr.Workspace;
64 import javax.jcr.nodetype.NodeTypeManager;
65 import javax.jcr.nodetype.NodeTypeTemplate;
66 import javax.jcr.query.Query;
67 import javax.jcr.query.QueryResult;
70 * @todo below: revise storage format for project version metadata
71 * @todo revise reference storage
73 public class JcrMetadataRepository
74 implements MetadataRepository
76 private static final String JCR_LAST_MODIFIED = "jcr:lastModified";
78 static final String NAMESPACE_NODE_TYPE = "archiva:namespace";
80 static final String PROJECT_NODE_TYPE = "archiva:project";
82 static final String PROJECT_VERSION_NODE_TYPE = "archiva:projectVersion";
84 static final String ARTIFACT_NODE_TYPE = "archiva:artifact";
86 static final String FACET_NODE_TYPE = "archiva:facet";
88 private final Map<String, MetadataFacetFactory> metadataFacetFactories;
90 private static final Logger log = LoggerFactory.getLogger( JcrMetadataRepository.class );
92 private Repository repository;
94 private Session session;
96 public JcrMetadataRepository( Map<String, MetadataFacetFactory> metadataFacetFactories, Repository repository )
97 throws RepositoryException
99 this.metadataFacetFactories = metadataFacetFactories;
100 this.repository = repository;
102 session = repository.login( new SimpleCredentials( "username", "password".toCharArray() ) );
105 static void initialize( Session session )
106 throws RepositoryException
108 // TODO: consider using namespaces for facets instead of the current approach:
109 // (if used, check if actually called by normal injection)
110 // for ( String facetId : metadataFacetFactories.keySet() )
112 // session.getWorkspace().getNamespaceRegistry().registerNamespace( facetId, facetId );
115 Workspace workspace = session.getWorkspace();
116 NamespaceRegistry registry = workspace.getNamespaceRegistry();
118 if ( !Arrays.asList( registry.getPrefixes() ).contains( "archiva" ) )
120 registry.registerNamespace( "archiva", "http://archiva.apache.org/jcr/" );
123 NodeTypeManager nodeTypeManager = workspace.getNodeTypeManager();
124 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.NAMESPACE_NODE_TYPE );
125 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.PROJECT_NODE_TYPE );
126 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.PROJECT_VERSION_NODE_TYPE );
127 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.ARTIFACT_NODE_TYPE );
128 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.FACET_NODE_TYPE );
131 private static void registerMixinNodeType( NodeTypeManager nodeTypeManager, String name )
132 throws RepositoryException
134 NodeTypeTemplate nodeType = nodeTypeManager.createNodeTypeTemplate();
135 nodeType.setMixin( true );
136 nodeType.setName( name );
138 // for now just don't re-create - but in future if we change the definition, make sure to remove first as an
140 if ( !nodeTypeManager.hasNodeType( name ) )
142 nodeTypeManager.registerNodeType( nodeType, false );
146 public void updateProject( String repositoryId, ProjectMetadata project )
147 throws MetadataRepositoryException
149 updateProject( repositoryId, project.getNamespace(), project.getId() );
152 private void updateProject( String repositoryId, String namespace, String projectId )
153 throws MetadataRepositoryException
155 updateNamespace( repositoryId, namespace );
159 getOrAddProjectNode( repositoryId, namespace, projectId );
161 catch ( RepositoryException e )
163 throw new MetadataRepositoryException( e.getMessage(), e );
167 public void updateArtifact( String repositoryId, String namespace, String projectId, String projectVersion,
168 ArtifactMetadata artifactMeta )
169 throws MetadataRepositoryException
171 updateNamespace( repositoryId, namespace );
175 Node node = getOrAddArtifactNode( repositoryId, namespace, projectId, projectVersion,
176 artifactMeta.getId() );
178 Calendar cal = Calendar.getInstance();
179 cal.setTime( artifactMeta.getFileLastModified() );
180 node.setProperty( JCR_LAST_MODIFIED, cal );
182 cal = Calendar.getInstance();
183 cal.setTime( artifactMeta.getWhenGathered() );
184 node.setProperty( "whenGathered", cal );
186 node.setProperty( "size", artifactMeta.getSize() );
187 node.setProperty( "md5", artifactMeta.getMd5() );
188 node.setProperty( "sha1", artifactMeta.getSha1() );
190 node.setProperty( "version", artifactMeta.getVersion() );
192 for ( MetadataFacet facet : artifactMeta.getFacetList() )
194 if ( node.hasNode( facet.getFacetId() ) )
196 node.getNode( facet.getFacetId() ).remove();
199 // recreate, to ensure properties are removed
200 Node n = node.addNode( facet.getFacetId() );
201 n.addMixin( FACET_NODE_TYPE );
203 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
205 n.setProperty( entry.getKey(), entry.getValue() );
209 catch ( RepositoryException e )
211 throw new MetadataRepositoryException( e.getMessage(), e );
215 public void updateProjectVersion( String repositoryId, String namespace, String projectId,
216 ProjectVersionMetadata versionMetadata )
217 throws MetadataRepositoryException
219 updateProject( repositoryId, namespace, projectId );
223 Node versionNode = getOrAddProjectVersionNode( repositoryId, namespace, projectId,
224 versionMetadata.getId() );
226 versionNode.setProperty( "name", versionMetadata.getName() );
227 versionNode.setProperty( "description", versionMetadata.getDescription() );
228 versionNode.setProperty( "url", versionMetadata.getUrl() );
229 versionNode.setProperty( "incomplete", versionMetadata.isIncomplete() );
231 // FIXME: decide how to treat these in the content repo
232 if ( versionMetadata.getScm() != null )
234 versionNode.setProperty( "scm.connection", versionMetadata.getScm().getConnection() );
235 versionNode.setProperty( "scm.developerConnection", versionMetadata.getScm().getDeveloperConnection() );
236 versionNode.setProperty( "scm.url", versionMetadata.getScm().getUrl() );
238 if ( versionMetadata.getCiManagement() != null )
240 versionNode.setProperty( "ci.system", versionMetadata.getCiManagement().getSystem() );
241 versionNode.setProperty( "ci.url", versionMetadata.getCiManagement().getUrl() );
243 if ( versionMetadata.getIssueManagement() != null )
245 versionNode.setProperty( "issue.system", versionMetadata.getIssueManagement().getSystem() );
246 versionNode.setProperty( "issue.url", versionMetadata.getIssueManagement().getUrl() );
248 if ( versionMetadata.getOrganization() != null )
250 versionNode.setProperty( "org.name", versionMetadata.getOrganization().getName() );
251 versionNode.setProperty( "org.url", versionMetadata.getOrganization().getUrl() );
254 for ( License license : versionMetadata.getLicenses() )
256 versionNode.setProperty( "license." + i + ".name", license.getName() );
257 versionNode.setProperty( "license." + i + ".url", license.getUrl() );
261 for ( MailingList mailingList : versionMetadata.getMailingLists() )
263 versionNode.setProperty( "mailingList." + i + ".archive", mailingList.getMainArchiveUrl() );
264 versionNode.setProperty( "mailingList." + i + ".name", mailingList.getName() );
265 versionNode.setProperty( "mailingList." + i + ".post", mailingList.getPostAddress() );
266 versionNode.setProperty( "mailingList." + i + ".unsubscribe", mailingList.getUnsubscribeAddress() );
267 versionNode.setProperty( "mailingList." + i + ".subscribe", mailingList.getSubscribeAddress() );
268 versionNode.setProperty( "mailingList." + i + ".otherArchives", join(
269 mailingList.getOtherArchives() ) );
273 for ( Dependency dependency : versionMetadata.getDependencies() )
275 versionNode.setProperty( "dependency." + i + ".classifier", dependency.getClassifier() );
276 versionNode.setProperty( "dependency." + i + ".scope", dependency.getScope() );
277 versionNode.setProperty( "dependency." + i + ".systemPath", dependency.getSystemPath() );
278 versionNode.setProperty( "dependency." + i + ".artifactId", dependency.getArtifactId() );
279 versionNode.setProperty( "dependency." + i + ".groupId", dependency.getGroupId() );
280 versionNode.setProperty( "dependency." + i + ".version", dependency.getVersion() );
281 versionNode.setProperty( "dependency." + i + ".type", dependency.getType() );
285 for ( MetadataFacet facet : versionMetadata.getFacetList() )
287 // recreate, to ensure properties are removed
288 if ( versionNode.hasNode( facet.getFacetId() ) )
290 versionNode.getNode( facet.getFacetId() ).remove();
292 Node n = versionNode.addNode( facet.getFacetId() );
293 n.addMixin( FACET_NODE_TYPE );
295 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
297 n.setProperty( entry.getKey(), entry.getValue() );
301 catch ( RepositoryException e )
303 throw new MetadataRepositoryException( e.getMessage(), e );
307 public void updateProjectReference( String repositoryId, String namespace, String projectId, String projectVersion,
308 ProjectVersionReference reference )
309 throws MetadataRepositoryException
311 // not using weak references, since they still need to exist upfront to be referred to
314 Node node = getOrAddRepositoryContentNode( repositoryId );
315 node = JcrUtils.getOrAddNode( node, namespace );
316 node = JcrUtils.getOrAddNode( node, projectId );
317 node = JcrUtils.getOrAddNode( node, projectVersion );
318 node = JcrUtils.getOrAddNode( node, "references" );
319 node = JcrUtils.getOrAddNode( node, reference.getNamespace() );
320 node = JcrUtils.getOrAddNode( node, reference.getProjectId() );
321 node = JcrUtils.getOrAddNode( node, reference.getProjectVersion() );
322 node.setProperty( "type", reference.getReferenceType().toString() );
324 catch ( RepositoryException e )
326 throw new MetadataRepositoryException( e.getMessage(), e );
330 public void updateNamespace( String repositoryId, String namespace )
331 throws MetadataRepositoryException
335 Node node = getOrAddNamespaceNode( repositoryId, namespace );
336 node.setProperty( "namespace", namespace );
338 catch ( RepositoryException e )
340 throw new MetadataRepositoryException( e.getMessage(), e );
344 public List<String> getMetadataFacets( String repositoryId, String facetId )
345 throws MetadataRepositoryException
347 List<String> facets = new ArrayList<String>();
351 // no need to construct node-by-node here, as we'll find in the next instance, the facet names have / and
352 // are paths themselves
353 Node node = session.getRootNode().getNode( getFacetPath( repositoryId, facetId ) );
355 // TODO: this is a bit awkward. Might be better to review the purpose of this function - why is the list of
357 recurse( facets, "", node );
359 catch ( PathNotFoundException e )
361 // ignored - the facet doesn't exist, so return the empty list
363 catch ( RepositoryException e )
365 throw new MetadataRepositoryException( e.getMessage(), e );
370 private void recurse( List<String> facets, String prefix, Node node )
371 throws RepositoryException
373 for ( Node n : JcrUtils.getChildNodes( node ) )
375 String name = prefix + "/" + n.getName();
378 recurse( facets, name, n );
382 // strip leading / first
383 facets.add( name.substring( 1 ) );
388 public MetadataFacet getMetadataFacet( String repositoryId, String facetId, String name )
389 throws MetadataRepositoryException
391 MetadataFacet metadataFacet = null;
394 Node root = session.getRootNode();
395 Node node = root.getNode( getFacetPath( repositoryId, facetId, name ) );
397 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId );
398 if ( metadataFacetFactory != null )
400 metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name );
401 Map<String, String> map = new HashMap<String, String>();
402 for ( Property property : JcrUtils.getProperties( node ) )
404 String p = property.getName();
405 if ( !p.startsWith( "jcr:" ) )
407 map.put( p, property.getString() );
410 metadataFacet.fromProperties( map );
413 catch ( PathNotFoundException e )
415 // ignored - the facet doesn't exist, so return null
417 catch ( RepositoryException e )
419 throw new MetadataRepositoryException( e.getMessage(), e );
421 return metadataFacet;
424 public void addMetadataFacet( String repositoryId, MetadataFacet metadataFacet )
425 throws MetadataRepositoryException
429 Node repo = getOrAddRepositoryNode( repositoryId );
430 Node facets = JcrUtils.getOrAddNode( repo, "facets" );
432 String id = metadataFacet.getFacetId();
433 Node facetNode = JcrUtils.getOrAddNode( facets, id );
435 Node node = getOrAddNodeByPath( facetNode, metadataFacet.getName() );
437 for ( Map.Entry<String, String> entry : metadataFacet.toProperties().entrySet() )
439 node.setProperty( entry.getKey(), entry.getValue() );
442 catch ( RepositoryException e )
444 throw new MetadataRepositoryException( e.getMessage(), e );
448 public void removeMetadataFacets( String repositoryId, String facetId )
449 throws MetadataRepositoryException
453 Node root = session.getRootNode();
454 String path = getFacetPath( repositoryId, facetId );
455 if ( root.hasNode( path ) )
457 root.getNode( path ).remove();
460 catch ( RepositoryException e )
462 throw new MetadataRepositoryException( e.getMessage(), e );
466 public void removeMetadataFacet( String repositoryId, String facetId, String name )
467 throws MetadataRepositoryException
471 Node root = session.getRootNode();
472 String path = getFacetPath( repositoryId, facetId, name );
473 if ( root.hasNode( path ) )
475 Node node = root.getNode( path );
478 // also remove empty container nodes
479 Node parent = node.getParent();
483 while ( !node.hasNodes() );
486 catch ( RepositoryException e )
488 throw new MetadataRepositoryException( e.getMessage(), e );
492 public List<ArtifactMetadata> getArtifactsByDateRange( String repoId, Date startTime, Date endTime )
493 throws MetadataRepositoryException
495 List<ArtifactMetadata> artifacts;
497 String q = getArtifactQuery( repoId );
499 if ( startTime != null )
501 q += " AND [whenGathered] >= $start";
503 if ( endTime != null )
505 q += " AND [whenGathered] <= $end";
510 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
511 ValueFactory valueFactory = session.getValueFactory();
512 if ( startTime != null )
514 query.bindValue( "start", valueFactory.createValue( createCalendar( startTime ) ) );
516 if ( endTime != null )
518 query.bindValue( "end", valueFactory.createValue( createCalendar( endTime ) ) );
520 QueryResult result = query.execute();
522 artifacts = new ArrayList<ArtifactMetadata>();
523 for ( Node n : JcrUtils.getNodes( result ) )
525 artifacts.add( getArtifactFromNode( repoId, n ) );
528 catch ( RepositoryException e )
530 throw new MetadataRepositoryException( e.getMessage(), e );
535 public Collection<String> getRepositories()
536 throws MetadataRepositoryException
538 List<String> repositories;
542 Node root = session.getRootNode();
543 if ( root.hasNode( "repositories" ) )
545 Node node = root.getNode( "repositories" );
547 repositories = new ArrayList<String>();
548 NodeIterator i = node.getNodes();
549 while ( i.hasNext() )
551 Node n = i.nextNode();
552 repositories.add( n.getName() );
557 repositories = Collections.emptyList();
560 catch ( RepositoryException e )
562 throw new MetadataRepositoryException( e.getMessage(), e );
567 public List<ArtifactMetadata> getArtifactsByChecksum( String repositoryId, String checksum )
568 throws MetadataRepositoryException
570 List<ArtifactMetadata> artifacts;
572 String q = getArtifactQuery( repositoryId ) + " AND ([sha1] = $checksum OR [md5] = $checksum)";
576 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
577 ValueFactory valueFactory = session.getValueFactory();
578 query.bindValue( "checksum", valueFactory.createValue( checksum ) );
579 QueryResult result = query.execute();
581 artifacts = new ArrayList<ArtifactMetadata>();
582 for ( Node n : JcrUtils.getNodes( result ) )
584 artifacts.add( getArtifactFromNode( repositoryId, n ) );
587 catch ( RepositoryException e )
589 throw new MetadataRepositoryException( e.getMessage(), e );
594 public void removeArtifact( String repositoryId, String namespace, String projectId, String projectVersion,
596 throws MetadataRepositoryException
600 Node root = session.getRootNode();
601 String path = getArtifactPath( repositoryId, namespace, projectId, projectVersion, id );
602 if ( root.hasNode( path ) )
604 root.getNode( path ).remove();
607 catch ( RepositoryException e )
609 throw new MetadataRepositoryException( e.getMessage(), e );
613 public void removeRepository( String repositoryId )
614 throws MetadataRepositoryException
618 Node root = session.getRootNode();
619 String path = getRepositoryPath( repositoryId );
620 if ( root.hasNode( path ) )
622 root.getNode( path ).remove();
625 catch ( RepositoryException e )
627 throw new MetadataRepositoryException( e.getMessage(), e );
631 public List<ArtifactMetadata> getArtifacts( String repositoryId )
632 throws MetadataRepositoryException
634 List<ArtifactMetadata> artifacts;
636 String q = getArtifactQuery( repositoryId );
640 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
641 QueryResult result = query.execute();
643 artifacts = new ArrayList<ArtifactMetadata>();
644 for ( Node n : JcrUtils.getNodes( result ) )
646 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) )
648 artifacts.add( getArtifactFromNode( repositoryId, n ) );
652 catch ( RepositoryException e )
654 throw new MetadataRepositoryException( e.getMessage(), e );
659 private static String getArtifactQuery( String repositoryId )
661 return "SELECT * FROM [" + ARTIFACT_NODE_TYPE + "] AS artifact WHERE ISDESCENDANTNODE(artifact,'/" +
662 getRepositoryContentPath( repositoryId ) + "')";
665 public ProjectMetadata getProject( String repositoryId, String namespace, String projectId )
666 throws MetadataResolutionException
668 ProjectMetadata metadata = null;
672 Node root = session.getRootNode();
674 // basically just checking it exists
675 String path = getProjectPath( repositoryId, namespace, projectId );
676 if ( root.hasNode( path ) )
678 metadata = new ProjectMetadata();
679 metadata.setId( projectId );
680 metadata.setNamespace( namespace );
683 catch ( RepositoryException e )
685 throw new MetadataResolutionException( e.getMessage(), e );
691 public ProjectVersionMetadata getProjectVersion( String repositoryId, String namespace, String projectId,
692 String projectVersion )
693 throws MetadataResolutionException
695 ProjectVersionMetadata versionMetadata;
699 Node root = session.getRootNode();
701 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
702 if ( !root.hasNode( path ) )
707 Node node = root.getNode( path );
709 versionMetadata = new ProjectVersionMetadata();
710 versionMetadata.setId( projectVersion );
711 versionMetadata.setName( getPropertyString( node, "name" ) );
712 versionMetadata.setDescription( getPropertyString( node, "description" ) );
713 versionMetadata.setUrl( getPropertyString( node, "url" ) );
714 versionMetadata.setIncomplete( node.hasProperty( "incomplete" ) && node.getProperty(
715 "incomplete" ).getBoolean() );
717 // FIXME: decide how to treat these in the content repo
718 String scmConnection = getPropertyString( node, "scm.connection" );
719 String scmDeveloperConnection = getPropertyString( node, "scm.developerConnection" );
720 String scmUrl = getPropertyString( node, "scm.url" );
721 if ( scmConnection != null || scmDeveloperConnection != null || scmUrl != null )
724 scm.setConnection( scmConnection );
725 scm.setDeveloperConnection( scmDeveloperConnection );
726 scm.setUrl( scmUrl );
727 versionMetadata.setScm( scm );
730 String ciSystem = getPropertyString( node, "ci.system" );
731 String ciUrl = getPropertyString( node, "ci.url" );
732 if ( ciSystem != null || ciUrl != null )
734 CiManagement ci = new CiManagement();
735 ci.setSystem( ciSystem );
737 versionMetadata.setCiManagement( ci );
740 String issueSystem = getPropertyString( node, "issue.system" );
741 String issueUrl = getPropertyString( node, "issue.url" );
742 if ( issueSystem != null || issueUrl != null )
744 IssueManagement issueManagement = new IssueManagement();
745 issueManagement.setSystem( issueSystem );
746 issueManagement.setUrl( issueUrl );
747 versionMetadata.setIssueManagement( issueManagement );
750 String orgName = getPropertyString( node, "org.name" );
751 String orgUrl = getPropertyString( node, "org.url" );
752 if ( orgName != null || orgUrl != null )
754 Organization org = new Organization();
755 org.setName( orgName );
756 org.setUrl( orgUrl );
757 versionMetadata.setOrganization( org );
760 boolean done = false;
764 String licenseName = getPropertyString( node, "license." + i + ".name" );
765 String licenseUrl = getPropertyString( node, "license." + i + ".url" );
766 if ( licenseName != null || licenseUrl != null )
768 License license = new License();
769 license.setName( licenseName );
770 license.setUrl( licenseUrl );
771 versionMetadata.addLicense( license );
784 String mailingListName = getPropertyString( node, "mailingList." + i + ".name" );
785 if ( mailingListName != null )
787 MailingList mailingList = new MailingList();
788 mailingList.setName( mailingListName );
789 mailingList.setMainArchiveUrl( getPropertyString( node, "mailingList." + i + ".archive" ) );
790 String n = "mailingList." + i + ".otherArchives";
791 if ( node.hasProperty( n ) )
793 mailingList.setOtherArchives( Arrays.asList( getPropertyString( node, n ).split( "," ) ) );
797 mailingList.setOtherArchives( Collections.<String>emptyList() );
799 mailingList.setPostAddress( getPropertyString( node, "mailingList." + i + ".post" ) );
800 mailingList.setSubscribeAddress( getPropertyString( node, "mailingList." + i + ".subscribe" ) );
801 mailingList.setUnsubscribeAddress( getPropertyString( node, "mailingList." + i + ".unsubscribe" ) );
802 versionMetadata.addMailingList( mailingList );
815 String dependencyArtifactId = getPropertyString( node, "dependency." + i + ".artifactId" );
816 if ( dependencyArtifactId != null )
818 Dependency dependency = new Dependency();
819 dependency.setArtifactId( dependencyArtifactId );
820 dependency.setGroupId( getPropertyString( node, "dependency." + i + ".groupId" ) );
821 dependency.setClassifier( getPropertyString( node, "dependency." + i + ".classifier" ) );
822 dependency.setOptional( Boolean.valueOf( getPropertyString( node,
823 "dependency." + i + ".optional" ) ) );
824 dependency.setScope( getPropertyString( node, "dependency." + i + ".scope" ) );
825 dependency.setSystemPath( getPropertyString( node, "dependency." + i + ".systemPath" ) );
826 dependency.setType( getPropertyString( node, "dependency." + i + ".type" ) );
827 dependency.setVersion( getPropertyString( node, "dependency." + i + ".version" ) );
828 versionMetadata.addDependency( dependency );
837 for ( Node n : JcrUtils.getChildNodes( node ) )
839 if ( n.isNodeType( FACET_NODE_TYPE ) )
841 String name = n.getName();
842 MetadataFacetFactory factory = metadataFacetFactories.get( name );
843 if ( factory == null )
845 log.error( "Attempted to load unknown project version metadata facet: " + name );
849 MetadataFacet facet = factory.createMetadataFacet();
850 Map<String, String> map = new HashMap<String, String>();
851 for ( Property property : JcrUtils.getProperties( n ) )
853 String p = property.getName();
854 if ( !p.startsWith( "jcr:" ) )
856 map.put( p, property.getString() );
859 facet.fromProperties( map );
860 versionMetadata.addFacet( facet );
865 catch ( RepositoryException e )
867 throw new MetadataResolutionException( e.getMessage(), e );
870 return versionMetadata;
873 public Collection<String> getArtifactVersions( String repositoryId, String namespace, String projectId,
874 String projectVersion )
875 throws MetadataResolutionException
877 Set<String> versions = new LinkedHashSet<String>();
881 Node root = session.getRootNode();
883 Node node = root.getNode( getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) );
885 for ( Node n : JcrUtils.getChildNodes( node ) )
887 versions.add( n.getProperty( "version" ).getString() );
890 catch ( PathNotFoundException e )
892 // ignore repo not found for now
894 catch ( RepositoryException e )
896 throw new MetadataResolutionException( e.getMessage(), e );
902 public Collection<ProjectVersionReference> getProjectReferences( String repositoryId, String namespace,
903 String projectId, String projectVersion )
904 throws MetadataResolutionException
906 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
910 Node root = session.getRootNode();
912 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/references";
913 if ( root.hasNode( path ) )
915 Node node = root.getNode( path );
917 NodeIterator i = node.getNodes();
918 while ( i.hasNext() )
920 Node ns = i.nextNode();
922 NodeIterator j = ns.getNodes();
924 while ( j.hasNext() )
926 Node project = j.nextNode();
928 NodeIterator k = project.getNodes();
930 while ( k.hasNext() )
932 Node version = k.nextNode();
934 ProjectVersionReference ref = new ProjectVersionReference();
935 ref.setNamespace( ns.getName() );
936 ref.setProjectId( project.getName() );
937 ref.setProjectVersion( version.getName() );
938 String type = version.getProperty( "type" ).getString();
939 ref.setReferenceType( ProjectVersionReference.ReferenceType.valueOf( type ) );
940 references.add( ref );
946 catch ( RepositoryException e )
948 throw new MetadataResolutionException( e.getMessage(), e );
954 public Collection<String> getRootNamespaces( String repositoryId )
955 throws MetadataResolutionException
957 return getNamespaces( repositoryId, null );
960 public Collection<String> getNamespaces( String repositoryId, String baseNamespace )
961 throws MetadataResolutionException
963 String path = baseNamespace != null
964 ? getNamespacePath( repositoryId, baseNamespace )
965 : getRepositoryContentPath( repositoryId );
967 return getNodeNames( path, NAMESPACE_NODE_TYPE );
970 public Collection<String> getProjects( String repositoryId, String namespace )
971 throws MetadataResolutionException
973 return getNodeNames( getNamespacePath( repositoryId, namespace ), PROJECT_NODE_TYPE );
976 public Collection<String> getProjectVersions( String repositoryId, String namespace, String projectId )
977 throws MetadataResolutionException
979 return getNodeNames( getProjectPath( repositoryId, namespace, projectId ), PROJECT_VERSION_NODE_TYPE );
982 public Collection<ArtifactMetadata> getArtifacts( String repositoryId, String namespace, String projectId,
983 String projectVersion )
984 throws MetadataResolutionException
986 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
990 Node root = session.getRootNode();
991 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
993 if ( root.hasNode( path ) )
995 Node node = root.getNode( path );
997 for ( Node n : JcrUtils.getChildNodes( node ) )
999 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) )
1001 artifacts.add( getArtifactFromNode( repositoryId, n ) );
1006 catch ( RepositoryException e )
1008 throw new MetadataResolutionException( e.getMessage(), e );
1015 throws MetadataRepositoryException
1021 catch ( RepositoryException e )
1023 throw new MetadataRepositoryException( e.getMessage(), e );
1027 public void revert()
1028 throws MetadataRepositoryException
1032 session.refresh( false );
1034 catch ( RepositoryException e )
1036 throw new MetadataRepositoryException( e.getMessage(), e );
1045 private ArtifactMetadata getArtifactFromNode( String repositoryId, Node artifactNode )
1046 throws RepositoryException
1048 String id = artifactNode.getName();
1050 ArtifactMetadata artifact = new ArtifactMetadata();
1051 artifact.setId( id );
1052 artifact.setRepositoryId( repositoryId );
1054 Node projectVersionNode = artifactNode.getParent();
1055 Node projectNode = projectVersionNode.getParent();
1056 Node namespaceNode = projectNode.getParent();
1058 artifact.setNamespace( namespaceNode.getProperty( "namespace" ).getString() );
1059 artifact.setProject( projectNode.getName() );
1060 artifact.setProjectVersion( projectVersionNode.getName() );
1061 artifact.setVersion( artifactNode.hasProperty( "version" )
1062 ? artifactNode.getProperty( "version" ).getString()
1063 : projectVersionNode.getName() );
1065 if ( artifactNode.hasProperty( JCR_LAST_MODIFIED ) )
1067 artifact.setFileLastModified( artifactNode.getProperty( JCR_LAST_MODIFIED ).getDate().getTimeInMillis() );
1070 if ( artifactNode.hasProperty( "whenGathered" ) )
1072 artifact.setWhenGathered( artifactNode.getProperty( "whenGathered" ).getDate().getTime() );
1075 if ( artifactNode.hasProperty( "size" ) )
1077 artifact.setSize( artifactNode.getProperty( "size" ).getLong() );
1080 if ( artifactNode.hasProperty( "md5" ) )
1082 artifact.setMd5( artifactNode.getProperty( "md5" ).getString() );
1085 if ( artifactNode.hasProperty( "sha1" ) )
1087 artifact.setSha1( artifactNode.getProperty( "sha1" ).getString() );
1090 for ( Node n : JcrUtils.getChildNodes( artifactNode ) )
1092 if ( n.isNodeType( FACET_NODE_TYPE ) )
1094 String name = n.getName();
1095 MetadataFacetFactory factory = metadataFacetFactories.get( name );
1096 if ( factory == null )
1098 log.error( "Attempted to load unknown project version metadata facet: " + name );
1102 MetadataFacet facet = factory.createMetadataFacet();
1103 Map<String, String> map = new HashMap<String, String>();
1104 for ( Property p : JcrUtils.getProperties( n ) )
1106 String property = p.getName();
1107 if ( !property.startsWith( "jcr:" ) )
1109 map.put( property, p.getString() );
1112 facet.fromProperties( map );
1113 artifact.addFacet( facet );
1120 private static String getPropertyString( Node node, String name )
1121 throws RepositoryException
1123 return node.hasProperty( name ) ? node.getProperty( name ).getString() : null;
1126 private Collection<String> getNodeNames( String path, String nodeType )
1127 throws MetadataResolutionException
1129 List<String> names = new ArrayList<String>();
1133 Node root = session.getRootNode();
1135 Node nodeAtPath = root.getNode( path );
1137 for ( Node node : JcrUtils.getChildNodes( nodeAtPath ) )
1139 if ( node.isNodeType( nodeType ) )
1141 names.add( node.getName() );
1145 catch ( PathNotFoundException e )
1147 // ignore repo not found for now
1149 catch ( RepositoryException e )
1151 throw new MetadataResolutionException( e.getMessage(), e );
1157 private static String getRepositoryPath( String repositoryId )
1159 return "repositories/" + repositoryId;
1162 private static String getRepositoryContentPath( String repositoryId )
1164 return getRepositoryPath( repositoryId ) + "/content/";
1167 private static String getFacetPath( String repositoryId, String facetId )
1169 return getRepositoryPath( repositoryId ) + "/facets/" + facetId;
1172 private static String getNamespacePath( String repositoryId, String namespace )
1174 return getRepositoryContentPath( repositoryId ) + namespace.replace( '.', '/' );
1177 private static String getProjectPath( String repositoryId, String namespace, String projectId )
1179 return getNamespacePath( repositoryId, namespace ) + "/" + projectId;
1182 private static String getProjectVersionPath( String repositoryId, String namespace, String projectId,
1183 String projectVersion )
1185 return getProjectPath( repositoryId, namespace, projectId ) + "/" + projectVersion;
1188 private static String getArtifactPath( String repositoryId, String namespace, String projectId,
1189 String projectVersion, String id )
1191 return getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/" + id;
1194 private Node getOrAddNodeByPath( Node baseNode, String name )
1195 throws RepositoryException
1197 return getOrAddNodeByPath( baseNode, name, null );
1200 private Node getOrAddNodeByPath( Node baseNode, String name, String nodeType )
1201 throws RepositoryException
1203 Node node = baseNode;
1204 for ( String n : name.split( "/" ) )
1206 node = JcrUtils.getOrAddNode( node, n );
1207 if ( nodeType != null )
1209 node.addMixin( nodeType );
1215 private static String getFacetPath( String repositoryId, String facetId, String name )
1217 return getFacetPath( repositoryId, facetId ) + "/" + name;
1220 private Node getOrAddRepositoryNode( String repositoryId )
1221 throws RepositoryException
1223 Node root = session.getRootNode();
1224 Node node = JcrUtils.getOrAddNode( root, "repositories" );
1225 node = JcrUtils.getOrAddNode( node, repositoryId );
1229 private Node getOrAddRepositoryContentNode( String repositoryId )
1230 throws RepositoryException
1232 Node node = getOrAddRepositoryNode( repositoryId );
1233 return JcrUtils.getOrAddNode( node, "content" );
1236 private Node getOrAddNamespaceNode( String repositoryId, String namespace )
1237 throws RepositoryException
1239 Node repo = getOrAddRepositoryContentNode( repositoryId );
1240 return getOrAddNodeByPath( repo, namespace.replace( '.', '/' ), NAMESPACE_NODE_TYPE );
1243 private Node getOrAddProjectNode( String repositoryId, String namespace, String projectId )
1244 throws RepositoryException
1246 Node namespaceNode = getOrAddNamespaceNode( repositoryId, namespace );
1247 Node node = JcrUtils.getOrAddNode( namespaceNode, projectId );
1248 node.addMixin( PROJECT_NODE_TYPE );
1252 private Node getOrAddProjectVersionNode( String repositoryId, String namespace, String projectId,
1253 String projectVersion )
1254 throws RepositoryException
1256 Node projectNode = getOrAddProjectNode( repositoryId, namespace, projectId );
1257 Node node = JcrUtils.getOrAddNode( projectNode, projectVersion );
1258 node.addMixin( PROJECT_VERSION_NODE_TYPE );
1262 private Node getOrAddArtifactNode( String repositoryId, String namespace, String projectId, String projectVersion,
1264 throws RepositoryException
1266 Node versionNode = getOrAddProjectVersionNode( repositoryId, namespace, projectId, projectVersion );
1267 Node node = JcrUtils.getOrAddNode( versionNode, id );
1268 node.addMixin( ARTIFACT_NODE_TYPE );
1272 private static Calendar createCalendar( Date time )
1274 Calendar cal = Calendar.getInstance();
1275 cal.setTime( time );
1279 private String join( Collection<String> ids )
1281 if ( ids != null && !ids.isEmpty() )
1283 StringBuilder s = new StringBuilder();
1284 for ( String id : ids )
1289 return s.substring( 0, s.length() - 1 );
1294 public Session getJcrSession()