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.apache.jackrabbit.core.TransientRepository;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.Calendar;
47 import java.util.Collection;
48 import java.util.Collections;
49 import java.util.Date;
50 import java.util.HashMap;
51 import java.util.LinkedHashSet;
52 import java.util.List;
55 import javax.jcr.LoginException;
56 import javax.jcr.Node;
57 import javax.jcr.NodeIterator;
58 import javax.jcr.PathNotFoundException;
59 import javax.jcr.Property;
60 import javax.jcr.Repository;
61 import javax.jcr.RepositoryException;
62 import javax.jcr.Session;
63 import javax.jcr.SimpleCredentials;
64 import javax.jcr.ValueFactory;
65 import javax.jcr.Workspace;
66 import javax.jcr.nodetype.NodeTypeManager;
67 import javax.jcr.nodetype.NodeTypeTemplate;
68 import javax.jcr.query.Query;
69 import javax.jcr.query.QueryResult;
72 * @plexus.component role="org.apache.archiva.metadata.repository.MetadataRepository"
73 * @todo below: revise storage format for project version metadata
74 * @todo revise reference storage
76 public class JcrMetadataRepository
77 implements MetadataRepository
79 private static final String JCR_LAST_MODIFIED = "jcr:lastModified";
81 private static final String ARTIFACT_NODE_TYPE = "archiva:artifact";
83 private static final String FACET_NODE_TYPE = "archiva:facet";
85 private static final String QUERY_ARTIFACTS = "SELECT * FROM [" + ARTIFACT_NODE_TYPE + "]";
88 * @plexus.requirement role="org.apache.archiva.metadata.model.MetadataFacetFactory"
90 private Map<String, MetadataFacetFactory> metadataFacetFactories;
92 private static final Logger log = LoggerFactory.getLogger( JcrMetadataRepository.class );
94 private static Repository repository;
96 private Session session;
98 public JcrMetadataRepository()
100 // TODO: need to close this at the end - do we need to add it in the API?
104 // TODO: push this in from the test, and make it possible from the webapp
105 if ( repository == null )
107 repository = new TransientRepository( new File( "src/test/repository.xml" ), new File( "target/jcr" ) );
109 // TODO: shouldn't do this in constructor since it's a singleton
110 session = repository.login( new SimpleCredentials( "username", "password".toCharArray() ) );
112 // TODO: try moving this into the repo instantiation
113 Workspace workspace = session.getWorkspace();
114 workspace.getNamespaceRegistry().registerNamespace( "archiva", "http://archiva.apache.org/jcr/" );
116 NodeTypeManager nodeTypeManager = workspace.getNodeTypeManager();
117 registerMixinNodeType( nodeTypeManager, ARTIFACT_NODE_TYPE );
118 registerMixinNodeType( nodeTypeManager, FACET_NODE_TYPE );
120 catch ( LoginException e )
123 throw new RuntimeException( e );
125 catch ( RepositoryException e )
128 throw new RuntimeException( e );
132 private static void registerMixinNodeType( NodeTypeManager nodeTypeManager, String name )
133 throws RepositoryException
135 NodeTypeTemplate nodeType = nodeTypeManager.createNodeTypeTemplate();
136 nodeType.setMixin( true );
137 nodeType.setName( name );
138 nodeTypeManager.registerNodeType( nodeType, false );
141 public void updateProject( String repositoryId, ProjectMetadata project )
142 throws MetadataRepositoryException
144 updateProject( repositoryId, project.getNamespace(), project.getId() );
147 private void updateProject( String repositoryId, String namespace, String projectId )
148 throws MetadataRepositoryException
150 updateNamespace( repositoryId, namespace );
154 getOrAddProjectNode( repositoryId, namespace, projectId );
156 catch ( RepositoryException e )
158 throw new MetadataRepositoryException( e.getMessage(), e );
162 public void updateArtifact( String repositoryId, String namespace, String projectId, String projectVersion,
163 ArtifactMetadata artifactMeta )
164 throws MetadataRepositoryException
166 updateNamespace( repositoryId, namespace );
170 Node node = getOrAddArtifactNode( repositoryId, namespace, projectId, projectVersion,
171 artifactMeta.getId() );
173 Calendar cal = Calendar.getInstance();
174 cal.setTime( artifactMeta.getFileLastModified() );
175 node.setProperty( JCR_LAST_MODIFIED, cal );
177 cal = Calendar.getInstance();
178 cal.setTime( artifactMeta.getWhenGathered() );
179 node.setProperty( "whenGathered", cal );
181 node.setProperty( "size", artifactMeta.getSize() );
182 node.setProperty( "md5", artifactMeta.getMd5() );
183 node.setProperty( "sha1", artifactMeta.getSha1() );
185 node.setProperty( "version", artifactMeta.getVersion() );
187 for ( MetadataFacet facet : artifactMeta.getFacetList() )
189 if ( node.hasNode( facet.getFacetId() ) )
191 node.getNode( facet.getFacetId() ).remove();
194 // recreate, to ensure properties are removed
195 Node n = node.addNode( facet.getFacetId() );
196 n.addMixin( FACET_NODE_TYPE );
198 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
200 n.setProperty( entry.getKey(), entry.getValue() );
203 // TODO: need some context around this so it can be done only when needed
206 catch ( RepositoryException e )
208 throw new MetadataRepositoryException( e.getMessage(), e );
212 public void updateProjectVersion( String repositoryId, String namespace, String projectId,
213 ProjectVersionMetadata versionMetadata )
214 throws MetadataRepositoryException
216 updateProject( repositoryId, namespace, projectId );
220 Node versionNode = getOrAddProjectVersionNode( repositoryId, namespace, projectId,
221 versionMetadata.getId() );
223 versionNode.setProperty( "name", versionMetadata.getName() );
224 versionNode.setProperty( "description", versionMetadata.getDescription() );
225 versionNode.setProperty( "url", versionMetadata.getUrl() );
226 versionNode.setProperty( "incomplete", versionMetadata.isIncomplete() );
228 // TODO: decide how to treat these in the content repo
229 if ( versionMetadata.getScm() != null )
231 versionNode.setProperty( "scm.connection", versionMetadata.getScm().getConnection() );
232 versionNode.setProperty( "scm.developerConnection", versionMetadata.getScm().getDeveloperConnection() );
233 versionNode.setProperty( "scm.url", versionMetadata.getScm().getUrl() );
235 if ( versionMetadata.getCiManagement() != null )
237 versionNode.setProperty( "ci.system", versionMetadata.getCiManagement().getSystem() );
238 versionNode.setProperty( "ci.url", versionMetadata.getCiManagement().getUrl() );
240 if ( versionMetadata.getIssueManagement() != null )
242 versionNode.setProperty( "issue.system", versionMetadata.getIssueManagement().getSystem() );
243 versionNode.setProperty( "issue.url", versionMetadata.getIssueManagement().getUrl() );
245 if ( versionMetadata.getOrganization() != null )
247 versionNode.setProperty( "org.name", versionMetadata.getOrganization().getName() );
248 versionNode.setProperty( "org.url", versionMetadata.getOrganization().getUrl() );
251 for ( License license : versionMetadata.getLicenses() )
253 versionNode.setProperty( "license." + i + ".name", license.getName() );
254 versionNode.setProperty( "license." + i + ".url", license.getUrl() );
258 for ( MailingList mailingList : versionMetadata.getMailingLists() )
260 versionNode.setProperty( "mailingList." + i + ".archive", mailingList.getMainArchiveUrl() );
261 versionNode.setProperty( "mailingList." + i + ".name", mailingList.getName() );
262 versionNode.setProperty( "mailingList." + i + ".post", mailingList.getPostAddress() );
263 versionNode.setProperty( "mailingList." + i + ".unsubscribe", mailingList.getUnsubscribeAddress() );
264 versionNode.setProperty( "mailingList." + i + ".subscribe", mailingList.getSubscribeAddress() );
265 versionNode.setProperty( "mailingList." + i + ".otherArchives", join(
266 mailingList.getOtherArchives() ) );
270 for ( Dependency dependency : versionMetadata.getDependencies() )
272 versionNode.setProperty( "dependency." + i + ".classifier", dependency.getClassifier() );
273 versionNode.setProperty( "dependency." + i + ".scope", dependency.getScope() );
274 versionNode.setProperty( "dependency." + i + ".systemPath", dependency.getSystemPath() );
275 versionNode.setProperty( "dependency." + i + ".artifactId", dependency.getArtifactId() );
276 versionNode.setProperty( "dependency." + i + ".groupId", dependency.getGroupId() );
277 versionNode.setProperty( "dependency." + i + ".version", dependency.getVersion() );
278 versionNode.setProperty( "dependency." + i + ".type", dependency.getType() );
282 for ( MetadataFacet facet : versionMetadata.getFacetList() )
284 // recreate, to ensure properties are removed
285 if ( versionNode.hasNode( facet.getFacetId() ) )
287 versionNode.getNode( facet.getFacetId() ).remove();
289 Node n = versionNode.addNode( facet.getFacetId() );
290 n.addMixin( FACET_NODE_TYPE );
292 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
294 n.setProperty( entry.getKey(), entry.getValue() );
298 catch ( RepositoryException e )
300 throw new MetadataRepositoryException( e.getMessage(), e );
304 public void updateProjectReference( String repositoryId, String namespace, String projectId, String projectVersion,
305 ProjectVersionReference reference )
306 throws MetadataRepositoryException
308 // not using weak references, since they still need to exist upfront to be referred to
311 Node node = getOrAddRepositoryContentNode( repositoryId );
312 node = JcrUtils.getOrAddNode( node, namespace );
313 node = JcrUtils.getOrAddNode( node, projectId );
314 node = JcrUtils.getOrAddNode( node, projectVersion );
315 node = JcrUtils.getOrAddNode( node, "references" );
316 node = JcrUtils.getOrAddNode( node, reference.getNamespace() );
317 node = JcrUtils.getOrAddNode( node, reference.getProjectId() );
318 node = JcrUtils.getOrAddNode( node, reference.getProjectVersion() );
319 node.setProperty( "type", reference.getReferenceType().toString() );
321 catch ( RepositoryException e )
323 throw new MetadataRepositoryException( e.getMessage(), e );
327 public void updateNamespace( String repositoryId, String namespace )
328 throws MetadataRepositoryException
332 Node node = getOrAddNamespaceNode( repositoryId, namespace );
333 node.setProperty( "namespace", namespace );
335 catch ( RepositoryException e )
337 throw new MetadataRepositoryException( e.getMessage(), e );
341 public List<String> getMetadataFacets( String repositoryId, String facetId )
342 throws MetadataRepositoryException
344 List<String> facets = new ArrayList<String>();
348 // no need to construct node-by-node here, as we'll find in the next instance, the facet names have / and
349 // are paths themselves
350 Node node = session.getRootNode().getNode( getFacetPath( repositoryId, facetId ) );
352 // TODO: this is a bit awkward. Might be better to review the purpose of this function - why is the list of
354 recurse( facets, "", node );
356 catch ( PathNotFoundException e )
358 // ignored - the facet doesn't exist, so return the empty list
360 catch ( RepositoryException e )
362 throw new MetadataRepositoryException( e.getMessage(), e );
367 private void recurse( List<String> facets, String prefix, Node node )
368 throws RepositoryException
370 for ( Node n : JcrUtils.getChildNodes( node ) )
372 String name = prefix + "/" + n.getName();
375 recurse( facets, name, n );
379 // strip leading / first
380 facets.add( name.substring( 1 ) );
385 public MetadataFacet getMetadataFacet( String repositoryId, String facetId, String name )
386 throws MetadataRepositoryException
388 MetadataFacet metadataFacet = null;
391 Node root = session.getRootNode();
392 Node node = root.getNode( getFacetPath( repositoryId, facetId, name ) );
394 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId );
395 if ( metadataFacetFactory != null )
397 metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name );
398 Map<String, String> map = new HashMap<String, String>();
399 for ( Property property : JcrUtils.getProperties( node ) )
401 String p = property.getName();
402 if ( !p.startsWith( "jcr:" ) )
404 map.put( p, property.getString() );
407 metadataFacet.fromProperties( map );
410 catch ( PathNotFoundException e )
412 // ignored - the facet doesn't exist, so return null
414 catch ( RepositoryException e )
416 throw new MetadataRepositoryException( e.getMessage(), e );
418 return metadataFacet;
421 public void addMetadataFacet( String repositoryId, MetadataFacet metadataFacet )
422 throws MetadataRepositoryException
426 Node repo = getOrAddRepositoryNode( repositoryId );
427 Node facets = JcrUtils.getOrAddNode( repo, "facets" );
429 String id = metadataFacet.getFacetId();
430 Node facetNode = JcrUtils.getOrAddNode( facets, id );
432 Node node = getOrAddNodeByPath( facetNode, metadataFacet.getName() );
434 for ( Map.Entry<String, String> entry : metadataFacet.toProperties().entrySet() )
436 node.setProperty( entry.getKey(), entry.getValue() );
439 catch ( RepositoryException e )
441 throw new MetadataRepositoryException( e.getMessage(), e );
445 public void removeMetadataFacets( String repositoryId, String facetId )
446 throws MetadataRepositoryException
450 Node root = session.getRootNode();
451 String path = getFacetPath( repositoryId, facetId );
452 if ( root.hasNode( path ) )
454 root.getNode( path ).remove();
457 catch ( RepositoryException e )
459 throw new MetadataRepositoryException( e.getMessage(), e );
463 public void removeMetadataFacet( String repositoryId, String facetId, String name )
464 throws MetadataRepositoryException
468 Node root = session.getRootNode();
469 String path = getFacetPath( repositoryId, facetId, name );
470 if ( root.hasNode( path ) )
472 Node node = root.getNode( path );
475 // also remove empty container nodes
476 Node parent = node.getParent();
480 while ( !node.hasNodes() );
483 catch ( RepositoryException e )
485 throw new MetadataRepositoryException( e.getMessage(), e );
489 public List<ArtifactMetadata> getArtifactsByDateRange( String repoId, Date startTime, Date endTime )
490 throws MetadataRepositoryException
492 List<ArtifactMetadata> artifacts;
494 String q = QUERY_ARTIFACTS;
496 String clause = " WHERE";
497 if ( startTime != null )
499 q += clause + " [whenGathered] >= $start";
502 if ( endTime != null )
504 q += clause + " [whenGathered] <= $end";
509 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
510 ValueFactory valueFactory = session.getValueFactory();
511 if ( startTime != null )
513 query.bindValue( "start", valueFactory.createValue( createCalendar( startTime ) ) );
515 if ( endTime != null )
517 query.bindValue( "end", valueFactory.createValue( createCalendar( endTime ) ) );
519 QueryResult result = query.execute();
521 artifacts = new ArrayList<ArtifactMetadata>();
522 for ( Node n : JcrUtils.getNodes( result ) )
524 artifacts.add( getArtifactFromNode( repoId, n ) );
527 catch ( RepositoryException e )
529 throw new MetadataRepositoryException( e.getMessage(), e );
534 public Collection<String> getRepositories()
535 throws MetadataRepositoryException
537 List<String> repositories;
541 Node root = session.getRootNode();
542 if ( root.hasNode( "repositories" ) )
544 Node node = root.getNode( "repositories" );
546 repositories = new ArrayList<String>();
547 NodeIterator i = node.getNodes();
548 while ( i.hasNext() )
550 Node n = i.nextNode();
551 repositories.add( n.getName() );
556 repositories = Collections.emptyList();
559 catch ( RepositoryException e )
561 throw new MetadataRepositoryException( e.getMessage(), e );
566 public List<ArtifactMetadata> getArtifactsByChecksum( String repositoryId, String checksum )
567 throws MetadataRepositoryException
569 List<ArtifactMetadata> artifacts;
571 String q = QUERY_ARTIFACTS + " WHERE [sha1] = $checksum OR [md5] = $checksum";
575 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
576 ValueFactory valueFactory = session.getValueFactory();
577 query.bindValue( "checksum", valueFactory.createValue( checksum ) );
578 QueryResult result = query.execute();
580 artifacts = new ArrayList<ArtifactMetadata>();
581 for ( Node n : JcrUtils.getNodes( result ) )
583 artifacts.add( getArtifactFromNode( repositoryId, n ) );
586 catch ( RepositoryException e )
588 throw new MetadataRepositoryException( e.getMessage(), e );
593 public void deleteArtifact( String repositoryId, String namespace, String projectId, String projectVersion,
595 throws MetadataRepositoryException
599 Node root = session.getRootNode();
600 String path = getArtifactPath( repositoryId, namespace, projectId, projectVersion, id );
601 if ( root.hasNode( path ) )
603 root.getNode( path ).remove();
606 catch ( RepositoryException e )
608 throw new MetadataRepositoryException( e.getMessage(), e );
612 public void deleteRepository( String repositoryId )
613 throws MetadataRepositoryException
617 Node root = session.getRootNode();
618 String path = getRepositoryPath( repositoryId );
619 if ( root.hasNode( path ) )
621 root.getNode( path ).remove();
624 catch ( RepositoryException e )
626 throw new MetadataRepositoryException( e.getMessage(), e );
630 public List<ArtifactMetadata> getArtifacts( String repositoryId )
631 throws MetadataRepositoryException
633 List<ArtifactMetadata> artifacts;
635 String q = QUERY_ARTIFACTS;
639 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
640 QueryResult result = query.execute();
642 artifacts = new ArrayList<ArtifactMetadata>();
643 for ( Node n : JcrUtils.getNodes( result ) )
645 artifacts.add( getArtifactFromNode( repositoryId, n ) );
648 catch ( RepositoryException e )
650 throw new MetadataRepositoryException( e.getMessage(), e );
655 public ProjectMetadata getProject( String repositoryId, String namespace, String projectId )
656 throws MetadataResolutionException
658 ProjectMetadata metadata = null;
662 Node root = session.getRootNode();
664 // basically just checking it exists
665 String path = getProjectPath( repositoryId, namespace, projectId );
666 if ( root.hasNode( path ) )
668 metadata = new ProjectMetadata();
669 metadata.setId( projectId );
670 metadata.setNamespace( namespace );
673 catch ( RepositoryException e )
675 throw new MetadataResolutionException( e.getMessage(), e );
681 public ProjectVersionMetadata getProjectVersion( String repositoryId, String namespace, String projectId,
682 String projectVersion )
683 throws MetadataResolutionException
685 ProjectVersionMetadata versionMetadata;
689 Node root = session.getRootNode();
691 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
692 if ( !root.hasNode( path ) )
697 Node node = root.getNode( path );
699 versionMetadata = new ProjectVersionMetadata();
700 versionMetadata.setId( projectVersion );
701 versionMetadata.setName( getPropertyString( node, "name" ) );
702 versionMetadata.setDescription( getPropertyString( node, "description" ) );
703 versionMetadata.setUrl( getPropertyString( node, "url" ) );
704 versionMetadata.setIncomplete( node.hasProperty( "incomplete" ) && node.getProperty(
705 "incomplete" ).getBoolean() );
707 // TODO: decide how to treat these in the content repo
708 String scmConnection = getPropertyString( node, "scm.connection" );
709 String scmDeveloperConnection = getPropertyString( node, "scm.developerConnection" );
710 String scmUrl = getPropertyString( node, "scm.url" );
711 if ( scmConnection != null || scmDeveloperConnection != null || scmUrl != null )
714 scm.setConnection( scmConnection );
715 scm.setDeveloperConnection( scmDeveloperConnection );
716 scm.setUrl( scmUrl );
717 versionMetadata.setScm( scm );
720 String ciSystem = getPropertyString( node, "ci.system" );
721 String ciUrl = getPropertyString( node, "ci.url" );
722 if ( ciSystem != null || ciUrl != null )
724 CiManagement ci = new CiManagement();
725 ci.setSystem( ciSystem );
727 versionMetadata.setCiManagement( ci );
730 String issueSystem = getPropertyString( node, "issue.system" );
731 String issueUrl = getPropertyString( node, "issue.url" );
732 if ( issueSystem != null || issueUrl != null )
734 IssueManagement issueManagement = new IssueManagement();
735 issueManagement.setSystem( issueSystem );
736 issueManagement.setUrl( issueUrl );
737 versionMetadata.setIssueManagement( issueManagement );
740 String orgName = getPropertyString( node, "org.name" );
741 String orgUrl = getPropertyString( node, "org.url" );
742 if ( orgName != null || orgUrl != null )
744 Organization org = new Organization();
745 org.setName( orgName );
746 org.setUrl( orgUrl );
747 versionMetadata.setOrganization( org );
750 boolean done = false;
754 String licenseName = getPropertyString( node, "license." + i + ".name" );
755 String licenseUrl = getPropertyString( node, "license." + i + ".url" );
756 if ( licenseName != null || licenseUrl != null )
758 License license = new License();
759 license.setName( licenseName );
760 license.setUrl( licenseUrl );
761 versionMetadata.addLicense( license );
774 String mailingListName = getPropertyString( node, "mailingList." + i + ".name" );
775 if ( mailingListName != null )
777 MailingList mailingList = new MailingList();
778 mailingList.setName( mailingListName );
779 mailingList.setMainArchiveUrl( getPropertyString( node, "mailingList." + i + ".archive" ) );
780 String n = "mailingList." + i + ".otherArchives";
781 if ( node.hasProperty( n ) )
783 mailingList.setOtherArchives( Arrays.asList( getPropertyString( node, n ).split( "," ) ) );
787 mailingList.setOtherArchives( Collections.<String>emptyList() );
789 mailingList.setPostAddress( getPropertyString( node, "mailingList." + i + ".post" ) );
790 mailingList.setSubscribeAddress( getPropertyString( node, "mailingList." + i + ".subscribe" ) );
791 mailingList.setUnsubscribeAddress( getPropertyString( node, "mailingList." + i + ".unsubscribe" ) );
792 versionMetadata.addMailingList( mailingList );
805 String dependencyArtifactId = getPropertyString( node, "dependency." + i + ".artifactId" );
806 if ( dependencyArtifactId != null )
808 Dependency dependency = new Dependency();
809 dependency.setArtifactId( dependencyArtifactId );
810 dependency.setGroupId( getPropertyString( node, "dependency." + i + ".groupId" ) );
811 dependency.setClassifier( getPropertyString( node, "dependency." + i + ".classifier" ) );
812 dependency.setOptional( Boolean.valueOf( getPropertyString( node,
813 "dependency." + i + ".optional" ) ) );
814 dependency.setScope( getPropertyString( node, "dependency." + i + ".scope" ) );
815 dependency.setSystemPath( getPropertyString( node, "dependency." + i + ".systemPath" ) );
816 dependency.setType( getPropertyString( node, "dependency." + i + ".type" ) );
817 dependency.setVersion( getPropertyString( node, "dependency." + i + ".version" ) );
818 versionMetadata.addDependency( dependency );
827 for ( Node n : JcrUtils.getChildNodes( node ) )
829 if ( n.isNodeType( FACET_NODE_TYPE ) )
831 String name = n.getName();
832 MetadataFacetFactory factory = metadataFacetFactories.get( name );
833 if ( factory == null )
835 log.error( "Attempted to load unknown project version metadata facet: " + name );
839 MetadataFacet facet = factory.createMetadataFacet();
840 Map<String, String> map = new HashMap<String, String>();
841 for ( Property property : JcrUtils.getProperties( n ) )
843 String p = property.getName();
844 if ( !p.startsWith( "jcr:" ) )
846 map.put( p, property.getString() );
849 facet.fromProperties( map );
850 versionMetadata.addFacet( facet );
855 catch ( RepositoryException e )
857 throw new MetadataResolutionException( e.getMessage(), e );
860 return versionMetadata;
863 public Collection<String> getArtifactVersions( String repositoryId, String namespace, String projectId,
864 String projectVersion )
865 throws MetadataResolutionException
867 Set<String> versions = new LinkedHashSet<String>();
871 Node root = session.getRootNode();
873 Node node = root.getNode( getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) );
875 for ( Node n : JcrUtils.getChildNodes( node ) )
877 versions.add( n.getProperty( "version" ).getString() );
880 catch ( PathNotFoundException e )
882 // ignore repo not found for now
884 catch ( RepositoryException e )
886 throw new MetadataResolutionException( e.getMessage(), e );
892 public Collection<ProjectVersionReference> getProjectReferences( String repositoryId, String namespace,
893 String projectId, String projectVersion )
894 throws MetadataResolutionException
896 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
900 Node root = session.getRootNode();
902 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/references";
903 if ( root.hasNode( path ) )
905 Node node = root.getNode( path );
907 NodeIterator i = node.getNodes();
908 while ( i.hasNext() )
910 Node ns = i.nextNode();
912 NodeIterator j = ns.getNodes();
914 while ( j.hasNext() )
916 Node project = j.nextNode();
918 NodeIterator k = project.getNodes();
920 while ( k.hasNext() )
922 Node version = k.nextNode();
924 ProjectVersionReference ref = new ProjectVersionReference();
925 ref.setNamespace( ns.getName() );
926 ref.setProjectId( project.getName() );
927 ref.setProjectVersion( version.getName() );
928 String type = version.getProperty( "type" ).getString();
929 ref.setReferenceType( ProjectVersionReference.ReferenceType.valueOf( type ) );
930 references.add( ref );
936 catch ( RepositoryException e )
938 throw new MetadataResolutionException( e.getMessage(), e );
944 public Collection<String> getRootNamespaces( String repositoryId )
945 throws MetadataResolutionException
947 return getNamespaces( repositoryId, null );
950 public Collection<String> getNamespaces( String repositoryId, String baseNamespace )
951 throws MetadataResolutionException
953 String path = baseNamespace != null
954 ? getNamespacePath( repositoryId, baseNamespace )
955 : getRepositoryContentPath( repositoryId );
957 return getNodeNames( path );
960 public Collection<String> getProjects( String repositoryId, String namespace )
961 throws MetadataResolutionException
963 return getNodeNames( getNamespacePath( repositoryId, namespace ) );
966 public Collection<String> getProjectVersions( String repositoryId, String namespace, String projectId )
967 throws MetadataResolutionException
969 return getNodeNames( getProjectPath( repositoryId, namespace, projectId ) );
972 public Collection<ArtifactMetadata> getArtifacts( String repositoryId, String namespace, String projectId,
973 String projectVersion )
974 throws MetadataResolutionException
976 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
980 Node root = session.getRootNode();
981 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
983 if ( root.hasNode( path ) )
985 Node node = root.getNode( path );
987 for ( Node n : JcrUtils.getChildNodes( node ) )
989 artifacts.add( getArtifactFromNode( repositoryId, n ) );
993 catch ( RepositoryException e )
995 throw new MetadataResolutionException( e.getMessage(), e );
1005 // TODO: this shouldn't be here! Repository may need a context
1008 catch ( RepositoryException e )
1011 throw new RuntimeException( e );
1016 public void setMetadataFacetFactories( Map<String, MetadataFacetFactory> metadataFacetFactories )
1018 this.metadataFacetFactories = metadataFacetFactories;
1020 // TODO: check if actually called by normal injection
1022 // TODO: consider using namespaces for facets instead of the current approach:
1023 // for ( String facetId : metadataFacetFactories.keySet() )
1025 // session.getWorkspace().getNamespaceRegistry().registerNamespace( facetId, facetId );
1029 private ArtifactMetadata getArtifactFromNode( String repositoryId, Node artifactNode )
1030 throws RepositoryException
1032 String id = artifactNode.getName();
1034 ArtifactMetadata artifact = new ArtifactMetadata();
1035 artifact.setId( id );
1036 artifact.setRepositoryId( repositoryId );
1038 Node projectVersionNode = artifactNode.getParent();
1039 Node projectNode = projectVersionNode.getParent();
1040 Node namespaceNode = projectNode.getParent();
1042 artifact.setNamespace( namespaceNode.getProperty( "namespace" ).getString() );
1043 artifact.setProject( projectNode.getName() );
1044 artifact.setProjectVersion( projectVersionNode.getName() );
1045 artifact.setVersion( artifactNode.hasProperty( "version" )
1046 ? artifactNode.getProperty( "version" ).getString()
1047 : projectVersionNode.getName() );
1049 if ( artifactNode.hasProperty( JCR_LAST_MODIFIED ) )
1051 artifact.setFileLastModified( artifactNode.getProperty( JCR_LAST_MODIFIED ).getDate().getTimeInMillis() );
1054 if ( artifactNode.hasProperty( "whenGathered" ) )
1056 artifact.setWhenGathered( artifactNode.getProperty( "whenGathered" ).getDate().getTime() );
1059 if ( artifactNode.hasProperty( "size" ) )
1061 artifact.setSize( artifactNode.getProperty( "size" ).getLong() );
1064 if ( artifactNode.hasProperty( "md5" ) )
1066 artifact.setMd5( artifactNode.getProperty( "md5" ).getString() );
1069 if ( artifactNode.hasProperty( "sha1" ) )
1071 artifact.setSha1( artifactNode.getProperty( "sha1" ).getString() );
1074 for ( Node n : JcrUtils.getChildNodes( artifactNode ) )
1076 if ( n.isNodeType( FACET_NODE_TYPE ) )
1078 String name = n.getName();
1079 MetadataFacetFactory factory = metadataFacetFactories.get( name );
1080 if ( factory == null )
1082 log.error( "Attempted to load unknown project version metadata facet: " + name );
1086 MetadataFacet facet = factory.createMetadataFacet();
1087 Map<String, String> map = new HashMap<String, String>();
1088 for ( Property p : JcrUtils.getProperties( n ) )
1090 String property = p.getName();
1091 if ( !property.startsWith( "jcr:" ) )
1093 map.put( property, p.getString() );
1096 facet.fromProperties( map );
1097 artifact.addFacet( facet );
1104 private static String getPropertyString( Node node, String name )
1105 throws RepositoryException
1107 return node.hasProperty( name ) ? node.getProperty( name ).getString() : null;
1110 private Collection<String> getNodeNames( String path )
1111 throws MetadataResolutionException
1113 List<String> names = new ArrayList<String>();
1117 Node root = session.getRootNode();
1119 Node repository = root.getNode( path );
1121 NodeIterator nodes = repository.getNodes();
1122 while ( nodes.hasNext() )
1124 Node node = nodes.nextNode();
1125 names.add( node.getName() );
1128 catch ( PathNotFoundException e )
1130 // ignore repo not found for now
1132 catch ( RepositoryException e )
1134 throw new MetadataResolutionException( e.getMessage(), e );
1140 private static String getRepositoryPath( String repositoryId )
1142 return "repositories/" + repositoryId;
1145 private static String getRepositoryContentPath( String repositoryId )
1147 return getRepositoryPath( repositoryId ) + "/content/";
1150 private static String getFacetPath( String repositoryId, String facetId )
1152 return getRepositoryPath( repositoryId ) + "/facets/" + facetId;
1155 private static String getNamespacePath( String repositoryId, String namespace )
1157 return getRepositoryContentPath( repositoryId ) + namespace.replace( '.', '/' );
1160 private static String getProjectPath( String repositoryId, String namespace, String projectId )
1162 return getNamespacePath( repositoryId, namespace ) + "/" + projectId;
1165 private static String getProjectVersionPath( String repositoryId, String namespace, String projectId,
1166 String projectVersion )
1168 return getProjectPath( repositoryId, namespace, projectId ) + "/" + projectVersion;
1171 private static String getArtifactPath( String repositoryId, String namespace, String projectId,
1172 String projectVersion, String id )
1174 return getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/" + id;
1177 private Node getOrAddNodeByPath( Node baseNode, String name )
1178 throws RepositoryException
1180 Node node = baseNode;
1181 for ( String n : name.split( "/" ) )
1183 node = JcrUtils.getOrAddNode( node, n );
1188 private static String getFacetPath( String repositoryId, String facetId, String name )
1190 return getFacetPath( repositoryId, facetId ) + "/" + name;
1193 private Node getOrAddRepositoryNode( String repositoryId )
1194 throws RepositoryException
1196 Node root = session.getRootNode();
1197 Node node = JcrUtils.getOrAddNode( root, "repositories" );
1198 node = JcrUtils.getOrAddNode( node, repositoryId );
1202 private Node getOrAddRepositoryContentNode( String repositoryId )
1203 throws RepositoryException
1205 Node node = getOrAddRepositoryNode( repositoryId );
1206 return JcrUtils.getOrAddNode( node, "content" );
1209 private Node getOrAddNamespaceNode( String repositoryId, String namespace )
1210 throws RepositoryException
1212 Node repo = getOrAddRepositoryContentNode( repositoryId );
1213 return getOrAddNodeByPath( repo, namespace.replace( '.', '/' ) );
1216 private Node getOrAddProjectNode( String repositoryId, String namespace, String projectId )
1217 throws RepositoryException
1219 Node namespaceNode = getOrAddNamespaceNode( repositoryId, namespace );
1220 return JcrUtils.getOrAddNode( namespaceNode, projectId );
1223 private Node getOrAddProjectVersionNode( String repositoryId, String namespace, String projectId,
1224 String projectVersion )
1225 throws RepositoryException
1227 Node projectNode = getOrAddProjectNode( repositoryId, namespace, projectId );
1228 return JcrUtils.getOrAddNode( projectNode, projectVersion );
1231 private Node getOrAddArtifactNode( String repositoryId, String namespace, String projectId, String projectVersion,
1233 throws RepositoryException
1235 Node versionNode = getOrAddProjectVersionNode( repositoryId, namespace, projectId, projectVersion );
1236 Node node = JcrUtils.getOrAddNode( versionNode, id );
1237 node.addMixin( ARTIFACT_NODE_TYPE );
1241 private static Calendar createCalendar( Date time )
1243 Calendar cal = Calendar.getInstance();
1244 cal.setTime( time );
1248 private String join( Collection<String> ids )
1250 if ( ids != null && !ids.isEmpty() )
1252 StringBuilder s = new StringBuilder();
1253 for ( String id : ids )
1258 return s.substring( 0, s.length() - 1 );
1263 public Session getJcrSession()