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 ARTIFACT_NODE_TYPE = "archiva:artifact";
80 static final String FACET_NODE_TYPE = "archiva:facet";
82 private final Map<String, MetadataFacetFactory> metadataFacetFactories;
84 private static final Logger log = LoggerFactory.getLogger( JcrMetadataRepository.class );
86 private Repository repository;
88 private Session session;
90 public JcrMetadataRepository( Map<String, MetadataFacetFactory> metadataFacetFactories, Repository repository )
91 throws RepositoryException
93 this.metadataFacetFactories = metadataFacetFactories;
94 this.repository = repository;
96 session = repository.login( new SimpleCredentials( "username", "password".toCharArray() ) );
99 static void initialize( Session session )
100 throws RepositoryException
102 // TODO: consider using namespaces for facets instead of the current approach:
103 // (if used, check if actually called by normal injection)
104 // for ( String facetId : metadataFacetFactories.keySet() )
106 // session.getWorkspace().getNamespaceRegistry().registerNamespace( facetId, facetId );
109 Workspace workspace = session.getWorkspace();
110 NamespaceRegistry registry = workspace.getNamespaceRegistry();
112 if ( !Arrays.asList( registry.getPrefixes() ).contains( "archiva" ) )
114 registry.registerNamespace( "archiva", "http://archiva.apache.org/jcr/" );
117 NodeTypeManager nodeTypeManager = workspace.getNodeTypeManager();
118 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.ARTIFACT_NODE_TYPE );
119 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.FACET_NODE_TYPE );
122 private static void registerMixinNodeType( NodeTypeManager nodeTypeManager, String name )
123 throws RepositoryException
125 NodeTypeTemplate nodeType = nodeTypeManager.createNodeTypeTemplate();
126 nodeType.setMixin( true );
127 nodeType.setName( name );
129 // for now just don't re-create - but in future if we change the definition, make sure to remove first as an
131 if ( !nodeTypeManager.hasNodeType( name ) )
133 nodeTypeManager.registerNodeType( nodeType, false );
137 public void updateProject( String repositoryId, ProjectMetadata project )
138 throws MetadataRepositoryException
140 updateProject( repositoryId, project.getNamespace(), project.getId() );
143 private void updateProject( String repositoryId, String namespace, String projectId )
144 throws MetadataRepositoryException
146 updateNamespace( repositoryId, namespace );
150 getOrAddProjectNode( repositoryId, namespace, projectId );
152 catch ( RepositoryException e )
154 throw new MetadataRepositoryException( e.getMessage(), e );
158 public void updateArtifact( String repositoryId, String namespace, String projectId, String projectVersion,
159 ArtifactMetadata artifactMeta )
160 throws MetadataRepositoryException
162 updateNamespace( repositoryId, namespace );
166 Node node = getOrAddArtifactNode( repositoryId, namespace, projectId, projectVersion,
167 artifactMeta.getId() );
169 Calendar cal = Calendar.getInstance();
170 cal.setTime( artifactMeta.getFileLastModified() );
171 node.setProperty( JCR_LAST_MODIFIED, cal );
173 cal = Calendar.getInstance();
174 cal.setTime( artifactMeta.getWhenGathered() );
175 node.setProperty( "whenGathered", cal );
177 node.setProperty( "size", artifactMeta.getSize() );
178 node.setProperty( "md5", artifactMeta.getMd5() );
179 node.setProperty( "sha1", artifactMeta.getSha1() );
181 node.setProperty( "version", artifactMeta.getVersion() );
183 for ( MetadataFacet facet : artifactMeta.getFacetList() )
185 if ( node.hasNode( facet.getFacetId() ) )
187 node.getNode( facet.getFacetId() ).remove();
190 // recreate, to ensure properties are removed
191 Node n = node.addNode( facet.getFacetId() );
192 n.addMixin( FACET_NODE_TYPE );
194 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
196 n.setProperty( entry.getKey(), entry.getValue() );
199 // FIXME: need some context around this so it can be done only when needed
202 catch ( RepositoryException e )
204 throw new MetadataRepositoryException( e.getMessage(), e );
208 public void updateProjectVersion( String repositoryId, String namespace, String projectId,
209 ProjectVersionMetadata versionMetadata )
210 throws MetadataRepositoryException
212 updateProject( repositoryId, namespace, projectId );
216 Node versionNode = getOrAddProjectVersionNode( repositoryId, namespace, projectId,
217 versionMetadata.getId() );
219 versionNode.setProperty( "name", versionMetadata.getName() );
220 versionNode.setProperty( "description", versionMetadata.getDescription() );
221 versionNode.setProperty( "url", versionMetadata.getUrl() );
222 versionNode.setProperty( "incomplete", versionMetadata.isIncomplete() );
224 // FIXME: decide how to treat these in the content repo
225 if ( versionMetadata.getScm() != null )
227 versionNode.setProperty( "scm.connection", versionMetadata.getScm().getConnection() );
228 versionNode.setProperty( "scm.developerConnection", versionMetadata.getScm().getDeveloperConnection() );
229 versionNode.setProperty( "scm.url", versionMetadata.getScm().getUrl() );
231 if ( versionMetadata.getCiManagement() != null )
233 versionNode.setProperty( "ci.system", versionMetadata.getCiManagement().getSystem() );
234 versionNode.setProperty( "ci.url", versionMetadata.getCiManagement().getUrl() );
236 if ( versionMetadata.getIssueManagement() != null )
238 versionNode.setProperty( "issue.system", versionMetadata.getIssueManagement().getSystem() );
239 versionNode.setProperty( "issue.url", versionMetadata.getIssueManagement().getUrl() );
241 if ( versionMetadata.getOrganization() != null )
243 versionNode.setProperty( "org.name", versionMetadata.getOrganization().getName() );
244 versionNode.setProperty( "org.url", versionMetadata.getOrganization().getUrl() );
247 for ( License license : versionMetadata.getLicenses() )
249 versionNode.setProperty( "license." + i + ".name", license.getName() );
250 versionNode.setProperty( "license." + i + ".url", license.getUrl() );
254 for ( MailingList mailingList : versionMetadata.getMailingLists() )
256 versionNode.setProperty( "mailingList." + i + ".archive", mailingList.getMainArchiveUrl() );
257 versionNode.setProperty( "mailingList." + i + ".name", mailingList.getName() );
258 versionNode.setProperty( "mailingList." + i + ".post", mailingList.getPostAddress() );
259 versionNode.setProperty( "mailingList." + i + ".unsubscribe", mailingList.getUnsubscribeAddress() );
260 versionNode.setProperty( "mailingList." + i + ".subscribe", mailingList.getSubscribeAddress() );
261 versionNode.setProperty( "mailingList." + i + ".otherArchives", join(
262 mailingList.getOtherArchives() ) );
266 for ( Dependency dependency : versionMetadata.getDependencies() )
268 versionNode.setProperty( "dependency." + i + ".classifier", dependency.getClassifier() );
269 versionNode.setProperty( "dependency." + i + ".scope", dependency.getScope() );
270 versionNode.setProperty( "dependency." + i + ".systemPath", dependency.getSystemPath() );
271 versionNode.setProperty( "dependency." + i + ".artifactId", dependency.getArtifactId() );
272 versionNode.setProperty( "dependency." + i + ".groupId", dependency.getGroupId() );
273 versionNode.setProperty( "dependency." + i + ".version", dependency.getVersion() );
274 versionNode.setProperty( "dependency." + i + ".type", dependency.getType() );
278 for ( MetadataFacet facet : versionMetadata.getFacetList() )
280 // recreate, to ensure properties are removed
281 if ( versionNode.hasNode( facet.getFacetId() ) )
283 versionNode.getNode( facet.getFacetId() ).remove();
285 Node n = versionNode.addNode( facet.getFacetId() );
286 n.addMixin( FACET_NODE_TYPE );
288 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
290 n.setProperty( entry.getKey(), entry.getValue() );
294 catch ( RepositoryException e )
296 throw new MetadataRepositoryException( e.getMessage(), e );
300 public void updateProjectReference( String repositoryId, String namespace, String projectId, String projectVersion,
301 ProjectVersionReference reference )
302 throws MetadataRepositoryException
304 // not using weak references, since they still need to exist upfront to be referred to
307 Node node = getOrAddRepositoryContentNode( repositoryId );
308 node = JcrUtils.getOrAddNode( node, namespace );
309 node = JcrUtils.getOrAddNode( node, projectId );
310 node = JcrUtils.getOrAddNode( node, projectVersion );
311 node = JcrUtils.getOrAddNode( node, "references" );
312 node = JcrUtils.getOrAddNode( node, reference.getNamespace() );
313 node = JcrUtils.getOrAddNode( node, reference.getProjectId() );
314 node = JcrUtils.getOrAddNode( node, reference.getProjectVersion() );
315 node.setProperty( "type", reference.getReferenceType().toString() );
317 catch ( RepositoryException e )
319 throw new MetadataRepositoryException( e.getMessage(), e );
323 public void updateNamespace( String repositoryId, String namespace )
324 throws MetadataRepositoryException
328 Node node = getOrAddNamespaceNode( repositoryId, namespace );
329 node.setProperty( "namespace", namespace );
331 catch ( RepositoryException e )
333 throw new MetadataRepositoryException( e.getMessage(), e );
337 public List<String> getMetadataFacets( String repositoryId, String facetId )
338 throws MetadataRepositoryException
340 List<String> facets = new ArrayList<String>();
344 // no need to construct node-by-node here, as we'll find in the next instance, the facet names have / and
345 // are paths themselves
346 Node node = session.getRootNode().getNode( getFacetPath( repositoryId, facetId ) );
348 // TODO: this is a bit awkward. Might be better to review the purpose of this function - why is the list of
350 recurse( facets, "", node );
352 catch ( PathNotFoundException e )
354 // ignored - the facet doesn't exist, so return the empty list
356 catch ( RepositoryException e )
358 throw new MetadataRepositoryException( e.getMessage(), e );
363 private void recurse( List<String> facets, String prefix, Node node )
364 throws RepositoryException
366 for ( Node n : JcrUtils.getChildNodes( node ) )
368 String name = prefix + "/" + n.getName();
371 recurse( facets, name, n );
375 // strip leading / first
376 facets.add( name.substring( 1 ) );
381 public MetadataFacet getMetadataFacet( String repositoryId, String facetId, String name )
382 throws MetadataRepositoryException
384 MetadataFacet metadataFacet = null;
387 Node root = session.getRootNode();
388 Node node = root.getNode( getFacetPath( repositoryId, facetId, name ) );
390 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId );
391 if ( metadataFacetFactory != null )
393 metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name );
394 Map<String, String> map = new HashMap<String, String>();
395 for ( Property property : JcrUtils.getProperties( node ) )
397 String p = property.getName();
398 if ( !p.startsWith( "jcr:" ) )
400 map.put( p, property.getString() );
403 metadataFacet.fromProperties( map );
406 catch ( PathNotFoundException e )
408 // ignored - the facet doesn't exist, so return null
410 catch ( RepositoryException e )
412 throw new MetadataRepositoryException( e.getMessage(), e );
414 return metadataFacet;
417 public void addMetadataFacet( String repositoryId, MetadataFacet metadataFacet )
418 throws MetadataRepositoryException
422 Node repo = getOrAddRepositoryNode( repositoryId );
423 Node facets = JcrUtils.getOrAddNode( repo, "facets" );
425 String id = metadataFacet.getFacetId();
426 Node facetNode = JcrUtils.getOrAddNode( facets, id );
428 Node node = getOrAddNodeByPath( facetNode, metadataFacet.getName() );
430 for ( Map.Entry<String, String> entry : metadataFacet.toProperties().entrySet() )
432 node.setProperty( entry.getKey(), entry.getValue() );
435 catch ( RepositoryException e )
437 throw new MetadataRepositoryException( e.getMessage(), e );
441 public void removeMetadataFacets( String repositoryId, String facetId )
442 throws MetadataRepositoryException
446 Node root = session.getRootNode();
447 String path = getFacetPath( repositoryId, facetId );
448 if ( root.hasNode( path ) )
450 root.getNode( path ).remove();
453 catch ( RepositoryException e )
455 throw new MetadataRepositoryException( e.getMessage(), e );
459 public void removeMetadataFacet( String repositoryId, String facetId, String name )
460 throws MetadataRepositoryException
464 Node root = session.getRootNode();
465 String path = getFacetPath( repositoryId, facetId, name );
466 if ( root.hasNode( path ) )
468 Node node = root.getNode( path );
471 // also remove empty container nodes
472 Node parent = node.getParent();
476 while ( !node.hasNodes() );
479 catch ( RepositoryException e )
481 throw new MetadataRepositoryException( e.getMessage(), e );
485 public List<ArtifactMetadata> getArtifactsByDateRange( String repoId, Date startTime, Date endTime )
486 throws MetadataRepositoryException
488 List<ArtifactMetadata> artifacts;
490 String q = getArtifactQuery( repoId );
492 if ( startTime != null )
494 q += " AND [whenGathered] >= $start";
496 if ( endTime != null )
498 q += " AND [whenGathered] <= $end";
503 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
504 ValueFactory valueFactory = session.getValueFactory();
505 if ( startTime != null )
507 query.bindValue( "start", valueFactory.createValue( createCalendar( startTime ) ) );
509 if ( endTime != null )
511 query.bindValue( "end", valueFactory.createValue( createCalendar( endTime ) ) );
513 QueryResult result = query.execute();
515 artifacts = new ArrayList<ArtifactMetadata>();
516 for ( Node n : JcrUtils.getNodes( result ) )
518 artifacts.add( getArtifactFromNode( repoId, n ) );
521 catch ( RepositoryException e )
523 throw new MetadataRepositoryException( e.getMessage(), e );
528 public Collection<String> getRepositories()
529 throws MetadataRepositoryException
531 List<String> repositories;
535 Node root = session.getRootNode();
536 if ( root.hasNode( "repositories" ) )
538 Node node = root.getNode( "repositories" );
540 repositories = new ArrayList<String>();
541 NodeIterator i = node.getNodes();
542 while ( i.hasNext() )
544 Node n = i.nextNode();
545 repositories.add( n.getName() );
550 repositories = Collections.emptyList();
553 catch ( RepositoryException e )
555 throw new MetadataRepositoryException( e.getMessage(), e );
560 public List<ArtifactMetadata> getArtifactsByChecksum( String repositoryId, String checksum )
561 throws MetadataRepositoryException
563 List<ArtifactMetadata> artifacts;
565 String q = getArtifactQuery( repositoryId ) + " AND ([sha1] = $checksum OR [md5] = $checksum)";
569 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
570 ValueFactory valueFactory = session.getValueFactory();
571 query.bindValue( "checksum", valueFactory.createValue( checksum ) );
572 QueryResult result = query.execute();
574 artifacts = new ArrayList<ArtifactMetadata>();
575 for ( Node n : JcrUtils.getNodes( result ) )
577 artifacts.add( getArtifactFromNode( repositoryId, n ) );
580 catch ( RepositoryException e )
582 throw new MetadataRepositoryException( e.getMessage(), e );
587 public void removeArtifact( String repositoryId, String namespace, String projectId, String projectVersion,
589 throws MetadataRepositoryException
593 Node root = session.getRootNode();
594 String path = getArtifactPath( repositoryId, namespace, projectId, projectVersion, id );
595 if ( root.hasNode( path ) )
597 root.getNode( path ).remove();
600 catch ( RepositoryException e )
602 throw new MetadataRepositoryException( e.getMessage(), e );
606 public void removeRepository( String repositoryId )
607 throws MetadataRepositoryException
611 Node root = session.getRootNode();
612 String path = getRepositoryPath( repositoryId );
613 if ( root.hasNode( path ) )
615 root.getNode( path ).remove();
618 catch ( RepositoryException e )
620 throw new MetadataRepositoryException( e.getMessage(), e );
624 public List<ArtifactMetadata> getArtifacts( String repositoryId )
625 throws MetadataRepositoryException
627 List<ArtifactMetadata> artifacts;
629 String q = getArtifactQuery( repositoryId );
633 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
634 QueryResult result = query.execute();
636 artifacts = new ArrayList<ArtifactMetadata>();
637 for ( Node n : JcrUtils.getNodes( result ) )
639 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) )
641 artifacts.add( getArtifactFromNode( repositoryId, n ) );
645 catch ( RepositoryException e )
647 throw new MetadataRepositoryException( e.getMessage(), e );
652 private static String getArtifactQuery( String repositoryId )
654 return "SELECT * FROM [" + ARTIFACT_NODE_TYPE + "] AS artifact WHERE ISDESCENDANTNODE(artifact,'/" +
655 getRepositoryContentPath( repositoryId ) + "')";
658 public ProjectMetadata getProject( String repositoryId, String namespace, String projectId )
659 throws MetadataResolutionException
661 ProjectMetadata metadata = null;
665 Node root = session.getRootNode();
667 // basically just checking it exists
668 String path = getProjectPath( repositoryId, namespace, projectId );
669 if ( root.hasNode( path ) )
671 metadata = new ProjectMetadata();
672 metadata.setId( projectId );
673 metadata.setNamespace( namespace );
676 catch ( RepositoryException e )
678 throw new MetadataResolutionException( e.getMessage(), e );
684 public ProjectVersionMetadata getProjectVersion( String repositoryId, String namespace, String projectId,
685 String projectVersion )
686 throws MetadataResolutionException
688 ProjectVersionMetadata versionMetadata;
692 Node root = session.getRootNode();
694 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
695 if ( !root.hasNode( path ) )
700 Node node = root.getNode( path );
702 versionMetadata = new ProjectVersionMetadata();
703 versionMetadata.setId( projectVersion );
704 versionMetadata.setName( getPropertyString( node, "name" ) );
705 versionMetadata.setDescription( getPropertyString( node, "description" ) );
706 versionMetadata.setUrl( getPropertyString( node, "url" ) );
707 versionMetadata.setIncomplete( node.hasProperty( "incomplete" ) && node.getProperty(
708 "incomplete" ).getBoolean() );
710 // FIXME: decide how to treat these in the content repo
711 String scmConnection = getPropertyString( node, "scm.connection" );
712 String scmDeveloperConnection = getPropertyString( node, "scm.developerConnection" );
713 String scmUrl = getPropertyString( node, "scm.url" );
714 if ( scmConnection != null || scmDeveloperConnection != null || scmUrl != null )
717 scm.setConnection( scmConnection );
718 scm.setDeveloperConnection( scmDeveloperConnection );
719 scm.setUrl( scmUrl );
720 versionMetadata.setScm( scm );
723 String ciSystem = getPropertyString( node, "ci.system" );
724 String ciUrl = getPropertyString( node, "ci.url" );
725 if ( ciSystem != null || ciUrl != null )
727 CiManagement ci = new CiManagement();
728 ci.setSystem( ciSystem );
730 versionMetadata.setCiManagement( ci );
733 String issueSystem = getPropertyString( node, "issue.system" );
734 String issueUrl = getPropertyString( node, "issue.url" );
735 if ( issueSystem != null || issueUrl != null )
737 IssueManagement issueManagement = new IssueManagement();
738 issueManagement.setSystem( issueSystem );
739 issueManagement.setUrl( issueUrl );
740 versionMetadata.setIssueManagement( issueManagement );
743 String orgName = getPropertyString( node, "org.name" );
744 String orgUrl = getPropertyString( node, "org.url" );
745 if ( orgName != null || orgUrl != null )
747 Organization org = new Organization();
748 org.setName( orgName );
749 org.setUrl( orgUrl );
750 versionMetadata.setOrganization( org );
753 boolean done = false;
757 String licenseName = getPropertyString( node, "license." + i + ".name" );
758 String licenseUrl = getPropertyString( node, "license." + i + ".url" );
759 if ( licenseName != null || licenseUrl != null )
761 License license = new License();
762 license.setName( licenseName );
763 license.setUrl( licenseUrl );
764 versionMetadata.addLicense( license );
777 String mailingListName = getPropertyString( node, "mailingList." + i + ".name" );
778 if ( mailingListName != null )
780 MailingList mailingList = new MailingList();
781 mailingList.setName( mailingListName );
782 mailingList.setMainArchiveUrl( getPropertyString( node, "mailingList." + i + ".archive" ) );
783 String n = "mailingList." + i + ".otherArchives";
784 if ( node.hasProperty( n ) )
786 mailingList.setOtherArchives( Arrays.asList( getPropertyString( node, n ).split( "," ) ) );
790 mailingList.setOtherArchives( Collections.<String>emptyList() );
792 mailingList.setPostAddress( getPropertyString( node, "mailingList." + i + ".post" ) );
793 mailingList.setSubscribeAddress( getPropertyString( node, "mailingList." + i + ".subscribe" ) );
794 mailingList.setUnsubscribeAddress( getPropertyString( node, "mailingList." + i + ".unsubscribe" ) );
795 versionMetadata.addMailingList( mailingList );
808 String dependencyArtifactId = getPropertyString( node, "dependency." + i + ".artifactId" );
809 if ( dependencyArtifactId != null )
811 Dependency dependency = new Dependency();
812 dependency.setArtifactId( dependencyArtifactId );
813 dependency.setGroupId( getPropertyString( node, "dependency." + i + ".groupId" ) );
814 dependency.setClassifier( getPropertyString( node, "dependency." + i + ".classifier" ) );
815 dependency.setOptional( Boolean.valueOf( getPropertyString( node,
816 "dependency." + i + ".optional" ) ) );
817 dependency.setScope( getPropertyString( node, "dependency." + i + ".scope" ) );
818 dependency.setSystemPath( getPropertyString( node, "dependency." + i + ".systemPath" ) );
819 dependency.setType( getPropertyString( node, "dependency." + i + ".type" ) );
820 dependency.setVersion( getPropertyString( node, "dependency." + i + ".version" ) );
821 versionMetadata.addDependency( dependency );
830 for ( Node n : JcrUtils.getChildNodes( node ) )
832 if ( n.isNodeType( FACET_NODE_TYPE ) )
834 String name = n.getName();
835 MetadataFacetFactory factory = metadataFacetFactories.get( name );
836 if ( factory == null )
838 log.error( "Attempted to load unknown project version metadata facet: " + name );
842 MetadataFacet facet = factory.createMetadataFacet();
843 Map<String, String> map = new HashMap<String, String>();
844 for ( Property property : JcrUtils.getProperties( n ) )
846 String p = property.getName();
847 if ( !p.startsWith( "jcr:" ) )
849 map.put( p, property.getString() );
852 facet.fromProperties( map );
853 versionMetadata.addFacet( facet );
858 catch ( RepositoryException e )
860 throw new MetadataResolutionException( e.getMessage(), e );
863 return versionMetadata;
866 public Collection<String> getArtifactVersions( String repositoryId, String namespace, String projectId,
867 String projectVersion )
868 throws MetadataResolutionException
870 Set<String> versions = new LinkedHashSet<String>();
874 Node root = session.getRootNode();
876 Node node = root.getNode( getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) );
878 for ( Node n : JcrUtils.getChildNodes( node ) )
880 versions.add( n.getProperty( "version" ).getString() );
883 catch ( PathNotFoundException e )
885 // ignore repo not found for now
887 catch ( RepositoryException e )
889 throw new MetadataResolutionException( e.getMessage(), e );
895 public Collection<ProjectVersionReference> getProjectReferences( String repositoryId, String namespace,
896 String projectId, String projectVersion )
897 throws MetadataResolutionException
899 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
903 Node root = session.getRootNode();
905 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/references";
906 if ( root.hasNode( path ) )
908 Node node = root.getNode( path );
910 NodeIterator i = node.getNodes();
911 while ( i.hasNext() )
913 Node ns = i.nextNode();
915 NodeIterator j = ns.getNodes();
917 while ( j.hasNext() )
919 Node project = j.nextNode();
921 NodeIterator k = project.getNodes();
923 while ( k.hasNext() )
925 Node version = k.nextNode();
927 ProjectVersionReference ref = new ProjectVersionReference();
928 ref.setNamespace( ns.getName() );
929 ref.setProjectId( project.getName() );
930 ref.setProjectVersion( version.getName() );
931 String type = version.getProperty( "type" ).getString();
932 ref.setReferenceType( ProjectVersionReference.ReferenceType.valueOf( type ) );
933 references.add( ref );
939 catch ( RepositoryException e )
941 throw new MetadataResolutionException( e.getMessage(), e );
947 public Collection<String> getRootNamespaces( String repositoryId )
948 throws MetadataResolutionException
950 return getNamespaces( repositoryId, null );
953 public Collection<String> getNamespaces( String repositoryId, String baseNamespace )
954 throws MetadataResolutionException
956 String path = baseNamespace != null
957 ? getNamespacePath( repositoryId, baseNamespace )
958 : getRepositoryContentPath( repositoryId );
960 return getNodeNames( path );
963 public Collection<String> getProjects( String repositoryId, String namespace )
964 throws MetadataResolutionException
966 return getNodeNames( getNamespacePath( repositoryId, namespace ) );
969 public Collection<String> getProjectVersions( String repositoryId, String namespace, String projectId )
970 throws MetadataResolutionException
972 return getNodeNames( getProjectPath( repositoryId, namespace, projectId ) );
975 public Collection<ArtifactMetadata> getArtifacts( String repositoryId, String namespace, String projectId,
976 String projectVersion )
977 throws MetadataResolutionException
979 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
983 Node root = session.getRootNode();
984 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
986 if ( root.hasNode( path ) )
988 Node node = root.getNode( path );
990 for ( Node n : JcrUtils.getChildNodes( node ) )
992 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) )
994 artifacts.add( getArtifactFromNode( repositoryId, n ) );
999 catch ( RepositoryException e )
1001 throw new MetadataResolutionException( e.getMessage(), e );
1008 throws MetadataRepositoryException
1014 catch ( RepositoryException e )
1016 throw new MetadataRepositoryException( e.getMessage(), e );
1020 public void revert()
1021 throws MetadataRepositoryException
1025 session.refresh( false );
1027 catch ( RepositoryException e )
1029 throw new MetadataRepositoryException( e.getMessage(), e );
1038 private ArtifactMetadata getArtifactFromNode( String repositoryId, Node artifactNode )
1039 throws RepositoryException
1041 String id = artifactNode.getName();
1043 ArtifactMetadata artifact = new ArtifactMetadata();
1044 artifact.setId( id );
1045 artifact.setRepositoryId( repositoryId );
1047 Node projectVersionNode = artifactNode.getParent();
1048 Node projectNode = projectVersionNode.getParent();
1049 Node namespaceNode = projectNode.getParent();
1051 artifact.setNamespace( namespaceNode.getProperty( "namespace" ).getString() );
1052 artifact.setProject( projectNode.getName() );
1053 artifact.setProjectVersion( projectVersionNode.getName() );
1054 artifact.setVersion( artifactNode.hasProperty( "version" )
1055 ? artifactNode.getProperty( "version" ).getString()
1056 : projectVersionNode.getName() );
1058 if ( artifactNode.hasProperty( JCR_LAST_MODIFIED ) )
1060 artifact.setFileLastModified( artifactNode.getProperty( JCR_LAST_MODIFIED ).getDate().getTimeInMillis() );
1063 if ( artifactNode.hasProperty( "whenGathered" ) )
1065 artifact.setWhenGathered( artifactNode.getProperty( "whenGathered" ).getDate().getTime() );
1068 if ( artifactNode.hasProperty( "size" ) )
1070 artifact.setSize( artifactNode.getProperty( "size" ).getLong() );
1073 if ( artifactNode.hasProperty( "md5" ) )
1075 artifact.setMd5( artifactNode.getProperty( "md5" ).getString() );
1078 if ( artifactNode.hasProperty( "sha1" ) )
1080 artifact.setSha1( artifactNode.getProperty( "sha1" ).getString() );
1083 for ( Node n : JcrUtils.getChildNodes( artifactNode ) )
1085 if ( n.isNodeType( FACET_NODE_TYPE ) )
1087 String name = n.getName();
1088 MetadataFacetFactory factory = metadataFacetFactories.get( name );
1089 if ( factory == null )
1091 log.error( "Attempted to load unknown project version metadata facet: " + name );
1095 MetadataFacet facet = factory.createMetadataFacet();
1096 Map<String, String> map = new HashMap<String, String>();
1097 for ( Property p : JcrUtils.getProperties( n ) )
1099 String property = p.getName();
1100 if ( !property.startsWith( "jcr:" ) )
1102 map.put( property, p.getString() );
1105 facet.fromProperties( map );
1106 artifact.addFacet( facet );
1113 private static String getPropertyString( Node node, String name )
1114 throws RepositoryException
1116 return node.hasProperty( name ) ? node.getProperty( name ).getString() : null;
1119 private Collection<String> getNodeNames( String path )
1120 throws MetadataResolutionException
1122 List<String> names = new ArrayList<String>();
1126 Node root = session.getRootNode();
1128 Node repository = root.getNode( path );
1130 NodeIterator nodes = repository.getNodes();
1131 while ( nodes.hasNext() )
1133 Node node = nodes.nextNode();
1134 names.add( node.getName() );
1137 catch ( PathNotFoundException e )
1139 // ignore repo not found for now
1141 catch ( RepositoryException e )
1143 throw new MetadataResolutionException( e.getMessage(), e );
1149 private static String getRepositoryPath( String repositoryId )
1151 return "repositories/" + repositoryId;
1154 private static String getRepositoryContentPath( String repositoryId )
1156 return getRepositoryPath( repositoryId ) + "/content/";
1159 private static String getFacetPath( String repositoryId, String facetId )
1161 return getRepositoryPath( repositoryId ) + "/facets/" + facetId;
1164 private static String getNamespacePath( String repositoryId, String namespace )
1166 return getRepositoryContentPath( repositoryId ) + namespace.replace( '.', '/' );
1169 private static String getProjectPath( String repositoryId, String namespace, String projectId )
1171 return getNamespacePath( repositoryId, namespace ) + "/" + projectId;
1174 private static String getProjectVersionPath( String repositoryId, String namespace, String projectId,
1175 String projectVersion )
1177 return getProjectPath( repositoryId, namespace, projectId ) + "/" + projectVersion;
1180 private static String getArtifactPath( String repositoryId, String namespace, String projectId,
1181 String projectVersion, String id )
1183 return getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/" + id;
1186 private Node getOrAddNodeByPath( Node baseNode, String name )
1187 throws RepositoryException
1189 Node node = baseNode;
1190 for ( String n : name.split( "/" ) )
1192 node = JcrUtils.getOrAddNode( node, n );
1197 private static String getFacetPath( String repositoryId, String facetId, String name )
1199 return getFacetPath( repositoryId, facetId ) + "/" + name;
1202 private Node getOrAddRepositoryNode( String repositoryId )
1203 throws RepositoryException
1205 Node root = session.getRootNode();
1206 Node node = JcrUtils.getOrAddNode( root, "repositories" );
1207 node = JcrUtils.getOrAddNode( node, repositoryId );
1211 private Node getOrAddRepositoryContentNode( String repositoryId )
1212 throws RepositoryException
1214 Node node = getOrAddRepositoryNode( repositoryId );
1215 return JcrUtils.getOrAddNode( node, "content" );
1218 private Node getOrAddNamespaceNode( String repositoryId, String namespace )
1219 throws RepositoryException
1221 Node repo = getOrAddRepositoryContentNode( repositoryId );
1222 return getOrAddNodeByPath( repo, namespace.replace( '.', '/' ) );
1225 private Node getOrAddProjectNode( String repositoryId, String namespace, String projectId )
1226 throws RepositoryException
1228 Node namespaceNode = getOrAddNamespaceNode( repositoryId, namespace );
1229 return JcrUtils.getOrAddNode( namespaceNode, projectId );
1232 private Node getOrAddProjectVersionNode( String repositoryId, String namespace, String projectId,
1233 String projectVersion )
1234 throws RepositoryException
1236 Node projectNode = getOrAddProjectNode( repositoryId, namespace, projectId );
1237 return JcrUtils.getOrAddNode( projectNode, projectVersion );
1240 private Node getOrAddArtifactNode( String repositoryId, String namespace, String projectId, String projectVersion,
1242 throws RepositoryException
1244 Node versionNode = getOrAddProjectVersionNode( repositoryId, namespace, projectId, projectVersion );
1245 Node node = JcrUtils.getOrAddNode( versionNode, id );
1246 node.addMixin( ARTIFACT_NODE_TYPE );
1250 private static Calendar createCalendar( Date time )
1252 Calendar cal = Calendar.getInstance();
1253 cal.setTime( time );
1257 private String join( Collection<String> ids )
1259 if ( ids != null && !ids.isEmpty() )
1261 StringBuilder s = new StringBuilder();
1262 for ( String id : ids )
1267 return s.substring( 0, s.length() - 1 );
1272 public Session getJcrSession()