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 static final String QUERY_ARTIFACTS = "SELECT * FROM [" + ARTIFACT_NODE_TYPE + "]";
84 private final Map<String, MetadataFacetFactory> metadataFacetFactories;
86 private static final Logger log = LoggerFactory.getLogger( JcrMetadataRepository.class );
88 private Repository repository;
90 private Session session;
92 public JcrMetadataRepository( Map<String, MetadataFacetFactory> metadataFacetFactories, Repository repository )
93 throws RepositoryException
95 this.metadataFacetFactories = metadataFacetFactories;
96 this.repository = repository;
98 session = repository.login( new SimpleCredentials( "username", "password".toCharArray() ) );
101 static void initialize( Session session )
102 throws RepositoryException
104 // TODO: consider using namespaces for facets instead of the current approach:
105 // (if used, check if actually called by normal injection)
106 // for ( String facetId : metadataFacetFactories.keySet() )
108 // session.getWorkspace().getNamespaceRegistry().registerNamespace( facetId, facetId );
111 Workspace workspace = session.getWorkspace();
112 NamespaceRegistry registry = workspace.getNamespaceRegistry();
114 if ( !Arrays.asList( registry.getPrefixes() ).contains( "archiva" ) )
116 registry.registerNamespace( "archiva", "http://archiva.apache.org/jcr/" );
119 NodeTypeManager nodeTypeManager = workspace.getNodeTypeManager();
120 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.ARTIFACT_NODE_TYPE );
121 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.FACET_NODE_TYPE );
124 private static void registerMixinNodeType( NodeTypeManager nodeTypeManager, String name )
125 throws RepositoryException
127 NodeTypeTemplate nodeType = nodeTypeManager.createNodeTypeTemplate();
128 nodeType.setMixin( true );
129 nodeType.setName( name );
131 // for now just don't re-create - but in future if we change the definition, make sure to remove first as an
133 if ( !nodeTypeManager.hasNodeType( name ) )
135 nodeTypeManager.registerNodeType( nodeType, false );
139 public void updateProject( String repositoryId, ProjectMetadata project )
140 throws MetadataRepositoryException
142 updateProject( repositoryId, project.getNamespace(), project.getId() );
145 private void updateProject( String repositoryId, String namespace, String projectId )
146 throws MetadataRepositoryException
148 updateNamespace( repositoryId, namespace );
152 getOrAddProjectNode( repositoryId, namespace, projectId );
154 catch ( RepositoryException e )
156 throw new MetadataRepositoryException( e.getMessage(), e );
160 public void updateArtifact( String repositoryId, String namespace, String projectId, String projectVersion,
161 ArtifactMetadata artifactMeta )
162 throws MetadataRepositoryException
164 updateNamespace( repositoryId, namespace );
168 Node node = getOrAddArtifactNode( repositoryId, namespace, projectId, projectVersion,
169 artifactMeta.getId() );
171 Calendar cal = Calendar.getInstance();
172 cal.setTime( artifactMeta.getFileLastModified() );
173 node.setProperty( JCR_LAST_MODIFIED, cal );
175 cal = Calendar.getInstance();
176 cal.setTime( artifactMeta.getWhenGathered() );
177 node.setProperty( "whenGathered", cal );
179 node.setProperty( "size", artifactMeta.getSize() );
180 node.setProperty( "md5", artifactMeta.getMd5() );
181 node.setProperty( "sha1", artifactMeta.getSha1() );
183 node.setProperty( "version", artifactMeta.getVersion() );
185 for ( MetadataFacet facet : artifactMeta.getFacetList() )
187 if ( node.hasNode( facet.getFacetId() ) )
189 node.getNode( facet.getFacetId() ).remove();
192 // recreate, to ensure properties are removed
193 Node n = node.addNode( facet.getFacetId() );
194 n.addMixin( FACET_NODE_TYPE );
196 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
198 n.setProperty( entry.getKey(), entry.getValue() );
201 // FIXME: need some context around this so it can be done only when needed
204 catch ( RepositoryException e )
206 throw new MetadataRepositoryException( e.getMessage(), e );
210 public void updateProjectVersion( String repositoryId, String namespace, String projectId,
211 ProjectVersionMetadata versionMetadata )
212 throws MetadataRepositoryException
214 updateProject( repositoryId, namespace, projectId );
218 Node versionNode = getOrAddProjectVersionNode( repositoryId, namespace, projectId,
219 versionMetadata.getId() );
221 versionNode.setProperty( "name", versionMetadata.getName() );
222 versionNode.setProperty( "description", versionMetadata.getDescription() );
223 versionNode.setProperty( "url", versionMetadata.getUrl() );
224 versionNode.setProperty( "incomplete", versionMetadata.isIncomplete() );
226 // FIXME: decide how to treat these in the content repo
227 if ( versionMetadata.getScm() != null )
229 versionNode.setProperty( "scm.connection", versionMetadata.getScm().getConnection() );
230 versionNode.setProperty( "scm.developerConnection", versionMetadata.getScm().getDeveloperConnection() );
231 versionNode.setProperty( "scm.url", versionMetadata.getScm().getUrl() );
233 if ( versionMetadata.getCiManagement() != null )
235 versionNode.setProperty( "ci.system", versionMetadata.getCiManagement().getSystem() );
236 versionNode.setProperty( "ci.url", versionMetadata.getCiManagement().getUrl() );
238 if ( versionMetadata.getIssueManagement() != null )
240 versionNode.setProperty( "issue.system", versionMetadata.getIssueManagement().getSystem() );
241 versionNode.setProperty( "issue.url", versionMetadata.getIssueManagement().getUrl() );
243 if ( versionMetadata.getOrganization() != null )
245 versionNode.setProperty( "org.name", versionMetadata.getOrganization().getName() );
246 versionNode.setProperty( "org.url", versionMetadata.getOrganization().getUrl() );
249 for ( License license : versionMetadata.getLicenses() )
251 versionNode.setProperty( "license." + i + ".name", license.getName() );
252 versionNode.setProperty( "license." + i + ".url", license.getUrl() );
256 for ( MailingList mailingList : versionMetadata.getMailingLists() )
258 versionNode.setProperty( "mailingList." + i + ".archive", mailingList.getMainArchiveUrl() );
259 versionNode.setProperty( "mailingList." + i + ".name", mailingList.getName() );
260 versionNode.setProperty( "mailingList." + i + ".post", mailingList.getPostAddress() );
261 versionNode.setProperty( "mailingList." + i + ".unsubscribe", mailingList.getUnsubscribeAddress() );
262 versionNode.setProperty( "mailingList." + i + ".subscribe", mailingList.getSubscribeAddress() );
263 versionNode.setProperty( "mailingList." + i + ".otherArchives", join(
264 mailingList.getOtherArchives() ) );
268 for ( Dependency dependency : versionMetadata.getDependencies() )
270 versionNode.setProperty( "dependency." + i + ".classifier", dependency.getClassifier() );
271 versionNode.setProperty( "dependency." + i + ".scope", dependency.getScope() );
272 versionNode.setProperty( "dependency." + i + ".systemPath", dependency.getSystemPath() );
273 versionNode.setProperty( "dependency." + i + ".artifactId", dependency.getArtifactId() );
274 versionNode.setProperty( "dependency." + i + ".groupId", dependency.getGroupId() );
275 versionNode.setProperty( "dependency." + i + ".version", dependency.getVersion() );
276 versionNode.setProperty( "dependency." + i + ".type", dependency.getType() );
280 for ( MetadataFacet facet : versionMetadata.getFacetList() )
282 // recreate, to ensure properties are removed
283 if ( versionNode.hasNode( facet.getFacetId() ) )
285 versionNode.getNode( facet.getFacetId() ).remove();
287 Node n = versionNode.addNode( facet.getFacetId() );
288 n.addMixin( FACET_NODE_TYPE );
290 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
292 n.setProperty( entry.getKey(), entry.getValue() );
296 catch ( RepositoryException e )
298 throw new MetadataRepositoryException( e.getMessage(), e );
302 public void updateProjectReference( String repositoryId, String namespace, String projectId, String projectVersion,
303 ProjectVersionReference reference )
304 throws MetadataRepositoryException
306 // not using weak references, since they still need to exist upfront to be referred to
309 Node node = getOrAddRepositoryContentNode( repositoryId );
310 node = JcrUtils.getOrAddNode( node, namespace );
311 node = JcrUtils.getOrAddNode( node, projectId );
312 node = JcrUtils.getOrAddNode( node, projectVersion );
313 node = JcrUtils.getOrAddNode( node, "references" );
314 node = JcrUtils.getOrAddNode( node, reference.getNamespace() );
315 node = JcrUtils.getOrAddNode( node, reference.getProjectId() );
316 node = JcrUtils.getOrAddNode( node, reference.getProjectVersion() );
317 node.setProperty( "type", reference.getReferenceType().toString() );
319 catch ( RepositoryException e )
321 throw new MetadataRepositoryException( e.getMessage(), e );
325 public void updateNamespace( String repositoryId, String namespace )
326 throws MetadataRepositoryException
330 Node node = getOrAddNamespaceNode( repositoryId, namespace );
331 node.setProperty( "namespace", namespace );
333 catch ( RepositoryException e )
335 throw new MetadataRepositoryException( e.getMessage(), e );
339 public List<String> getMetadataFacets( String repositoryId, String facetId )
340 throws MetadataRepositoryException
342 List<String> facets = new ArrayList<String>();
346 // no need to construct node-by-node here, as we'll find in the next instance, the facet names have / and
347 // are paths themselves
348 Node node = session.getRootNode().getNode( getFacetPath( repositoryId, facetId ) );
350 // TODO: this is a bit awkward. Might be better to review the purpose of this function - why is the list of
352 recurse( facets, "", node );
354 catch ( PathNotFoundException e )
356 // ignored - the facet doesn't exist, so return the empty list
358 catch ( RepositoryException e )
360 throw new MetadataRepositoryException( e.getMessage(), e );
365 private void recurse( List<String> facets, String prefix, Node node )
366 throws RepositoryException
368 for ( Node n : JcrUtils.getChildNodes( node ) )
370 String name = prefix + "/" + n.getName();
373 recurse( facets, name, n );
377 // strip leading / first
378 facets.add( name.substring( 1 ) );
383 public MetadataFacet getMetadataFacet( String repositoryId, String facetId, String name )
384 throws MetadataRepositoryException
386 MetadataFacet metadataFacet = null;
389 Node root = session.getRootNode();
390 Node node = root.getNode( getFacetPath( repositoryId, facetId, name ) );
392 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId );
393 if ( metadataFacetFactory != null )
395 metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name );
396 Map<String, String> map = new HashMap<String, String>();
397 for ( Property property : JcrUtils.getProperties( node ) )
399 String p = property.getName();
400 if ( !p.startsWith( "jcr:" ) )
402 map.put( p, property.getString() );
405 metadataFacet.fromProperties( map );
408 catch ( PathNotFoundException e )
410 // ignored - the facet doesn't exist, so return null
412 catch ( RepositoryException e )
414 throw new MetadataRepositoryException( e.getMessage(), e );
416 return metadataFacet;
419 public void addMetadataFacet( String repositoryId, MetadataFacet metadataFacet )
420 throws MetadataRepositoryException
424 Node repo = getOrAddRepositoryNode( repositoryId );
425 Node facets = JcrUtils.getOrAddNode( repo, "facets" );
427 String id = metadataFacet.getFacetId();
428 Node facetNode = JcrUtils.getOrAddNode( facets, id );
430 Node node = getOrAddNodeByPath( facetNode, metadataFacet.getName() );
432 for ( Map.Entry<String, String> entry : metadataFacet.toProperties().entrySet() )
434 node.setProperty( entry.getKey(), entry.getValue() );
437 catch ( RepositoryException e )
439 throw new MetadataRepositoryException( e.getMessage(), e );
443 public void removeMetadataFacets( String repositoryId, String facetId )
444 throws MetadataRepositoryException
448 Node root = session.getRootNode();
449 String path = getFacetPath( repositoryId, facetId );
450 if ( root.hasNode( path ) )
452 root.getNode( path ).remove();
455 catch ( RepositoryException e )
457 throw new MetadataRepositoryException( e.getMessage(), e );
461 public void removeMetadataFacet( String repositoryId, String facetId, String name )
462 throws MetadataRepositoryException
466 Node root = session.getRootNode();
467 String path = getFacetPath( repositoryId, facetId, name );
468 if ( root.hasNode( path ) )
470 Node node = root.getNode( path );
473 // also remove empty container nodes
474 Node parent = node.getParent();
478 while ( !node.hasNodes() );
481 catch ( RepositoryException e )
483 throw new MetadataRepositoryException( e.getMessage(), e );
487 public List<ArtifactMetadata> getArtifactsByDateRange( String repoId, Date startTime, Date endTime )
488 throws MetadataRepositoryException
490 List<ArtifactMetadata> artifacts;
492 String q = QUERY_ARTIFACTS;
494 String clause = " WHERE";
495 if ( startTime != null )
497 q += clause + " [whenGathered] >= $start";
500 if ( endTime != null )
502 q += clause + " [whenGathered] <= $end";
507 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
508 ValueFactory valueFactory = session.getValueFactory();
509 if ( startTime != null )
511 query.bindValue( "start", valueFactory.createValue( createCalendar( startTime ) ) );
513 if ( endTime != null )
515 query.bindValue( "end", valueFactory.createValue( createCalendar( endTime ) ) );
517 QueryResult result = query.execute();
519 artifacts = new ArrayList<ArtifactMetadata>();
520 for ( Node n : JcrUtils.getNodes( result ) )
522 artifacts.add( getArtifactFromNode( repoId, n ) );
525 catch ( RepositoryException e )
527 throw new MetadataRepositoryException( e.getMessage(), e );
532 public Collection<String> getRepositories()
533 throws MetadataRepositoryException
535 List<String> repositories;
539 Node root = session.getRootNode();
540 if ( root.hasNode( "repositories" ) )
542 Node node = root.getNode( "repositories" );
544 repositories = new ArrayList<String>();
545 NodeIterator i = node.getNodes();
546 while ( i.hasNext() )
548 Node n = i.nextNode();
549 repositories.add( n.getName() );
554 repositories = Collections.emptyList();
557 catch ( RepositoryException e )
559 throw new MetadataRepositoryException( e.getMessage(), e );
564 public List<ArtifactMetadata> getArtifactsByChecksum( String repositoryId, String checksum )
565 throws MetadataRepositoryException
567 List<ArtifactMetadata> artifacts;
569 String q = QUERY_ARTIFACTS + " WHERE [sha1] = $checksum OR [md5] = $checksum";
573 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
574 ValueFactory valueFactory = session.getValueFactory();
575 query.bindValue( "checksum", valueFactory.createValue( checksum ) );
576 QueryResult result = query.execute();
578 artifacts = new ArrayList<ArtifactMetadata>();
579 for ( Node n : JcrUtils.getNodes( result ) )
581 artifacts.add( getArtifactFromNode( repositoryId, n ) );
584 catch ( RepositoryException e )
586 throw new MetadataRepositoryException( e.getMessage(), e );
591 public void removeArtifact( String repositoryId, String namespace, String projectId, String projectVersion,
593 throws MetadataRepositoryException
597 Node root = session.getRootNode();
598 String path = getArtifactPath( repositoryId, namespace, projectId, projectVersion, id );
599 if ( root.hasNode( path ) )
601 root.getNode( path ).remove();
604 catch ( RepositoryException e )
606 throw new MetadataRepositoryException( e.getMessage(), e );
610 public void removeRepository( String repositoryId )
611 throws MetadataRepositoryException
615 Node root = session.getRootNode();
616 String path = getRepositoryPath( repositoryId );
617 if ( root.hasNode( path ) )
619 root.getNode( path ).remove();
622 catch ( RepositoryException e )
624 throw new MetadataRepositoryException( e.getMessage(), e );
628 public List<ArtifactMetadata> getArtifacts( String repositoryId )
629 throws MetadataRepositoryException
631 List<ArtifactMetadata> artifacts;
633 String q = QUERY_ARTIFACTS;
637 Query query = session.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
638 QueryResult result = query.execute();
640 artifacts = new ArrayList<ArtifactMetadata>();
641 for ( Node n : JcrUtils.getNodes( result ) )
643 artifacts.add( getArtifactFromNode( repositoryId, n ) );
646 catch ( RepositoryException e )
648 throw new MetadataRepositoryException( e.getMessage(), e );
653 public ProjectMetadata getProject( String repositoryId, String namespace, String projectId )
654 throws MetadataResolutionException
656 ProjectMetadata metadata = null;
660 Node root = session.getRootNode();
662 // basically just checking it exists
663 String path = getProjectPath( repositoryId, namespace, projectId );
664 if ( root.hasNode( path ) )
666 metadata = new ProjectMetadata();
667 metadata.setId( projectId );
668 metadata.setNamespace( namespace );
671 catch ( RepositoryException e )
673 throw new MetadataResolutionException( e.getMessage(), e );
679 public ProjectVersionMetadata getProjectVersion( String repositoryId, String namespace, String projectId,
680 String projectVersion )
681 throws MetadataResolutionException
683 ProjectVersionMetadata versionMetadata;
687 Node root = session.getRootNode();
689 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
690 if ( !root.hasNode( path ) )
695 Node node = root.getNode( path );
697 versionMetadata = new ProjectVersionMetadata();
698 versionMetadata.setId( projectVersion );
699 versionMetadata.setName( getPropertyString( node, "name" ) );
700 versionMetadata.setDescription( getPropertyString( node, "description" ) );
701 versionMetadata.setUrl( getPropertyString( node, "url" ) );
702 versionMetadata.setIncomplete( node.hasProperty( "incomplete" ) && node.getProperty(
703 "incomplete" ).getBoolean() );
705 // FIXME: decide how to treat these in the content repo
706 String scmConnection = getPropertyString( node, "scm.connection" );
707 String scmDeveloperConnection = getPropertyString( node, "scm.developerConnection" );
708 String scmUrl = getPropertyString( node, "scm.url" );
709 if ( scmConnection != null || scmDeveloperConnection != null || scmUrl != null )
712 scm.setConnection( scmConnection );
713 scm.setDeveloperConnection( scmDeveloperConnection );
714 scm.setUrl( scmUrl );
715 versionMetadata.setScm( scm );
718 String ciSystem = getPropertyString( node, "ci.system" );
719 String ciUrl = getPropertyString( node, "ci.url" );
720 if ( ciSystem != null || ciUrl != null )
722 CiManagement ci = new CiManagement();
723 ci.setSystem( ciSystem );
725 versionMetadata.setCiManagement( ci );
728 String issueSystem = getPropertyString( node, "issue.system" );
729 String issueUrl = getPropertyString( node, "issue.url" );
730 if ( issueSystem != null || issueUrl != null )
732 IssueManagement issueManagement = new IssueManagement();
733 issueManagement.setSystem( issueSystem );
734 issueManagement.setUrl( issueUrl );
735 versionMetadata.setIssueManagement( issueManagement );
738 String orgName = getPropertyString( node, "org.name" );
739 String orgUrl = getPropertyString( node, "org.url" );
740 if ( orgName != null || orgUrl != null )
742 Organization org = new Organization();
743 org.setName( orgName );
744 org.setUrl( orgUrl );
745 versionMetadata.setOrganization( org );
748 boolean done = false;
752 String licenseName = getPropertyString( node, "license." + i + ".name" );
753 String licenseUrl = getPropertyString( node, "license." + i + ".url" );
754 if ( licenseName != null || licenseUrl != null )
756 License license = new License();
757 license.setName( licenseName );
758 license.setUrl( licenseUrl );
759 versionMetadata.addLicense( license );
772 String mailingListName = getPropertyString( node, "mailingList." + i + ".name" );
773 if ( mailingListName != null )
775 MailingList mailingList = new MailingList();
776 mailingList.setName( mailingListName );
777 mailingList.setMainArchiveUrl( getPropertyString( node, "mailingList." + i + ".archive" ) );
778 String n = "mailingList." + i + ".otherArchives";
779 if ( node.hasProperty( n ) )
781 mailingList.setOtherArchives( Arrays.asList( getPropertyString( node, n ).split( "," ) ) );
785 mailingList.setOtherArchives( Collections.<String>emptyList() );
787 mailingList.setPostAddress( getPropertyString( node, "mailingList." + i + ".post" ) );
788 mailingList.setSubscribeAddress( getPropertyString( node, "mailingList." + i + ".subscribe" ) );
789 mailingList.setUnsubscribeAddress( getPropertyString( node, "mailingList." + i + ".unsubscribe" ) );
790 versionMetadata.addMailingList( mailingList );
803 String dependencyArtifactId = getPropertyString( node, "dependency." + i + ".artifactId" );
804 if ( dependencyArtifactId != null )
806 Dependency dependency = new Dependency();
807 dependency.setArtifactId( dependencyArtifactId );
808 dependency.setGroupId( getPropertyString( node, "dependency." + i + ".groupId" ) );
809 dependency.setClassifier( getPropertyString( node, "dependency." + i + ".classifier" ) );
810 dependency.setOptional( Boolean.valueOf( getPropertyString( node,
811 "dependency." + i + ".optional" ) ) );
812 dependency.setScope( getPropertyString( node, "dependency." + i + ".scope" ) );
813 dependency.setSystemPath( getPropertyString( node, "dependency." + i + ".systemPath" ) );
814 dependency.setType( getPropertyString( node, "dependency." + i + ".type" ) );
815 dependency.setVersion( getPropertyString( node, "dependency." + i + ".version" ) );
816 versionMetadata.addDependency( dependency );
825 for ( Node n : JcrUtils.getChildNodes( node ) )
827 if ( n.isNodeType( FACET_NODE_TYPE ) )
829 String name = n.getName();
830 MetadataFacetFactory factory = metadataFacetFactories.get( name );
831 if ( factory == null )
833 log.error( "Attempted to load unknown project version metadata facet: " + name );
837 MetadataFacet facet = factory.createMetadataFacet();
838 Map<String, String> map = new HashMap<String, String>();
839 for ( Property property : JcrUtils.getProperties( n ) )
841 String p = property.getName();
842 if ( !p.startsWith( "jcr:" ) )
844 map.put( p, property.getString() );
847 facet.fromProperties( map );
848 versionMetadata.addFacet( facet );
853 catch ( RepositoryException e )
855 throw new MetadataResolutionException( e.getMessage(), e );
858 return versionMetadata;
861 public Collection<String> getArtifactVersions( String repositoryId, String namespace, String projectId,
862 String projectVersion )
863 throws MetadataResolutionException
865 Set<String> versions = new LinkedHashSet<String>();
869 Node root = session.getRootNode();
871 Node node = root.getNode( getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) );
873 for ( Node n : JcrUtils.getChildNodes( node ) )
875 versions.add( n.getProperty( "version" ).getString() );
878 catch ( PathNotFoundException e )
880 // ignore repo not found for now
882 catch ( RepositoryException e )
884 throw new MetadataResolutionException( e.getMessage(), e );
890 public Collection<ProjectVersionReference> getProjectReferences( String repositoryId, String namespace,
891 String projectId, String projectVersion )
892 throws MetadataResolutionException
894 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
898 Node root = session.getRootNode();
900 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/references";
901 if ( root.hasNode( path ) )
903 Node node = root.getNode( path );
905 NodeIterator i = node.getNodes();
906 while ( i.hasNext() )
908 Node ns = i.nextNode();
910 NodeIterator j = ns.getNodes();
912 while ( j.hasNext() )
914 Node project = j.nextNode();
916 NodeIterator k = project.getNodes();
918 while ( k.hasNext() )
920 Node version = k.nextNode();
922 ProjectVersionReference ref = new ProjectVersionReference();
923 ref.setNamespace( ns.getName() );
924 ref.setProjectId( project.getName() );
925 ref.setProjectVersion( version.getName() );
926 String type = version.getProperty( "type" ).getString();
927 ref.setReferenceType( ProjectVersionReference.ReferenceType.valueOf( type ) );
928 references.add( ref );
934 catch ( RepositoryException e )
936 throw new MetadataResolutionException( e.getMessage(), e );
942 public Collection<String> getRootNamespaces( String repositoryId )
943 throws MetadataResolutionException
945 return getNamespaces( repositoryId, null );
948 public Collection<String> getNamespaces( String repositoryId, String baseNamespace )
949 throws MetadataResolutionException
951 String path = baseNamespace != null
952 ? getNamespacePath( repositoryId, baseNamespace )
953 : getRepositoryContentPath( repositoryId );
955 return getNodeNames( path );
958 public Collection<String> getProjects( String repositoryId, String namespace )
959 throws MetadataResolutionException
961 return getNodeNames( getNamespacePath( repositoryId, namespace ) );
964 public Collection<String> getProjectVersions( String repositoryId, String namespace, String projectId )
965 throws MetadataResolutionException
967 return getNodeNames( getProjectPath( repositoryId, namespace, projectId ) );
970 public Collection<ArtifactMetadata> getArtifacts( String repositoryId, String namespace, String projectId,
971 String projectVersion )
972 throws MetadataResolutionException
974 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
978 Node root = session.getRootNode();
979 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
981 if ( root.hasNode( path ) )
983 Node node = root.getNode( path );
985 for ( Node n : JcrUtils.getChildNodes( node ) )
987 artifacts.add( getArtifactFromNode( repositoryId, n ) );
991 catch ( RepositoryException e )
993 throw new MetadataResolutionException( e.getMessage(), e );
1000 throws MetadataRepositoryException
1006 catch ( RepositoryException e )
1008 throw new MetadataRepositoryException( e.getMessage(), e );
1012 public void revert()
1013 throws MetadataRepositoryException
1017 session.refresh( false );
1019 catch ( RepositoryException e )
1021 throw new MetadataRepositoryException( e.getMessage(), e );
1030 private ArtifactMetadata getArtifactFromNode( String repositoryId, Node artifactNode )
1031 throws RepositoryException
1033 String id = artifactNode.getName();
1035 ArtifactMetadata artifact = new ArtifactMetadata();
1036 artifact.setId( id );
1037 artifact.setRepositoryId( repositoryId );
1039 Node projectVersionNode = artifactNode.getParent();
1040 Node projectNode = projectVersionNode.getParent();
1041 Node namespaceNode = projectNode.getParent();
1043 artifact.setNamespace( namespaceNode.getProperty( "namespace" ).getString() );
1044 artifact.setProject( projectNode.getName() );
1045 artifact.setProjectVersion( projectVersionNode.getName() );
1046 artifact.setVersion( artifactNode.hasProperty( "version" )
1047 ? artifactNode.getProperty( "version" ).getString()
1048 : projectVersionNode.getName() );
1050 if ( artifactNode.hasProperty( JCR_LAST_MODIFIED ) )
1052 artifact.setFileLastModified( artifactNode.getProperty( JCR_LAST_MODIFIED ).getDate().getTimeInMillis() );
1055 if ( artifactNode.hasProperty( "whenGathered" ) )
1057 artifact.setWhenGathered( artifactNode.getProperty( "whenGathered" ).getDate().getTime() );
1060 if ( artifactNode.hasProperty( "size" ) )
1062 artifact.setSize( artifactNode.getProperty( "size" ).getLong() );
1065 if ( artifactNode.hasProperty( "md5" ) )
1067 artifact.setMd5( artifactNode.getProperty( "md5" ).getString() );
1070 if ( artifactNode.hasProperty( "sha1" ) )
1072 artifact.setSha1( artifactNode.getProperty( "sha1" ).getString() );
1075 for ( Node n : JcrUtils.getChildNodes( artifactNode ) )
1077 if ( n.isNodeType( FACET_NODE_TYPE ) )
1079 String name = n.getName();
1080 MetadataFacetFactory factory = metadataFacetFactories.get( name );
1081 if ( factory == null )
1083 log.error( "Attempted to load unknown project version metadata facet: " + name );
1087 MetadataFacet facet = factory.createMetadataFacet();
1088 Map<String, String> map = new HashMap<String, String>();
1089 for ( Property p : JcrUtils.getProperties( n ) )
1091 String property = p.getName();
1092 if ( !property.startsWith( "jcr:" ) )
1094 map.put( property, p.getString() );
1097 facet.fromProperties( map );
1098 artifact.addFacet( facet );
1105 private static String getPropertyString( Node node, String name )
1106 throws RepositoryException
1108 return node.hasProperty( name ) ? node.getProperty( name ).getString() : null;
1111 private Collection<String> getNodeNames( String path )
1112 throws MetadataResolutionException
1114 List<String> names = new ArrayList<String>();
1118 Node root = session.getRootNode();
1120 Node repository = root.getNode( path );
1122 NodeIterator nodes = repository.getNodes();
1123 while ( nodes.hasNext() )
1125 Node node = nodes.nextNode();
1126 names.add( node.getName() );
1129 catch ( PathNotFoundException e )
1131 // ignore repo not found for now
1133 catch ( RepositoryException e )
1135 throw new MetadataResolutionException( e.getMessage(), e );
1141 private static String getRepositoryPath( String repositoryId )
1143 return "repositories/" + repositoryId;
1146 private static String getRepositoryContentPath( String repositoryId )
1148 return getRepositoryPath( repositoryId ) + "/content/";
1151 private static String getFacetPath( String repositoryId, String facetId )
1153 return getRepositoryPath( repositoryId ) + "/facets/" + facetId;
1156 private static String getNamespacePath( String repositoryId, String namespace )
1158 return getRepositoryContentPath( repositoryId ) + namespace.replace( '.', '/' );
1161 private static String getProjectPath( String repositoryId, String namespace, String projectId )
1163 return getNamespacePath( repositoryId, namespace ) + "/" + projectId;
1166 private static String getProjectVersionPath( String repositoryId, String namespace, String projectId,
1167 String projectVersion )
1169 return getProjectPath( repositoryId, namespace, projectId ) + "/" + projectVersion;
1172 private static String getArtifactPath( String repositoryId, String namespace, String projectId,
1173 String projectVersion, String id )
1175 return getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/" + id;
1178 private Node getOrAddNodeByPath( Node baseNode, String name )
1179 throws RepositoryException
1181 Node node = baseNode;
1182 for ( String n : name.split( "/" ) )
1184 node = JcrUtils.getOrAddNode( node, n );
1189 private static String getFacetPath( String repositoryId, String facetId, String name )
1191 return getFacetPath( repositoryId, facetId ) + "/" + name;
1194 private Node getOrAddRepositoryNode( String repositoryId )
1195 throws RepositoryException
1197 Node root = session.getRootNode();
1198 Node node = JcrUtils.getOrAddNode( root, "repositories" );
1199 node = JcrUtils.getOrAddNode( node, repositoryId );
1203 private Node getOrAddRepositoryContentNode( String repositoryId )
1204 throws RepositoryException
1206 Node node = getOrAddRepositoryNode( repositoryId );
1207 return JcrUtils.getOrAddNode( node, "content" );
1210 private Node getOrAddNamespaceNode( String repositoryId, String namespace )
1211 throws RepositoryException
1213 Node repo = getOrAddRepositoryContentNode( repositoryId );
1214 return getOrAddNodeByPath( repo, namespace.replace( '.', '/' ) );
1217 private Node getOrAddProjectNode( String repositoryId, String namespace, String projectId )
1218 throws RepositoryException
1220 Node namespaceNode = getOrAddNamespaceNode( repositoryId, namespace );
1221 return JcrUtils.getOrAddNode( namespaceNode, projectId );
1224 private Node getOrAddProjectVersionNode( String repositoryId, String namespace, String projectId,
1225 String projectVersion )
1226 throws RepositoryException
1228 Node projectNode = getOrAddProjectNode( repositoryId, namespace, projectId );
1229 return JcrUtils.getOrAddNode( projectNode, projectVersion );
1232 private Node getOrAddArtifactNode( String repositoryId, String namespace, String projectId, String projectVersion,
1234 throws RepositoryException
1236 Node versionNode = getOrAddProjectVersionNode( repositoryId, namespace, projectId, projectVersion );
1237 Node node = JcrUtils.getOrAddNode( versionNode, id );
1238 node.addMixin( ARTIFACT_NODE_TYPE );
1242 private static Calendar createCalendar( Date time )
1244 Calendar cal = Calendar.getInstance();
1245 cal.setTime( time );
1249 private String join( Collection<String> ids )
1251 if ( ids != null && !ids.isEmpty() )
1253 StringBuilder s = new StringBuilder();
1254 for ( String id : ids )
1259 return s.substring( 0, s.length() - 1 );
1264 public Session getJcrSession()