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 com.google.common.collect.ImmutableMap;
23 import org.apache.archiva.metadata.model.ArtifactMetadata;
24 import org.apache.archiva.metadata.model.CiManagement;
25 import org.apache.archiva.metadata.model.Dependency;
26 import org.apache.archiva.metadata.model.FacetedMetadata;
27 import org.apache.archiva.metadata.model.IssueManagement;
28 import org.apache.archiva.metadata.model.License;
29 import org.apache.archiva.metadata.model.MailingList;
30 import org.apache.archiva.metadata.model.MetadataFacet;
31 import org.apache.archiva.metadata.model.MetadataFacetFactory;
32 import org.apache.archiva.metadata.model.Organization;
33 import org.apache.archiva.metadata.model.ProjectMetadata;
34 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
35 import org.apache.archiva.metadata.model.ProjectVersionReference;
36 import org.apache.archiva.metadata.model.Scm;
37 import org.apache.archiva.metadata.model.maven2.MavenArtifactFacet;
38 import org.apache.archiva.metadata.repository.MetadataRepository;
39 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
40 import org.apache.archiva.metadata.repository.MetadataResolutionException;
41 import org.apache.archiva.metadata.repository.RepositorySession;
42 import org.apache.archiva.metadata.repository.stats.model.RepositoryStatistics;
43 import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsProvider;
44 import org.apache.commons.lang.StringUtils;
45 import org.apache.jackrabbit.commons.JcrUtils;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 import javax.jcr.NamespaceRegistry;
50 import javax.jcr.Node;
51 import javax.jcr.PathNotFoundException;
52 import javax.jcr.Property;
53 import javax.jcr.Repository;
54 import javax.jcr.RepositoryException;
55 import javax.jcr.Session;
56 import javax.jcr.SimpleCredentials;
57 import javax.jcr.ValueFactory;
58 import javax.jcr.Workspace;
59 import javax.jcr.nodetype.NodeTypeManager;
60 import javax.jcr.nodetype.NodeTypeTemplate;
61 import javax.jcr.query.Query;
62 import javax.jcr.query.QueryManager;
63 import javax.jcr.query.QueryResult;
64 import javax.jcr.query.Row;
65 import javax.jcr.query.RowIterator;
66 import java.util.ArrayList;
67 import java.util.Arrays;
68 import java.util.Calendar;
69 import java.util.Collection;
70 import java.util.Collections;
71 import java.util.Date;
72 import java.util.HashMap;
73 import java.util.Iterator;
74 import java.util.LinkedHashSet;
75 import java.util.List;
77 import java.util.Map.Entry;
81 * TODO below: revise storage format for project version metadata
82 * TODO revise reference storage
84 public class JcrMetadataRepository
85 implements MetadataRepository, RepositoryStatisticsProvider
88 private static final String JCR_LAST_MODIFIED = "jcr:lastModified";
90 static final String NAMESPACE_NODE_TYPE = "archiva:namespace";
92 static final String PROJECT_NODE_TYPE = "archiva:project";
94 static final String PROJECT_VERSION_NODE_TYPE = "archiva:projectVersion";
96 static final String ARTIFACT_NODE_TYPE = "archiva:artifact";
97 private static final String QUERY_ARTIFACT_1 = "SELECT * FROM [" + ARTIFACT_NODE_TYPE + "] AS artifact WHERE ISDESCENDANTNODE(artifact,'/";
99 static final String FACET_NODE_TYPE = "archiva:facet";
101 static final String QUERY_ARTIFACTS_BY_PROJECT_VERSION_1 = "SELECT * FROM [" + PROJECT_VERSION_NODE_TYPE + "] AS projectVersion INNER JOIN [" + ARTIFACT_NODE_TYPE
102 + "] AS artifact ON ISCHILDNODE(artifact, projectVersion) INNER JOIN [" + FACET_NODE_TYPE
103 + "] AS facet ON ISCHILDNODE(facet, projectVersion) WHERE ([facet].[";
104 static final String QUERY_ARTIFACTS_BY_PROJECT_VERSION_2= "] = $value)";
106 static final String QUERY_ARTIFACTS_BY_METADATA_1 = "SELECT * FROM [" + ARTIFACT_NODE_TYPE + "] AS artifact INNER JOIN [" + FACET_NODE_TYPE
107 + "] AS facet ON ISCHILDNODE(facet, artifact) WHERE ([facet].[";
108 static final String QUERY_ARTIFACTS_BY_METADATA_2 = "] = $value)";
110 static final String QUERY_ARTIFACTS_BY_PROPERTY_1 = "SELECT * FROM [" + PROJECT_VERSION_NODE_TYPE + "] AS projectVersion INNER JOIN [" + ARTIFACT_NODE_TYPE
111 + "] AS artifact ON ISCHILDNODE(artifact, projectVersion) WHERE ([projectVersion].[";
112 static final String QUERY_ARTIFACTS_BY_PROPERTY_2 = "] = $value)";
115 private static final String DEPENDENCY_NODE_TYPE = "archiva:dependency";
116 private static final String QUERY_ARTIFACT_2 = "')";
118 private final Map<String, MetadataFacetFactory> metadataFacetFactories;
120 private Logger log = LoggerFactory.getLogger( JcrMetadataRepository.class );
122 private Repository repository;
124 public JcrMetadataRepository( Map<String, MetadataFacetFactory> metadataFacetFactories, Repository repository )
125 throws RepositoryException
127 this.metadataFacetFactories = metadataFacetFactories;
128 this.repository = repository;
132 public static void initializeNodeTypes( Session session )
133 throws RepositoryException
136 // TODO: consider using namespaces for facets instead of the current approach:
137 // (if used, check if actually called by normal injection)
138 // for ( String facetId : metadataFacetFactories.keySet() )
140 // session.getWorkspace().getNamespaceRegistry().registerNamespace( facetId, facetId );
142 Workspace workspace = session.getWorkspace();
143 NamespaceRegistry registry = workspace.getNamespaceRegistry();
145 if ( !Arrays.asList( registry.getPrefixes() ).contains( "archiva" ) )
147 registry.registerNamespace( "archiva", "http://archiva.apache.org/jcr/" );
150 NodeTypeManager nodeTypeManager = workspace.getNodeTypeManager();
151 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.NAMESPACE_NODE_TYPE );
152 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.PROJECT_NODE_TYPE );
153 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.PROJECT_VERSION_NODE_TYPE );
154 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.ARTIFACT_NODE_TYPE );
155 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.FACET_NODE_TYPE );
156 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.DEPENDENCY_NODE_TYPE );
161 private static void registerMixinNodeType( NodeTypeManager nodeTypeManager, String name )
162 throws RepositoryException
164 // for now just don't re-create - but in future if we change the definition, make sure to remove first as an
166 if ( !nodeTypeManager.hasNodeType( name ) )
168 NodeTypeTemplate nodeType = nodeTypeManager.createNodeTypeTemplate();
169 nodeType.setMixin( true );
170 nodeType.setName( name );
171 nodeTypeManager.registerNodeType( nodeType, false );
175 private Session getSession(RepositorySession repositorySession) throws MetadataRepositoryException {
176 if (repositorySession instanceof JcrSession) {
177 return ( (JcrSession) repositorySession ).getJcrSession();
179 throw new MetadataRepositoryException( "The given session object is not a JcrSession instance: " + repositorySession.getClass( ).getName( ) );
184 public void updateProject( RepositorySession session, String repositoryId, ProjectMetadata project )
185 throws MetadataRepositoryException
187 final Session jcrSession = getSession( session );
188 updateProject( jcrSession, repositoryId, project.getNamespace(), project.getId() );
191 private void updateProject( Session jcrSession, String repositoryId, String namespace, String projectId )
192 throws MetadataRepositoryException
194 updateNamespace( jcrSession , repositoryId, namespace );
198 getOrAddProjectNode( jcrSession, repositoryId, namespace, projectId );
200 catch ( RepositoryException e )
202 throw new MetadataRepositoryException( e.getMessage(), e );
207 public void updateArtifact( RepositorySession session, String repositoryId, String namespace, String projectId, String projectVersion,
208 ArtifactMetadata artifactMeta )
209 throws MetadataRepositoryException
211 final Session jcrSession = getSession( session );
212 updateNamespace( session, repositoryId, namespace );
217 getOrAddArtifactNode( jcrSession, repositoryId, namespace, projectId, projectVersion, artifactMeta.getId() );
219 Calendar cal = Calendar.getInstance();
220 cal.setTime( artifactMeta.getFileLastModified() );
221 node.setProperty( JCR_LAST_MODIFIED, cal );
223 cal = Calendar.getInstance();
224 cal.setTime( artifactMeta.getWhenGathered() );
225 node.setProperty( "whenGathered", cal );
227 node.setProperty( "size", artifactMeta.getSize() );
228 node.setProperty( "md5", artifactMeta.getMd5() );
229 node.setProperty( "sha1", artifactMeta.getSha1() );
231 node.setProperty( "version", artifactMeta.getVersion() );
233 // iterate over available facets to update/add/remove from the artifactMetadata
234 for ( String facetId : metadataFacetFactories.keySet() )
236 MetadataFacet metadataFacet = artifactMeta.getFacet( facetId );
237 if ( metadataFacet == null )
241 if ( node.hasNode( facetId ) )
243 node.getNode( facetId ).remove();
245 if ( metadataFacet != null )
247 // recreate, to ensure properties are removed
248 Node n = node.addNode( facetId );
249 n.addMixin( FACET_NODE_TYPE );
251 for ( Map.Entry<String, String> entry : metadataFacet.toProperties().entrySet() )
253 n.setProperty( entry.getKey(), entry.getValue() );
258 catch ( RepositoryException e )
260 throw new MetadataRepositoryException( e.getMessage(), e );
265 public void updateProjectVersion( RepositorySession session, String repositoryId, String namespace, String projectId,
266 ProjectVersionMetadata versionMetadata )
267 throws MetadataRepositoryException
269 final Session jcrSession = getSession( session );
270 updateProject( jcrSession, repositoryId, namespace, projectId );
275 getOrAddProjectVersionNode( jcrSession, repositoryId, namespace, projectId, versionMetadata.getId() );
277 versionNode.setProperty( "name", versionMetadata.getName() );
278 versionNode.setProperty( "description", versionMetadata.getDescription() );
279 versionNode.setProperty( "url", versionMetadata.getUrl() );
280 versionNode.setProperty( "incomplete", versionMetadata.isIncomplete() );
282 // FIXME: decide how to treat these in the content repo
283 if ( versionMetadata.getScm() != null )
285 versionNode.setProperty( "scm.connection", versionMetadata.getScm().getConnection() );
286 versionNode.setProperty( "scm.developerConnection", versionMetadata.getScm().getDeveloperConnection() );
287 versionNode.setProperty( "scm.url", versionMetadata.getScm().getUrl() );
289 if ( versionMetadata.getCiManagement() != null )
291 versionNode.setProperty( "ci.system", versionMetadata.getCiManagement().getSystem() );
292 versionNode.setProperty( "ci.url", versionMetadata.getCiManagement().getUrl() );
294 if ( versionMetadata.getIssueManagement() != null )
296 versionNode.setProperty( "issue.system", versionMetadata.getIssueManagement().getSystem() );
297 versionNode.setProperty( "issue.url", versionMetadata.getIssueManagement().getUrl() );
299 if ( versionMetadata.getOrganization() != null )
301 versionNode.setProperty( "org.name", versionMetadata.getOrganization().getName() );
302 versionNode.setProperty( "org.url", versionMetadata.getOrganization().getUrl() );
305 for ( License license : versionMetadata.getLicenses() )
307 versionNode.setProperty( "license." + i + ".name", license.getName() );
308 versionNode.setProperty( "license." + i + ".url", license.getUrl() );
312 for ( MailingList mailingList : versionMetadata.getMailingLists() )
314 versionNode.setProperty( "mailingList." + i + ".archive", mailingList.getMainArchiveUrl() );
315 versionNode.setProperty( "mailingList." + i + ".name", mailingList.getName() );
316 versionNode.setProperty( "mailingList." + i + ".post", mailingList.getPostAddress() );
317 versionNode.setProperty( "mailingList." + i + ".unsubscribe", mailingList.getUnsubscribeAddress() );
318 versionNode.setProperty( "mailingList." + i + ".subscribe", mailingList.getSubscribeAddress() );
319 versionNode.setProperty( "mailingList." + i + ".otherArchives",
320 join( mailingList.getOtherArchives() ) );
324 if ( !versionMetadata.getDependencies().isEmpty() )
326 Node dependenciesNode = JcrUtils.getOrAddNode( versionNode, "dependencies" );
328 for ( Dependency dependency : versionMetadata.getDependencies() )
330 // Note that we deliberately don't alter the namespace path - not enough dependencies for
331 // number of nodes at a given depth to be an issue. Similarly, we don't add subnodes for each
332 // component of the ID as that creates extra depth and causes a great cost in space and memory
334 // FIXME: change group ID to namespace
335 // FIXME: change to artifact's ID - this is constructed by the Maven 2 format for now.
336 // This won't support types where the extension doesn't match the type.
337 // (see also Maven2RepositoryStorage#readProjectVersionMetadata construction of POM)
339 dependency.getGroupId() + ";" + dependency.getArtifactId() + "-" + dependency.getVersion();
340 if ( dependency.getClassifier() != null )
342 id += "-" + dependency.getClassifier();
344 id += "." + dependency.getType();
346 Node n = JcrUtils.getOrAddNode( dependenciesNode, id );
347 n.addMixin( DEPENDENCY_NODE_TYPE );
349 // FIXME: remove temp code just to make it keep working
350 n.setProperty( "groupId", dependency.getGroupId() );
351 n.setProperty( "artifactId", dependency.getArtifactId() );
352 n.setProperty( "version", dependency.getVersion() );
353 n.setProperty( "type", dependency.getType() );
354 n.setProperty( "classifier", dependency.getClassifier() );
355 n.setProperty( "scope", dependency.getScope() );
356 n.setProperty( "systemPath", dependency.getSystemPath() );
357 n.setProperty( "optional", dependency.isOptional() );
359 // node has no native content at this time, just facets
360 // no need to list a type as it's implied by the path. Parents are Maven specific.
362 // FIXME: add scope, systemPath, type, version, classifier & maven2 specific IDs as a facet
363 // (should also have been added to the Dependency)
365 // TODO: add a property that is a weak reference to the originating artifact, creating it if
366 // necessary (without adding the archiva:artifact mixin so that it doesn't get listed as an
367 // artifact, which gives a different meaning to "incomplete" which is a known local project
368 // that doesn't have metadata yet but has artifacts). (Though we may want to give it the
369 // artifact mixin and another property to identify all non-local artifacts for the closure
374 for ( MetadataFacet facet : versionMetadata.getFacetList() )
376 // recreate, to ensure properties are removed
377 if ( versionNode.hasNode( facet.getFacetId() ) )
379 versionNode.getNode( facet.getFacetId() ).remove();
381 Node n = versionNode.addNode( facet.getFacetId() );
382 n.addMixin( FACET_NODE_TYPE );
384 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() )
386 n.setProperty( entry.getKey(), entry.getValue() );
390 catch ( RepositoryException e )
392 throw new MetadataRepositoryException( e.getMessage(), e );
396 private void updateNamespace(Session jcrSession, String repositoryId, String namespace) throws MetadataRepositoryException
400 Node node = getOrAddNamespaceNode( jcrSession, repositoryId, namespace );
401 node.setProperty( "namespace", namespace );
403 catch ( RepositoryException e )
405 throw new MetadataRepositoryException( e.getMessage(), e );
410 public void updateNamespace( RepositorySession session, String repositoryId, String namespace )
411 throws MetadataRepositoryException
413 updateNamespace( getSession(session), repositoryId, namespace );
417 public void removeProject( RepositorySession session, String repositoryId, String namespace, String projectId )
418 throws MetadataRepositoryException
420 final Session jcrSession = getSession( session );
423 Node root = jcrSession.getRootNode();
424 String namespacePath = getNamespacePath( repositoryId, namespace );
426 if ( root.hasNode( namespacePath ) )
428 Iterator<Node> nodeIterator = JcrUtils.getChildNodes( root.getNode( namespacePath ) ).iterator();
429 while ( nodeIterator.hasNext() )
431 Node node = nodeIterator.next();
432 if ( node.isNodeType( PROJECT_NODE_TYPE ) && projectId.equals( node.getName() ) )
440 catch ( RepositoryException e )
442 throw new MetadataRepositoryException( e.getMessage(), e );
449 public boolean hasMetadataFacet( RepositorySession session, String repositoryId, String facetId )
450 throws MetadataRepositoryException
452 final Session jcrSession = getSession( session );
455 Node node = jcrSession.getRootNode().getNode( getFacetPath( repositoryId, facetId ) );
456 return node.getNodes().hasNext();
458 catch ( PathNotFoundException e )
460 // ignored - the facet doesn't exist, so return false
463 catch ( RepositoryException e )
465 throw new MetadataRepositoryException( e.getMessage(), e );
470 public List<String> getMetadataFacets( RepositorySession session, String repositoryId, String facetId )
471 throws MetadataRepositoryException
473 final Session jcrSession = getSession( session );
474 List<String> facets = new ArrayList<>();
478 // no need to construct node-by-node here, as we'll find in the next instance, the facet names have / and
479 // are paths themselves
480 Node node = jcrSession.getRootNode().getNode( getFacetPath( repositoryId, facetId ) );
482 // TODO: this is a bit awkward. Might be better to review the purpose of this function - why is the list of
484 recurse( facets, "", node );
486 catch ( PathNotFoundException e )
488 // ignored - the facet doesn't exist, so return the empty list
490 catch ( RepositoryException e )
492 throw new MetadataRepositoryException( e.getMessage(), e );
497 private void recurse( List<String> facets, String prefix, Node node )
498 throws RepositoryException
500 for ( Node n : JcrUtils.getChildNodes( node ) )
502 String name = prefix + "/" + n.getName();
505 recurse( facets, name, n );
509 // strip leading / first
510 facets.add( name.substring( 1 ) );
516 public MetadataFacet getMetadataFacet( RepositorySession session, String repositoryId, String facetId, String name )
517 throws MetadataRepositoryException
519 final Session jcrSession = getSession( session );
520 MetadataFacet metadataFacet = null;
523 Node root = jcrSession.getRootNode();
524 Node node = root.getNode( getFacetPath( repositoryId, facetId, name ) );
526 if ( metadataFacetFactories == null )
528 return metadataFacet;
531 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId );
532 if ( metadataFacetFactory != null )
534 metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name );
535 Map<String, String> map = new HashMap<>();
536 for ( Property property : JcrUtils.getProperties( node ) )
538 String p = property.getName();
539 if ( !p.startsWith( "jcr:" ) )
541 map.put( p, property.getString() );
544 metadataFacet.fromProperties( map );
547 catch ( PathNotFoundException e )
549 // ignored - the facet doesn't exist, so return null
551 catch ( RepositoryException e )
553 throw new MetadataRepositoryException( e.getMessage(), e );
555 return metadataFacet;
559 public void addMetadataFacet( RepositorySession session, String repositoryId, MetadataFacet metadataFacet )
560 throws MetadataRepositoryException
562 final Session jcrSession = getSession( session );
565 Node repo = getOrAddRepositoryNode( jcrSession, repositoryId );
566 Node facets = JcrUtils.getOrAddNode( repo, "facets" );
568 String id = metadataFacet.getFacetId();
569 Node facetNode = JcrUtils.getOrAddNode( facets, id );
571 Node node = getOrAddNodeByPath( facetNode, metadataFacet.getName() );
573 for ( Map.Entry<String, String> entry : metadataFacet.toProperties().entrySet() )
575 node.setProperty( entry.getKey(), entry.getValue() );
578 catch ( RepositoryException e )
580 throw new MetadataRepositoryException( e.getMessage(), e );
585 public void removeNamespace( RepositorySession session, String repositoryId, String projectId )
586 throws MetadataRepositoryException
588 final Session jcrSession = getSession( session );
591 Node root = jcrSession.getRootNode();
592 String path = getNamespacePath( repositoryId, projectId );
593 if ( root.hasNode( path ) )
595 Node node = root.getNode( path );
596 if ( node.isNodeType( NAMESPACE_NODE_TYPE ) )
602 catch ( RepositoryException e )
604 throw new MetadataRepositoryException( e.getMessage(), e );
609 public void removeMetadataFacets( RepositorySession session, String repositoryId, String facetId )
610 throws MetadataRepositoryException
612 final Session jcrSession = getSession( session );
615 Node root = jcrSession.getRootNode();
616 String path = getFacetPath( repositoryId, facetId );
617 if ( root.hasNode( path ) )
619 root.getNode( path ).remove();
622 catch ( RepositoryException e )
624 throw new MetadataRepositoryException( e.getMessage(), e );
629 public void removeMetadataFacet( RepositorySession session, String repositoryId, String facetId, String name )
630 throws MetadataRepositoryException
632 final Session jcrSession = getSession( session );
635 Node root = jcrSession.getRootNode();
636 String path = getFacetPath( repositoryId, facetId, name );
637 if ( root.hasNode( path ) )
639 Node node = root.getNode( path );
642 // also remove empty container nodes
643 Node parent = node.getParent();
647 while ( !node.hasNodes() );
650 catch ( RepositoryException e )
652 throw new MetadataRepositoryException( e.getMessage(), e );
657 public List<ArtifactMetadata> getArtifactsByDateRange( RepositorySession session, String repoId, Date startTime, Date endTime )
658 throws MetadataRepositoryException
660 final Session jcrSession = getSession( session );
662 List<ArtifactMetadata> artifacts;
664 String q = getArtifactQuery( repoId );
666 if ( startTime != null )
668 q += " AND [whenGathered] >= $start";
670 if ( endTime != null )
672 q += " AND [whenGathered] <= $end";
677 Query query = jcrSession.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
678 ValueFactory valueFactory = jcrSession.getValueFactory();
679 if ( startTime != null )
681 query.bindValue( "start", valueFactory.createValue( createCalendar( startTime ) ) );
683 if ( endTime != null )
685 query.bindValue( "end", valueFactory.createValue( createCalendar( endTime ) ) );
687 QueryResult result = query.execute();
689 artifacts = new ArrayList<>();
690 for ( Node n : JcrUtils.getNodes( result ) )
692 artifacts.add( getArtifactFromNode( repoId, n ) );
695 catch ( RepositoryException e )
697 throw new MetadataRepositoryException( e.getMessage(), e );
704 public List<ArtifactMetadata> getArtifactsByChecksum( RepositorySession session, String repositoryId, String checksum )
705 throws MetadataRepositoryException
707 final Session jcrSession = getSession( session );
708 List<ArtifactMetadata> artifacts;
710 String q = getArtifactQuery( repositoryId ) + " AND ([sha1] = $checksum OR [md5] = $checksum)";
714 Query query = jcrSession.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
715 ValueFactory valueFactory = jcrSession.getValueFactory();
716 query.bindValue( "checksum", valueFactory.createValue( checksum ) );
717 QueryResult result = query.execute();
719 artifacts = new ArrayList<>();
720 for ( Node n : JcrUtils.getNodes( result ) )
722 artifacts.add( getArtifactFromNode( repositoryId, n ) );
725 catch ( RepositoryException e )
727 throw new MetadataRepositoryException( e.getMessage(), e );
732 private List<ArtifactMetadata> runJcrQuery( Session jcrSession, String repositoryId, String q, Map<String, String> bindings )
733 throws MetadataRepositoryException
735 List<ArtifactMetadata> artifacts;
736 if ( repositoryId != null )
738 q += " AND ISDESCENDANTNODE(artifact,'/" + getRepositoryContentPath( repositoryId ) + "')";
741 log.info( "Running JCR Query: {}", q );
745 Query query = jcrSession.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
746 ValueFactory valueFactory = jcrSession.getValueFactory();
747 for ( Entry<String, String> entry : bindings.entrySet() )
749 query.bindValue( entry.getKey(), valueFactory.createValue( entry.getValue() ) );
751 long start = Calendar.getInstance().getTimeInMillis();
752 QueryResult result = query.execute();
753 long end = Calendar.getInstance().getTimeInMillis();
754 log.info( "JCR Query ran in {} milliseconds: {}", end - start, q );
756 artifacts = new ArrayList<>();
757 RowIterator rows = result.getRows();
758 while ( rows.hasNext() )
760 Row row = rows.nextRow();
761 Node node = row.getNode( "artifact" );
762 artifacts.add( getArtifactFromNode( repositoryId, node ) );
765 catch ( RepositoryException e )
767 throw new MetadataRepositoryException( e.getMessage(), e );
769 log.info( "Artifacts found {}", artifacts.size() );
770 for ( ArtifactMetadata meta : artifacts )
772 log.info( "Artifact: " + meta.getVersion() + " " + meta.getFacetList() );
778 public List<ArtifactMetadata> getArtifactsByProjectVersionMetadata( RepositorySession session, String key, String value, String repositoryId )
779 throws MetadataRepositoryException
781 final Session jcrSession = getSession( session );
782 final String q = new StringBuilder( QUERY_ARTIFACTS_BY_PROJECT_VERSION_1 ).append( key ).append( QUERY_ARTIFACTS_BY_PROJECT_VERSION_2 ).toString();
783 return runJcrQuery( jcrSession, repositoryId, q, ImmutableMap.of( "value", value ) );
788 public List<ArtifactMetadata> getArtifactsByMetadata( RepositorySession session, String key, String value, String repositoryId )
789 throws MetadataRepositoryException
791 final Session jcrSession = getSession( session );
792 final String q = new StringBuilder( QUERY_ARTIFACTS_BY_METADATA_1 ).append( key ).append( QUERY_ARTIFACTS_BY_METADATA_2 ).toString( );
793 return runJcrQuery( jcrSession, repositoryId, q, ImmutableMap.of( "value", value ) );
798 public List<ArtifactMetadata> getArtifactsByProperty( RepositorySession session, String key, String value, String repositoryId )
799 throws MetadataRepositoryException
801 final Session jcrSession = getSession( session );
802 final String q = new StringBuilder( QUERY_ARTIFACTS_BY_PROPERTY_1 ).append( key ).append( QUERY_ARTIFACTS_BY_PROPERTY_2 ).toString();
803 return runJcrQuery( jcrSession, repositoryId, q, ImmutableMap.of( "value", value ) );
808 public void removeRepository( RepositorySession session, String repositoryId )
809 throws MetadataRepositoryException
811 final Session jcrSession = getSession( session );
814 Node root = jcrSession.getRootNode();
815 String path = getRepositoryPath( repositoryId );
816 if ( root.hasNode( path ) )
818 root.getNode( path ).remove();
821 catch ( RepositoryException e )
823 throw new MetadataRepositoryException( e.getMessage(), e );
828 public List<ArtifactMetadata> getArtifacts( RepositorySession session, String repositoryId )
829 throws MetadataRepositoryException
831 final Session jcrSession = getSession( session );
832 List<ArtifactMetadata> artifacts;
834 String q = getArtifactQuery( repositoryId );
838 Query query = jcrSession.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
839 QueryResult result = query.execute();
841 artifacts = new ArrayList<>();
842 for ( Node n : JcrUtils.getNodes( result ) )
844 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) )
846 artifacts.add( getArtifactFromNode( repositoryId, n ) );
850 catch ( RepositoryException e )
852 throw new MetadataRepositoryException( e.getMessage(), e );
857 private static String getArtifactQuery( String repositoryId )
859 return new StringBuilder(QUERY_ARTIFACT_1).append(getRepositoryContentPath( repositoryId )).append(QUERY_ARTIFACT_2).toString();
863 public ProjectMetadata getProject( RepositorySession session, String repositoryId, String namespace, String projectId )
864 throws MetadataResolutionException
866 final Session jcrSession;
869 jcrSession = getSession( session );
871 catch ( MetadataRepositoryException e )
873 throw new MetadataResolutionException( e.getMessage() );
875 ProjectMetadata metadata = null;
879 Node root = jcrSession.getRootNode();
881 // basically just checking it exists
882 String path = getProjectPath( repositoryId, namespace, projectId );
883 if ( root.hasNode( path ) )
885 metadata = new ProjectMetadata();
886 metadata.setId( projectId );
887 metadata.setNamespace( namespace );
890 catch ( RepositoryException e )
892 throw new MetadataResolutionException( e.getMessage(), e );
899 public ProjectVersionMetadata getProjectVersion( RepositorySession session, String repositoryId, String namespace, String projectId,
900 String projectVersion )
901 throws MetadataResolutionException
903 final Session jcrSession;
906 jcrSession = getSession( session );
908 catch ( MetadataRepositoryException e )
910 throw new MetadataResolutionException( e.getMessage() );
912 ProjectVersionMetadata versionMetadata;
916 Node root = jcrSession.getRootNode();
918 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
919 if ( !root.hasNode( path ) )
924 Node node = root.getNode( path );
926 versionMetadata = new ProjectVersionMetadata();
927 versionMetadata.setId( projectVersion );
928 versionMetadata.setName( getPropertyString( node, "name" ) );
929 versionMetadata.setDescription( getPropertyString( node, "description" ) );
930 versionMetadata.setUrl( getPropertyString( node, "url" ) );
931 versionMetadata.setIncomplete(
932 node.hasProperty( "incomplete" ) && node.getProperty( "incomplete" ).getBoolean() );
934 // FIXME: decide how to treat these in the content repo
935 String scmConnection = getPropertyString( node, "scm.connection" );
936 String scmDeveloperConnection = getPropertyString( node, "scm.developerConnection" );
937 String scmUrl = getPropertyString( node, "scm.url" );
938 if ( scmConnection != null || scmDeveloperConnection != null || scmUrl != null )
941 scm.setConnection( scmConnection );
942 scm.setDeveloperConnection( scmDeveloperConnection );
943 scm.setUrl( scmUrl );
944 versionMetadata.setScm( scm );
947 String ciSystem = getPropertyString( node, "ci.system" );
948 String ciUrl = getPropertyString( node, "ci.url" );
949 if ( ciSystem != null || ciUrl != null )
951 CiManagement ci = new CiManagement();
952 ci.setSystem( ciSystem );
954 versionMetadata.setCiManagement( ci );
957 String issueSystem = getPropertyString( node, "issue.system" );
958 String issueUrl = getPropertyString( node, "issue.url" );
959 if ( issueSystem != null || issueUrl != null )
961 IssueManagement issueManagement = new IssueManagement();
962 issueManagement.setSystem( issueSystem );
963 issueManagement.setUrl( issueUrl );
964 versionMetadata.setIssueManagement( issueManagement );
967 String orgName = getPropertyString( node, "org.name" );
968 String orgUrl = getPropertyString( node, "org.url" );
969 if ( orgName != null || orgUrl != null )
971 Organization org = new Organization();
972 org.setName( orgName );
973 org.setUrl( orgUrl );
974 versionMetadata.setOrganization( org );
977 boolean done = false;
981 String licenseName = getPropertyString( node, "license." + i + ".name" );
982 String licenseUrl = getPropertyString( node, "license." + i + ".url" );
983 if ( licenseName != null || licenseUrl != null )
985 License license = new License();
986 license.setName( licenseName );
987 license.setUrl( licenseUrl );
988 versionMetadata.addLicense( license );
1001 String mailingListName = getPropertyString( node, "mailingList." + i + ".name" );
1002 if ( mailingListName != null )
1004 MailingList mailingList = new MailingList();
1005 mailingList.setName( mailingListName );
1006 mailingList.setMainArchiveUrl( getPropertyString( node, "mailingList." + i + ".archive" ) );
1007 String n = "mailingList." + i + ".otherArchives";
1008 if ( node.hasProperty( n ) )
1010 mailingList.setOtherArchives( Arrays.asList( getPropertyString( node, n ).split( "," ) ) );
1014 mailingList.setOtherArchives( Collections.<String>emptyList() );
1016 mailingList.setPostAddress( getPropertyString( node, "mailingList." + i + ".post" ) );
1017 mailingList.setSubscribeAddress( getPropertyString( node, "mailingList." + i + ".subscribe" ) );
1018 mailingList.setUnsubscribeAddress( getPropertyString( node, "mailingList." + i + ".unsubscribe" ) );
1019 versionMetadata.addMailingList( mailingList );
1028 if ( node.hasNode( "dependencies" ) )
1030 Node dependenciesNode = node.getNode( "dependencies" );
1031 for ( Node n : JcrUtils.getChildNodes( dependenciesNode ) )
1033 if ( n.isNodeType( DEPENDENCY_NODE_TYPE ) )
1035 Dependency dependency = new Dependency();
1036 // FIXME: correct these properties
1037 dependency.setArtifactId( getPropertyString( n, "artifactId" ) );
1038 dependency.setGroupId( getPropertyString( n, "groupId" ) );
1039 dependency.setClassifier( getPropertyString( n, "classifier" ) );
1040 dependency.setOptional( Boolean.valueOf( getPropertyString( n, "optional" ) ) );
1041 dependency.setScope( getPropertyString( n, "scope" ) );
1042 dependency.setSystemPath( getPropertyString( n, "systemPath" ) );
1043 dependency.setType( getPropertyString( n, "type" ) );
1044 dependency.setVersion( getPropertyString( n, "version" ) );
1045 versionMetadata.addDependency( dependency );
1050 retrieveFacetProperties( versionMetadata, node );
1052 catch ( RepositoryException e )
1054 throw new MetadataResolutionException( e.getMessage(), e );
1057 return versionMetadata;
1060 private void retrieveFacetProperties( FacetedMetadata metadata, Node node ) throws RepositoryException
1062 for ( Node n : JcrUtils.getChildNodes( node ) )
1064 if ( n.isNodeType( FACET_NODE_TYPE ) )
1066 String name = n.getName();
1067 MetadataFacetFactory factory = metadataFacetFactories.get( name );
1068 if ( factory == null )
1070 log.error( "Attempted to load unknown project version metadata facet: {}", name );
1074 MetadataFacet facet = factory.createMetadataFacet();
1075 Map<String, String> map = new HashMap<>();
1076 for ( Property property : JcrUtils.getProperties( n ) )
1078 String p = property.getName();
1079 if ( !p.startsWith( "jcr:" ) )
1081 map.put( p, property.getString() );
1084 facet.fromProperties( map );
1085 metadata.addFacet( facet );
1092 public Collection<String> getArtifactVersions( RepositorySession session, String repositoryId, String namespace, String projectId,
1093 String projectVersion )
1094 throws MetadataResolutionException
1096 final Session jcrSession;
1099 jcrSession = getSession( session );
1101 catch ( MetadataRepositoryException e )
1103 throw new MetadataResolutionException( e.getMessage() );
1105 Set<String> versions = new LinkedHashSet<String>();
1109 Node root = jcrSession.getRootNode();
1111 Node node = root.getNode( getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) );
1113 for ( Node n : JcrUtils.getChildNodes( node ) )
1115 versions.add( n.getProperty( "version" ).getString() );
1118 catch ( PathNotFoundException e )
1120 // ignore repo not found for now
1122 catch ( RepositoryException e )
1124 throw new MetadataResolutionException( e.getMessage(), e );
1131 public Collection<ProjectVersionReference> getProjectReferences( RepositorySession session, String repositoryId, String namespace,
1132 String projectId, String projectVersion )
1133 throws MetadataResolutionException
1135 final Session jcrSession;
1138 jcrSession = getSession( session );
1140 catch ( MetadataRepositoryException e )
1142 throw new MetadataResolutionException( e.getMessage() );
1145 List<ProjectVersionReference> references = new ArrayList<>();
1147 // TODO: bind variables instead
1148 String q = "SELECT * FROM [archiva:dependency] WHERE ISDESCENDANTNODE([/repositories/" + repositoryId
1149 + "/content]) AND [groupId]='" + namespace + "' AND [artifactId]='" + projectId + "'";
1150 if ( projectVersion != null )
1152 q += " AND [version]='" + projectVersion + "'";
1156 Query query = jcrSession.getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 );
1157 QueryResult result = query.execute();
1159 for ( Node n : JcrUtils.getNodes( result ) )
1161 n = n.getParent(); // dependencies grouping element
1163 n = n.getParent(); // project version
1164 String usedByProjectVersion = n.getName();
1166 n = n.getParent(); // project
1167 String usedByProject = n.getName();
1169 n = n.getParent(); // namespace
1170 String usedByNamespace = n.getProperty( "namespace" ).getString();
1172 ProjectVersionReference ref = new ProjectVersionReference();
1173 ref.setNamespace( usedByNamespace );
1174 ref.setProjectId( usedByProject );
1175 ref.setProjectVersion( usedByProjectVersion );
1176 ref.setReferenceType( ProjectVersionReference.ReferenceType.DEPENDENCY );
1177 references.add( ref );
1180 catch ( RepositoryException e )
1182 throw new MetadataResolutionException( e.getMessage(), e );
1189 public Collection<String> getRootNamespaces( RepositorySession session, String repositoryId )
1190 throws MetadataResolutionException
1192 return getNamespaces(session , repositoryId, null );
1196 public Collection<String> getNamespaces( RepositorySession session, String repositoryId, String baseNamespace )
1197 throws MetadataResolutionException
1199 String path = baseNamespace != null
1200 ? getNamespacePath( repositoryId, baseNamespace )
1201 : getRepositoryContentPath( repositoryId );
1205 return getNodeNames( getSession(session), path, NAMESPACE_NODE_TYPE );
1207 catch ( MetadataRepositoryException e )
1209 throw new MetadataResolutionException( e.getMessage( ) );
1214 public Collection<String> getProjects( RepositorySession session, String repositoryId, String namespace )
1215 throws MetadataResolutionException
1219 return getNodeNames( getSession(session), getNamespacePath( repositoryId, namespace ), PROJECT_NODE_TYPE );
1221 catch ( MetadataRepositoryException e )
1223 throw new MetadataResolutionException( e.getMessage( ) );
1228 public Collection<String> getProjectVersions( RepositorySession session, String repositoryId, String namespace, String projectId )
1229 throws MetadataResolutionException
1233 return getNodeNames( getSession(session), getProjectPath( repositoryId, namespace, projectId ), PROJECT_VERSION_NODE_TYPE );
1235 catch ( MetadataRepositoryException e )
1237 throw new MetadataResolutionException( e.getMessage( ) );
1242 public void removeArtifact( RepositorySession session, ArtifactMetadata artifactMetadata, String baseVersion )
1243 throws MetadataRepositoryException
1245 final Session jcrSession = getSession( session );
1246 String repositoryId = artifactMetadata.getRepositoryId();
1250 Node root = jcrSession.getRootNode();
1252 getProjectVersionPath( repositoryId, artifactMetadata.getNamespace(), artifactMetadata.getProject(),
1255 if ( root.hasNode( path ) )
1257 Node node = root.getNode( path );
1259 for ( Node n : JcrUtils.getChildNodes( node ) )
1261 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) )
1263 if ( n.hasProperty( "version" ) )
1265 String version = n.getProperty( "version" ).getString();
1266 if ( StringUtils.equals( version, artifactMetadata.getVersion() ) )
1276 catch ( RepositoryException e )
1278 throw new MetadataRepositoryException( e.getMessage(), e );
1286 public void removeProjectVersion( RepositorySession session, String repoId, String namespace, String projectId, String projectVersion )
1287 throws MetadataRepositoryException
1289 final Session jcrSession = getSession( session );
1293 String path = getProjectPath( repoId, namespace, projectId );
1294 Node root = jcrSession.getRootNode();
1296 Node nodeAtPath = root.getNode( path );
1298 for ( Node node : JcrUtils.getChildNodes( nodeAtPath ) )
1300 if ( node.isNodeType( PROJECT_VERSION_NODE_TYPE ) && StringUtils.equals( projectVersion,
1307 catch ( RepositoryException e )
1309 throw new MetadataRepositoryException( e.getMessage(), e );
1314 public void removeArtifact( RepositorySession session, String repositoryId, String namespace, String projectId, String projectVersion,
1316 throws MetadataRepositoryException
1318 final Session jcrSession = getSession( session );
1321 Node root = jcrSession.getRootNode();
1322 String path = getArtifactPath( repositoryId, namespace, projectId, projectVersion, id );
1323 if ( root.hasNode( path ) )
1325 root.getNode( path ).remove();
1330 path = getProjectPath( repositoryId, namespace, projectId );
1332 Node nodeAtPath = root.getNode( path );
1334 for ( Node node : JcrUtils.getChildNodes( nodeAtPath ) )
1336 if ( node.isNodeType( PROJECT_VERSION_NODE_TYPE ) //
1337 && StringUtils.equals( node.getName(), projectVersion ) )
1343 catch ( RepositoryException e )
1345 throw new MetadataRepositoryException( e.getMessage(), e );
1350 public void removeArtifact( RepositorySession session, String repositoryId, String namespace, String project, String projectVersion,
1351 MetadataFacet metadataFacet )
1352 throws MetadataRepositoryException
1354 final Session jcrSession = getSession( session );
1357 Node root = jcrSession.getRootNode();
1358 String path = getProjectVersionPath( repositoryId, namespace, project, projectVersion );
1360 if ( root.hasNode( path ) )
1362 Node node = root.getNode( path );
1364 for ( Node n : JcrUtils.getChildNodes( node ) )
1366 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) )
1368 ArtifactMetadata artifactMetadata = getArtifactFromNode( repositoryId, n );
1369 log.debug( "artifactMetadata: {}", artifactMetadata );
1370 MetadataFacet metadataFacetToRemove = artifactMetadata.getFacet( metadataFacet.getFacetId() );
1371 if ( metadataFacetToRemove != null && metadataFacet.equals( metadataFacetToRemove ) )
1379 catch ( RepositoryException e )
1381 throw new MetadataRepositoryException( e.getMessage(), e );
1386 public Collection<ArtifactMetadata> getArtifacts( RepositorySession session, String repositoryId, String namespace, String projectId,
1387 String projectVersion )
1388 throws MetadataResolutionException
1390 final Session jcrSession;
1393 jcrSession = getSession( session );
1395 catch ( MetadataRepositoryException e )
1397 throw new MetadataResolutionException( e.getMessage( ) );
1399 List<ArtifactMetadata> artifacts = new ArrayList<>();
1403 Node root = jcrSession.getRootNode();
1404 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion );
1406 if ( root.hasNode( path ) )
1408 Node node = root.getNode( path );
1410 for ( Node n : JcrUtils.getChildNodes( node ) )
1412 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) )
1414 artifacts.add( getArtifactFromNode( repositoryId, n ) );
1419 catch ( RepositoryException e )
1421 throw new MetadataResolutionException( e.getMessage(), e );
1429 public boolean canObtainAccess( Class<?> aClass )
1431 return aClass == Session.class;
1434 @SuppressWarnings( "unchecked" )
1436 public <T> T obtainAccess( RepositorySession session, Class<T> aClass )
1437 throws MetadataRepositoryException
1439 if ( aClass == Session.class )
1441 return (T) getSession( session );
1443 throw new IllegalArgumentException(
1444 "Access using " + aClass + " is not supported on the JCR metadata storage" );
1449 throws MetadataRepositoryException
1455 * Exact is ignored as we can't do exact search in any property, we need a key
1458 public List<ArtifactMetadata> searchArtifacts( RepositorySession session, String repositoryId, String text, boolean exact )
1459 throws MetadataRepositoryException
1461 return searchArtifacts( session, repositoryId, null, text, exact );
1465 public List<ArtifactMetadata> searchArtifacts( RepositorySession session, String repositoryId, String key, String text, boolean e )
1466 throws MetadataRepositoryException
1468 final Session jcrSession = getSession( session );
1469 String theKey = key == null ? "*" : "[" + key + "]";
1470 String projectVersionCondition =
1471 e ? "(projectVersion." + theKey + " = $value)" : "contains([projectVersion]." + theKey + ", $value)";
1472 String facetCondition = e ? "(facet." + theKey + " = $value)" : "contains([facet]." + theKey + ", $value)";
1474 "SELECT * FROM [" + PROJECT_VERSION_NODE_TYPE + "] AS projectVersion LEFT OUTER JOIN [" + ARTIFACT_NODE_TYPE
1475 + "] AS artifact ON ISCHILDNODE(artifact, projectVersion) LEFT OUTER JOIN [" + FACET_NODE_TYPE
1476 + "] AS facet ON ISCHILDNODE(facet, projectVersion) WHERE (" + projectVersionCondition + " OR "
1477 + facetCondition + ")";
1478 return runJcrQuery( jcrSession, repositoryId, q, ImmutableMap.of( "value", text ) );
1481 private ArtifactMetadata getArtifactFromNode( String repositoryId, Node artifactNode )
1482 throws RepositoryException
1484 String id = artifactNode.getName();
1486 ArtifactMetadata artifact = new ArtifactMetadata();
1487 artifact.setId( id );
1488 artifact.setRepositoryId( repositoryId == null ? artifactNode.getAncestor( 2 ).getName() : repositoryId );
1490 Node projectVersionNode = artifactNode.getParent();
1491 Node projectNode = projectVersionNode.getParent();
1492 Node namespaceNode = projectNode.getParent();
1494 artifact.setNamespace( namespaceNode.getProperty( "namespace" ).getString() );
1495 artifact.setProject( projectNode.getName() );
1496 artifact.setProjectVersion( projectVersionNode.getName() );
1497 artifact.setVersion( artifactNode.hasProperty( "version" )
1498 ? artifactNode.getProperty( "version" ).getString()
1499 : projectVersionNode.getName() );
1501 if ( artifactNode.hasProperty( JCR_LAST_MODIFIED ) )
1503 artifact.setFileLastModified( artifactNode.getProperty( JCR_LAST_MODIFIED ).getDate().getTimeInMillis() );
1506 if ( artifactNode.hasProperty( "whenGathered" ) )
1508 artifact.setWhenGathered( artifactNode.getProperty( "whenGathered" ).getDate().getTime() );
1511 if ( artifactNode.hasProperty( "size" ) )
1513 artifact.setSize( artifactNode.getProperty( "size" ).getLong() );
1516 if ( artifactNode.hasProperty( "md5" ) )
1518 artifact.setMd5( artifactNode.getProperty( "md5" ).getString() );
1521 if ( artifactNode.hasProperty( "sha1" ) )
1523 artifact.setSha1( artifactNode.getProperty( "sha1" ).getString() );
1526 retrieveFacetProperties( artifact, artifactNode );
1530 private static String getPropertyString( Node node, String name )
1531 throws RepositoryException
1533 return node.hasProperty( name ) ? node.getProperty( name ).getString() : null;
1536 private Collection<String> getNodeNames( Session jcrSession, String path, String nodeType )
1537 throws MetadataResolutionException
1540 List<String> names = new ArrayList<>();
1544 Node root = jcrSession.getRootNode();
1546 Node nodeAtPath = root.getNode( path );
1548 for ( Node node : JcrUtils.getChildNodes( nodeAtPath ) )
1550 if ( node.isNodeType( nodeType ) )
1552 names.add( node.getName() );
1556 catch ( PathNotFoundException e )
1558 // ignore repo not found for now
1560 catch ( RepositoryException e )
1562 throw new MetadataResolutionException( e.getMessage(), e );
1568 private static String getRepositoryPath( String repositoryId )
1570 return "repositories/" + repositoryId;
1573 private static String getRepositoryContentPath( String repositoryId )
1575 return getRepositoryPath( repositoryId ) + "/content";
1578 private static String getFacetPath( String repositoryId, String facetId )
1580 return getRepositoryPath( repositoryId ) + "/facets/" + facetId;
1583 private static String getNamespacePath( String repositoryId, String namespace )
1585 return getRepositoryContentPath( repositoryId ) + "/" + namespace.replace( '.', '/' );
1588 private static String getProjectPath( String repositoryId, String namespace, String projectId )
1590 return getNamespacePath( repositoryId, namespace ) + "/" + projectId;
1593 private static String getProjectVersionPath( String repositoryId, String namespace, String projectId,
1594 String projectVersion )
1596 return getProjectPath( repositoryId, namespace, projectId ) + "/" + projectVersion;
1599 private static String getArtifactPath( String repositoryId, String namespace, String projectId,
1600 String projectVersion, String id )
1602 return getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/" + id;
1605 private Node getOrAddNodeByPath( Node baseNode, String name )
1606 throws RepositoryException
1608 return getOrAddNodeByPath( baseNode, name, null );
1611 private Node getOrAddNodeByPath( Node baseNode, String name, String nodeType )
1612 throws RepositoryException
1614 log.debug( "getOrAddNodeByPath" + baseNode + " " + name + " " + nodeType );
1615 Node node = baseNode;
1616 for ( String n : name.split( "/" ) )
1618 node = JcrUtils.getOrAddNode( node, n );
1619 if ( nodeType != null )
1621 node.addMixin( nodeType );
1627 private static String getFacetPath( String repositoryId, String facetId, String name )
1629 return getFacetPath( repositoryId, facetId ) + "/" + name;
1632 private Node getOrAddRepositoryNode( Session jcrSession, String repositoryId )
1633 throws RepositoryException
1635 log.debug( "getOrAddRepositoryNode " + repositoryId );
1636 Node root = jcrSession.getRootNode();
1637 Node node = JcrUtils.getOrAddNode( root, "repositories" );
1638 log.debug( "Repositories " + node );
1639 node = JcrUtils.getOrAddNode( node, repositoryId );
1643 private Node getOrAddRepositoryContentNode( Session jcrSession, String repositoryId )
1644 throws RepositoryException
1646 Node node = getOrAddRepositoryNode( jcrSession, repositoryId );
1647 return JcrUtils.getOrAddNode( node, "content" );
1650 private Node getOrAddNamespaceNode( Session jcrSession, String repositoryId, String namespace )
1651 throws RepositoryException
1653 Node repo = getOrAddRepositoryContentNode( jcrSession, repositoryId );
1654 return getOrAddNodeByPath( repo, namespace.replace( '.', '/' ), NAMESPACE_NODE_TYPE );
1657 private Node getOrAddProjectNode( Session jcrSession, String repositoryId, String namespace, String projectId )
1658 throws RepositoryException
1660 Node namespaceNode = getOrAddNamespaceNode( jcrSession, repositoryId, namespace );
1661 Node node = JcrUtils.getOrAddNode( namespaceNode, projectId );
1662 node.addMixin( PROJECT_NODE_TYPE );
1666 private Node getOrAddProjectVersionNode( Session jcrSession, String repositoryId, String namespace, String projectId,
1667 String projectVersion )
1668 throws RepositoryException
1670 Node projectNode = getOrAddProjectNode( jcrSession, repositoryId, namespace, projectId );
1671 Node node = JcrUtils.getOrAddNode( projectNode, projectVersion );
1672 node.addMixin( PROJECT_VERSION_NODE_TYPE );
1676 private Node getOrAddArtifactNode( Session jcrSession, String repositoryId, String namespace, String projectId, String projectVersion,
1678 throws RepositoryException
1680 Node versionNode = getOrAddProjectVersionNode( jcrSession, repositoryId, namespace, projectId, projectVersion );
1681 Node node = JcrUtils.getOrAddNode( versionNode, id );
1682 node.addMixin( ARTIFACT_NODE_TYPE );
1686 private static Calendar createCalendar( Date time )
1688 Calendar cal = Calendar.getInstance();
1689 cal.setTime( time );
1693 private String join( Collection<String> ids )
1695 if ( ids != null && !ids.isEmpty() )
1697 StringBuilder s = new StringBuilder();
1698 for ( String id : ids )
1703 return s.substring( 0, s.length() - 1 );
1710 public void populateStatistics( RepositorySession repositorySession, MetadataRepository repository, String repositoryId,
1711 RepositoryStatistics repositoryStatistics )
1712 throws MetadataRepositoryException
1714 if ( !( repository instanceof JcrMetadataRepository ) )
1716 throw new MetadataRepositoryException(
1717 "The statistics population is only possible for JcrMetdataRepository implementations" );
1719 Session session = getSession( repositorySession );
1720 // TODO: these may be best as running totals, maintained by observations on the properties in JCR
1724 QueryManager queryManager = session.getWorkspace().getQueryManager();
1726 // TODO: Check, if this is still the case - Switched to Jackrabbit OAK with archiva 3.0
1727 // Former statement: JCR-SQL2 query will not complete on a large repo in Jackrabbit 2.2.0 - see JCR-2835
1728 // Using the JCR-SQL2 variants gives
1729 // "org.apache.lucene.search.BooleanQuery$TooManyClauses: maxClauseCount is set to 1024"
1730 // String whereClause = "WHERE ISDESCENDANTNODE([/repositories/" + repositoryId + "/content])";
1731 // Query query = queryManager.createQuery( "SELECT size FROM [archiva:artifact] " + whereClause,
1732 // Query.JCR_SQL2 );
1733 String whereClause = "WHERE ISDESCENDANTNODE([/repositories/" + repositoryId + "/content])";
1734 Query query = queryManager.createQuery( "SELECT size FROM [archiva:artifact] " + whereClause, Query.JCR_SQL2 );
1736 QueryResult queryResult = query.execute();
1738 Map<String, Integer> totalByType = new HashMap<>();
1739 long totalSize = 0, totalArtifacts = 0;
1740 for ( Row row : JcrUtils.getRows( queryResult ) )
1742 Node n = row.getNode();
1743 totalSize += row.getValue( "size" ).getLong();
1746 if ( n.hasNode( MavenArtifactFacet.FACET_ID ) )
1748 Node facetNode = n.getNode( MavenArtifactFacet.FACET_ID );
1749 type = facetNode.getProperty( "type" ).getString();
1755 Integer prev = totalByType.get( type );
1756 totalByType.put( type, prev != null ? prev + 1 : 1 );
1761 repositoryStatistics.setTotalArtifactCount( totalArtifacts );
1762 repositoryStatistics.setTotalArtifactFileSize( totalSize );
1763 for ( Map.Entry<String, Integer> entry : totalByType.entrySet() )
1765 log.info( "Setting count for type: {} = {}", entry.getKey(), entry.getValue() );
1766 repositoryStatistics.setTotalCountForType( entry.getKey(), entry.getValue() );
1769 // The query ordering is a trick to ensure that the size is correct, otherwise due to lazy init it will be -1
1770 // query = queryManager.createQuery( "SELECT * FROM [archiva:project] " + whereClause, Query.JCR_SQL2 );
1771 query = queryManager.createQuery( "SELECT * FROM [archiva:project] " + whereClause + " ORDER BY [jcr:score]",
1773 repositoryStatistics.setTotalProjectCount( query.execute().getRows().getSize() );
1775 // query = queryManager.createQuery(
1776 // "SELECT * FROM [archiva:namespace] " + whereClause + " AND namespace IS NOT NULL", Query.JCR_SQL2 );
1777 query = queryManager.createQuery(
1778 "SELECT * FROM [archiva:namespace] " + whereClause + " AND namespace IS NOT NULL ORDER BY [jcr:score]",
1780 repositoryStatistics.setTotalGroupCount( query.execute().getRows().getSize() );
1782 catch ( RepositoryException e )
1784 throw new MetadataRepositoryException( e.getMessage(), e );
1789 public Session login() throws RepositoryException
1791 return repository.login(new SimpleCredentials( "admin", "admin".toCharArray() ) );