001 package org.apache.archiva.metadata.repository.jcr; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 import org.apache.archiva.metadata.model.ArtifactMetadata; 023 import org.apache.archiva.metadata.model.CiManagement; 024 import org.apache.archiva.metadata.model.Dependency; 025 import org.apache.archiva.metadata.model.IssueManagement; 026 import org.apache.archiva.metadata.model.License; 027 import org.apache.archiva.metadata.model.MailingList; 028 import org.apache.archiva.metadata.model.MetadataFacet; 029 import org.apache.archiva.metadata.model.MetadataFacetFactory; 030 import org.apache.archiva.metadata.model.Organization; 031 import org.apache.archiva.metadata.model.ProjectMetadata; 032 import org.apache.archiva.metadata.model.ProjectVersionMetadata; 033 import org.apache.archiva.metadata.model.ProjectVersionReference; 034 import org.apache.archiva.metadata.model.Scm; 035 import org.apache.archiva.metadata.repository.MetadataRepository; 036 import org.apache.archiva.metadata.repository.MetadataRepositoryException; 037 import org.apache.archiva.metadata.repository.MetadataResolutionException; 038 import org.apache.commons.lang.StringUtils; 039 import org.apache.jackrabbit.commons.JcrUtils; 040 import org.slf4j.Logger; 041 import org.slf4j.LoggerFactory; 042 043 import javax.jcr.NamespaceRegistry; 044 import javax.jcr.Node; 045 import javax.jcr.NodeIterator; 046 import javax.jcr.PathNotFoundException; 047 import javax.jcr.Property; 048 import javax.jcr.Repository; 049 import javax.jcr.RepositoryException; 050 import javax.jcr.Session; 051 import javax.jcr.SimpleCredentials; 052 import javax.jcr.ValueFactory; 053 import javax.jcr.Workspace; 054 import javax.jcr.nodetype.NodeTypeManager; 055 import javax.jcr.nodetype.NodeTypeTemplate; 056 import javax.jcr.query.Query; 057 import javax.jcr.query.QueryResult; 058 import java.util.ArrayList; 059 import java.util.Arrays; 060 import java.util.Calendar; 061 import java.util.Collection; 062 import java.util.Collections; 063 import java.util.Date; 064 import java.util.HashMap; 065 import java.util.Iterator; 066 import java.util.LinkedHashSet; 067 import java.util.List; 068 import java.util.Map; 069 import java.util.Set; 070 071 /** 072 * @todo below: revise storage format for project version metadata 073 * @todo revise reference storage 074 */ 075 public class JcrMetadataRepository 076 implements MetadataRepository 077 { 078 079 private static final String JCR_LAST_MODIFIED = "jcr:lastModified"; 080 081 static final String NAMESPACE_NODE_TYPE = "archiva:namespace"; 082 083 static final String PROJECT_NODE_TYPE = "archiva:project"; 084 085 static final String PROJECT_VERSION_NODE_TYPE = "archiva:projectVersion"; 086 087 static final String ARTIFACT_NODE_TYPE = "archiva:artifact"; 088 089 static final String FACET_NODE_TYPE = "archiva:facet"; 090 091 private static final String DEPENDENCY_NODE_TYPE = "archiva:dependency"; 092 093 private final Map<String, MetadataFacetFactory> metadataFacetFactories; 094 095 private Logger log = LoggerFactory.getLogger( JcrMetadataRepository.class ); 096 097 private Repository repository; 098 099 private Session jcrSession; 100 101 public JcrMetadataRepository( Map<String, MetadataFacetFactory> metadataFacetFactories, Repository repository ) 102 throws RepositoryException 103 { 104 this.metadataFacetFactories = metadataFacetFactories; 105 this.repository = repository; 106 } 107 108 109 static void initialize( Session session ) 110 throws RepositoryException 111 { 112 113 // TODO: consider using namespaces for facets instead of the current approach: 114 // (if used, check if actually called by normal injection) 115 // for ( String facetId : metadataFacetFactories.keySet() ) 116 // { 117 // session.getWorkspace().getNamespaceRegistry().registerNamespace( facetId, facetId ); 118 // } 119 120 Workspace workspace = session.getWorkspace(); 121 NamespaceRegistry registry = workspace.getNamespaceRegistry(); 122 123 if ( !Arrays.asList( registry.getPrefixes() ).contains( "archiva" ) ) 124 { 125 registry.registerNamespace( "archiva", "http://archiva.apache.org/jcr/" ); 126 } 127 128 NodeTypeManager nodeTypeManager = workspace.getNodeTypeManager(); 129 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.NAMESPACE_NODE_TYPE ); 130 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.PROJECT_NODE_TYPE ); 131 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.PROJECT_VERSION_NODE_TYPE ); 132 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.ARTIFACT_NODE_TYPE ); 133 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.FACET_NODE_TYPE ); 134 registerMixinNodeType( nodeTypeManager, JcrMetadataRepository.DEPENDENCY_NODE_TYPE ); 135 136 } 137 138 private static void registerMixinNodeType( NodeTypeManager nodeTypeManager, String name ) 139 throws RepositoryException 140 { 141 NodeTypeTemplate nodeType = nodeTypeManager.createNodeTypeTemplate(); 142 nodeType.setMixin( true ); 143 nodeType.setName( name ); 144 145 // for now just don't re-create - but in future if we change the definition, make sure to remove first as an 146 // upgrade path 147 if ( !nodeTypeManager.hasNodeType( name ) ) 148 { 149 nodeTypeManager.registerNodeType( nodeType, false ); 150 } 151 } 152 153 public void updateProject( String repositoryId, ProjectMetadata project ) 154 throws MetadataRepositoryException 155 { 156 updateProject( repositoryId, project.getNamespace(), project.getId() ); 157 } 158 159 private void updateProject( String repositoryId, String namespace, String projectId ) 160 throws MetadataRepositoryException 161 { 162 updateNamespace( repositoryId, namespace ); 163 164 try 165 { 166 getOrAddProjectNode( repositoryId, namespace, projectId ); 167 } 168 catch ( RepositoryException e ) 169 { 170 throw new MetadataRepositoryException( e.getMessage(), e ); 171 } 172 } 173 174 public void updateArtifact( String repositoryId, String namespace, String projectId, String projectVersion, 175 ArtifactMetadata artifactMeta ) 176 throws MetadataRepositoryException 177 { 178 updateNamespace( repositoryId, namespace ); 179 180 try 181 { 182 Node node = 183 getOrAddArtifactNode( repositoryId, namespace, projectId, projectVersion, artifactMeta.getId() ); 184 185 Calendar cal = Calendar.getInstance(); 186 cal.setTime( artifactMeta.getFileLastModified() ); 187 node.setProperty( JCR_LAST_MODIFIED, cal ); 188 189 cal = Calendar.getInstance(); 190 cal.setTime( artifactMeta.getWhenGathered() ); 191 node.setProperty( "whenGathered", cal ); 192 193 node.setProperty( "size", artifactMeta.getSize() ); 194 node.setProperty( "md5", artifactMeta.getMd5() ); 195 node.setProperty( "sha1", artifactMeta.getSha1() ); 196 197 node.setProperty( "version", artifactMeta.getVersion() ); 198 199 // iterate over available facets to update/add/remove from the artifactMetadata 200 for ( String facetId : metadataFacetFactories.keySet() ) 201 { 202 MetadataFacet metadataFacet = artifactMeta.getFacet( facetId ); 203 if ( metadataFacet == null ) 204 { 205 continue; 206 } 207 if ( node.hasNode( facetId ) ) 208 { 209 node.getNode( facetId ).remove(); 210 } 211 if ( metadataFacet != null ) 212 { 213 // recreate, to ensure properties are removed 214 Node n = node.addNode( facetId ); 215 n.addMixin( FACET_NODE_TYPE ); 216 217 for ( Map.Entry<String, String> entry : metadataFacet.toProperties().entrySet() ) 218 { 219 n.setProperty( entry.getKey(), entry.getValue() ); 220 } 221 } 222 } 223 } 224 catch ( RepositoryException e ) 225 { 226 throw new MetadataRepositoryException( e.getMessage(), e ); 227 } 228 } 229 230 public void updateProjectVersion( String repositoryId, String namespace, String projectId, 231 ProjectVersionMetadata versionMetadata ) 232 throws MetadataRepositoryException 233 { 234 updateProject( repositoryId, namespace, projectId ); 235 236 try 237 { 238 Node versionNode = 239 getOrAddProjectVersionNode( repositoryId, namespace, projectId, versionMetadata.getId() ); 240 241 versionNode.setProperty( "name", versionMetadata.getName() ); 242 versionNode.setProperty( "description", versionMetadata.getDescription() ); 243 versionNode.setProperty( "url", versionMetadata.getUrl() ); 244 versionNode.setProperty( "incomplete", versionMetadata.isIncomplete() ); 245 246 // FIXME: decide how to treat these in the content repo 247 if ( versionMetadata.getScm() != null ) 248 { 249 versionNode.setProperty( "scm.connection", versionMetadata.getScm().getConnection() ); 250 versionNode.setProperty( "scm.developerConnection", versionMetadata.getScm().getDeveloperConnection() ); 251 versionNode.setProperty( "scm.url", versionMetadata.getScm().getUrl() ); 252 } 253 if ( versionMetadata.getCiManagement() != null ) 254 { 255 versionNode.setProperty( "ci.system", versionMetadata.getCiManagement().getSystem() ); 256 versionNode.setProperty( "ci.url", versionMetadata.getCiManagement().getUrl() ); 257 } 258 if ( versionMetadata.getIssueManagement() != null ) 259 { 260 versionNode.setProperty( "issue.system", versionMetadata.getIssueManagement().getSystem() ); 261 versionNode.setProperty( "issue.url", versionMetadata.getIssueManagement().getUrl() ); 262 } 263 if ( versionMetadata.getOrganization() != null ) 264 { 265 versionNode.setProperty( "org.name", versionMetadata.getOrganization().getName() ); 266 versionNode.setProperty( "org.url", versionMetadata.getOrganization().getUrl() ); 267 } 268 int i = 0; 269 for ( License license : versionMetadata.getLicenses() ) 270 { 271 versionNode.setProperty( "license." + i + ".name", license.getName() ); 272 versionNode.setProperty( "license." + i + ".url", license.getUrl() ); 273 i++; 274 } 275 i = 0; 276 for ( MailingList mailingList : versionMetadata.getMailingLists() ) 277 { 278 versionNode.setProperty( "mailingList." + i + ".archive", mailingList.getMainArchiveUrl() ); 279 versionNode.setProperty( "mailingList." + i + ".name", mailingList.getName() ); 280 versionNode.setProperty( "mailingList." + i + ".post", mailingList.getPostAddress() ); 281 versionNode.setProperty( "mailingList." + i + ".unsubscribe", mailingList.getUnsubscribeAddress() ); 282 versionNode.setProperty( "mailingList." + i + ".subscribe", mailingList.getSubscribeAddress() ); 283 versionNode.setProperty( "mailingList." + i + ".otherArchives", 284 join( mailingList.getOtherArchives() ) ); 285 i++; 286 } 287 288 if ( !versionMetadata.getDependencies().isEmpty() ) 289 { 290 Node dependenciesNode = JcrUtils.getOrAddNode( versionNode, "dependencies" ); 291 292 for ( Dependency dependency : versionMetadata.getDependencies() ) 293 { 294 // Note that we deliberately don't alter the namespace path - not enough dependencies for 295 // number of nodes at a given depth to be an issue. Similarly, we don't add subnodes for each 296 // component of the ID as that creates extra depth and causes a great cost in space and memory 297 298 // FIXME: change group ID to namespace 299 // FIXME: change to artifact's ID - this is constructed by the Maven 2 format for now. 300 // This won't support types where the extension doesn't match the type. 301 // (see also Maven2RepositoryStorage#readProjectVersionMetadata construction of POM) 302 String id = 303 dependency.getGroupId() + ";" + dependency.getArtifactId() + "-" + dependency.getVersion(); 304 if ( dependency.getClassifier() != null ) 305 { 306 id += "-" + dependency.getClassifier(); 307 } 308 id += "." + dependency.getType(); 309 310 Node n = JcrUtils.getOrAddNode( dependenciesNode, id ); 311 n.addMixin( DEPENDENCY_NODE_TYPE ); 312 313 // FIXME: remove temp code just to make it keep working 314 n.setProperty( "groupId", dependency.getGroupId() ); 315 n.setProperty( "artifactId", dependency.getArtifactId() ); 316 n.setProperty( "version", dependency.getVersion() ); 317 n.setProperty( "type", dependency.getType() ); 318 n.setProperty( "classifier", dependency.getClassifier() ); 319 n.setProperty( "scope", dependency.getScope() ); 320 n.setProperty( "systemPath", dependency.getSystemPath() ); 321 n.setProperty( "optional", dependency.isOptional() ); 322 323 // node has no native content at this time, just facets 324 // no need to list a type as it's implied by the path. Parents are Maven specific. 325 326 // FIXME: add scope, systemPath, type, version, classifier & maven2 specific IDs as a facet 327 // (should also have been added to the Dependency) 328 329 // TODO: add a property that is a weak reference to the originating artifact, creating it if 330 // necessary (without adding the archiva:artifact mixin so that it doesn't get listed as an 331 // artifact, which gives a different meaning to "incomplete" which is a known local project 332 // that doesn't have metadata yet but has artifacts). (Though we may want to give it the 333 // artifact mixin and another property to identify all non-local artifacts for the closure 334 // reports) 335 } 336 } 337 338 for ( MetadataFacet facet : versionMetadata.getFacetList() ) 339 { 340 // recreate, to ensure properties are removed 341 if ( versionNode.hasNode( facet.getFacetId() ) ) 342 { 343 versionNode.getNode( facet.getFacetId() ).remove(); 344 } 345 Node n = versionNode.addNode( facet.getFacetId() ); 346 n.addMixin( FACET_NODE_TYPE ); 347 348 for ( Map.Entry<String, String> entry : facet.toProperties().entrySet() ) 349 { 350 n.setProperty( entry.getKey(), entry.getValue() ); 351 } 352 } 353 } 354 catch ( RepositoryException e ) 355 { 356 throw new MetadataRepositoryException( e.getMessage(), e ); 357 } 358 } 359 360 public void updateNamespace( String repositoryId, String namespace ) 361 throws MetadataRepositoryException 362 { 363 try 364 { 365 Node node = getOrAddNamespaceNode( repositoryId, namespace ); 366 node.setProperty( "namespace", namespace ); 367 } 368 catch ( RepositoryException e ) 369 { 370 throw new MetadataRepositoryException( e.getMessage(), e ); 371 } 372 } 373 374 public void removeProject( String repositoryId, String namespace, String projectId ) 375 throws MetadataRepositoryException 376 { 377 try 378 { 379 Node root = getJcrSession().getRootNode(); 380 String namespacePath = getNamespacePath( repositoryId, namespace ); 381 382 if ( root.hasNode( namespacePath ) ) 383 { 384 Iterator<Node> nodeIterator = JcrUtils.getChildNodes( root.getNode( namespacePath ) ).iterator(); 385 while ( nodeIterator.hasNext() ) 386 { 387 Node node = nodeIterator.next(); 388 if ( node.isNodeType( PROJECT_NODE_TYPE ) && projectId.equals( node.getName() ) ) 389 { 390 node.remove(); 391 } 392 } 393 394 } 395 } 396 catch ( RepositoryException e ) 397 { 398 throw new MetadataRepositoryException( e.getMessage(), e ); 399 } 400 401 } 402 403 404 public boolean hasMetadataFacet( String repositoryId, String facetId ) 405 throws MetadataRepositoryException 406 { 407 try 408 { 409 Node node = getJcrSession().getRootNode().getNode( getFacetPath( repositoryId, facetId ) ); 410 return node.getNodes().hasNext(); 411 } 412 catch ( PathNotFoundException e ) 413 { 414 // ignored - the facet doesn't exist, so return false 415 return false; 416 } 417 catch ( RepositoryException e ) 418 { 419 throw new MetadataRepositoryException( e.getMessage(), e ); 420 } 421 } 422 423 public List<String> getMetadataFacets( String repositoryId, String facetId ) 424 throws MetadataRepositoryException 425 { 426 List<String> facets = new ArrayList<String>(); 427 428 try 429 { 430 // no need to construct node-by-node here, as we'll find in the next instance, the facet names have / and 431 // are paths themselves 432 Node node = getJcrSession().getRootNode().getNode( getFacetPath( repositoryId, facetId ) ); 433 434 // TODO: this is a bit awkward. Might be better to review the purpose of this function - why is the list of 435 // paths helpful? 436 recurse( facets, "", node ); 437 } 438 catch ( PathNotFoundException e ) 439 { 440 // ignored - the facet doesn't exist, so return the empty list 441 } 442 catch ( RepositoryException e ) 443 { 444 throw new MetadataRepositoryException( e.getMessage(), e ); 445 } 446 return facets; 447 } 448 449 private void recurse( List<String> facets, String prefix, Node node ) 450 throws RepositoryException 451 { 452 for ( Node n : JcrUtils.getChildNodes( node ) ) 453 { 454 String name = prefix + "/" + n.getName(); 455 if ( n.hasNodes() ) 456 { 457 recurse( facets, name, n ); 458 } 459 else 460 { 461 // strip leading / first 462 facets.add( name.substring( 1 ) ); 463 } 464 } 465 } 466 467 public MetadataFacet getMetadataFacet( String repositoryId, String facetId, String name ) 468 throws MetadataRepositoryException 469 { 470 MetadataFacet metadataFacet = null; 471 try 472 { 473 Node root = getJcrSession().getRootNode(); 474 Node node = root.getNode( getFacetPath( repositoryId, facetId, name ) ); 475 476 if ( metadataFacetFactories == null ) 477 { 478 return metadataFacet; 479 } 480 481 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId ); 482 if ( metadataFacetFactory != null ) 483 { 484 metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name ); 485 Map<String, String> map = new HashMap<String, String>(); 486 for ( Property property : JcrUtils.getProperties( node ) ) 487 { 488 String p = property.getName(); 489 if ( !p.startsWith( "jcr:" ) ) 490 { 491 map.put( p, property.getString() ); 492 } 493 } 494 metadataFacet.fromProperties( map ); 495 } 496 } 497 catch ( PathNotFoundException e ) 498 { 499 // ignored - the facet doesn't exist, so return null 500 } 501 catch ( RepositoryException e ) 502 { 503 throw new MetadataRepositoryException( e.getMessage(), e ); 504 } 505 return metadataFacet; 506 } 507 508 public void addMetadataFacet( String repositoryId, MetadataFacet metadataFacet ) 509 throws MetadataRepositoryException 510 { 511 try 512 { 513 Node repo = getOrAddRepositoryNode( repositoryId ); 514 Node facets = JcrUtils.getOrAddNode( repo, "facets" ); 515 516 String id = metadataFacet.getFacetId(); 517 Node facetNode = JcrUtils.getOrAddNode( facets, id ); 518 519 Node node = getOrAddNodeByPath( facetNode, metadataFacet.getName() ); 520 521 for ( Map.Entry<String, String> entry : metadataFacet.toProperties().entrySet() ) 522 { 523 node.setProperty( entry.getKey(), entry.getValue() ); 524 } 525 } 526 catch ( RepositoryException e ) 527 { 528 throw new MetadataRepositoryException( e.getMessage(), e ); 529 } 530 } 531 532 public void removeNamespace( String repositoryId, String projectId ) 533 throws MetadataRepositoryException 534 { 535 try 536 { 537 Node root = getJcrSession().getRootNode(); 538 String path = getNamespacePath( repositoryId, projectId ); 539 if ( root.hasNode( path ) ) 540 { 541 Node node = root.getNode( path ); 542 if ( node.isNodeType( NAMESPACE_NODE_TYPE ) ) 543 { 544 node.remove(); 545 } 546 } 547 } 548 catch ( RepositoryException e ) 549 { 550 throw new MetadataRepositoryException( e.getMessage(), e ); 551 } 552 } 553 554 public void removeMetadataFacets( String repositoryId, String facetId ) 555 throws MetadataRepositoryException 556 { 557 try 558 { 559 Node root = getJcrSession().getRootNode(); 560 String path = getFacetPath( repositoryId, facetId ); 561 if ( root.hasNode( path ) ) 562 { 563 root.getNode( path ).remove(); 564 } 565 } 566 catch ( RepositoryException e ) 567 { 568 throw new MetadataRepositoryException( e.getMessage(), e ); 569 } 570 } 571 572 public void removeMetadataFacet( String repositoryId, String facetId, String name ) 573 throws MetadataRepositoryException 574 { 575 try 576 { 577 Node root = getJcrSession().getRootNode(); 578 String path = getFacetPath( repositoryId, facetId, name ); 579 if ( root.hasNode( path ) ) 580 { 581 Node node = root.getNode( path ); 582 do 583 { 584 // also remove empty container nodes 585 Node parent = node.getParent(); 586 node.remove(); 587 node = parent; 588 } 589 while ( !node.hasNodes() ); 590 } 591 } 592 catch ( RepositoryException e ) 593 { 594 throw new MetadataRepositoryException( e.getMessage(), e ); 595 } 596 } 597 598 public List<ArtifactMetadata> getArtifactsByDateRange( String repoId, Date startTime, Date endTime ) 599 throws MetadataRepositoryException 600 { 601 List<ArtifactMetadata> artifacts; 602 603 String q = getArtifactQuery( repoId ); 604 605 if ( startTime != null ) 606 { 607 q += " AND [whenGathered] >= $start"; 608 } 609 if ( endTime != null ) 610 { 611 q += " AND [whenGathered] <= $end"; 612 } 613 614 try 615 { 616 Query query = getJcrSession().getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 ); 617 ValueFactory valueFactory = getJcrSession().getValueFactory(); 618 if ( startTime != null ) 619 { 620 query.bindValue( "start", valueFactory.createValue( createCalendar( startTime ) ) ); 621 } 622 if ( endTime != null ) 623 { 624 query.bindValue( "end", valueFactory.createValue( createCalendar( endTime ) ) ); 625 } 626 QueryResult result = query.execute(); 627 628 artifacts = new ArrayList<ArtifactMetadata>(); 629 for ( Node n : JcrUtils.getNodes( result ) ) 630 { 631 artifacts.add( getArtifactFromNode( repoId, n ) ); 632 } 633 } 634 catch ( RepositoryException e ) 635 { 636 throw new MetadataRepositoryException( e.getMessage(), e ); 637 } 638 return artifacts; 639 } 640 641 public Collection<String> getRepositories() 642 throws MetadataRepositoryException 643 { 644 List<String> repositories; 645 646 try 647 { 648 Node root = getJcrSession().getRootNode(); 649 if ( root.hasNode( "repositories" ) ) 650 { 651 Node node = root.getNode( "repositories" ); 652 653 repositories = new ArrayList<String>(); 654 NodeIterator i = node.getNodes(); 655 while ( i.hasNext() ) 656 { 657 Node n = i.nextNode(); 658 repositories.add( n.getName() ); 659 } 660 } 661 else 662 { 663 repositories = Collections.emptyList(); 664 } 665 } 666 catch ( RepositoryException e ) 667 { 668 throw new MetadataRepositoryException( e.getMessage(), e ); 669 } 670 return repositories; 671 } 672 673 public List<ArtifactMetadata> getArtifactsByChecksum( String repositoryId, String checksum ) 674 throws MetadataRepositoryException 675 { 676 List<ArtifactMetadata> artifacts; 677 678 String q = getArtifactQuery( repositoryId ) + " AND ([sha1] = $checksum OR [md5] = $checksum)"; 679 680 try 681 { 682 Query query = getJcrSession().getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 ); 683 ValueFactory valueFactory = getJcrSession().getValueFactory(); 684 query.bindValue( "checksum", valueFactory.createValue( checksum ) ); 685 QueryResult result = query.execute(); 686 687 artifacts = new ArrayList<ArtifactMetadata>(); 688 for ( Node n : JcrUtils.getNodes( result ) ) 689 { 690 artifacts.add( getArtifactFromNode( repositoryId, n ) ); 691 } 692 } 693 catch ( RepositoryException e ) 694 { 695 throw new MetadataRepositoryException( e.getMessage(), e ); 696 } 697 return artifacts; 698 } 699 700 701 public void removeRepository( String repositoryId ) 702 throws MetadataRepositoryException 703 { 704 try 705 { 706 Node root = getJcrSession().getRootNode(); 707 String path = getRepositoryPath( repositoryId ); 708 if ( root.hasNode( path ) ) 709 { 710 root.getNode( path ).remove(); 711 } 712 } 713 catch ( RepositoryException e ) 714 { 715 throw new MetadataRepositoryException( e.getMessage(), e ); 716 } 717 } 718 719 public List<ArtifactMetadata> getArtifacts( String repositoryId ) 720 throws MetadataRepositoryException 721 { 722 List<ArtifactMetadata> artifacts; 723 724 String q = getArtifactQuery( repositoryId ); 725 726 try 727 { 728 Query query = getJcrSession().getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 ); 729 QueryResult result = query.execute(); 730 731 artifacts = new ArrayList<ArtifactMetadata>(); 732 for ( Node n : JcrUtils.getNodes( result ) ) 733 { 734 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) ) 735 { 736 artifacts.add( getArtifactFromNode( repositoryId, n ) ); 737 } 738 } 739 } 740 catch ( RepositoryException e ) 741 { 742 throw new MetadataRepositoryException( e.getMessage(), e ); 743 } 744 return artifacts; 745 } 746 747 private static String getArtifactQuery( String repositoryId ) 748 { 749 return "SELECT * FROM [" + ARTIFACT_NODE_TYPE + "] AS artifact WHERE ISDESCENDANTNODE(artifact,'/" + 750 getRepositoryContentPath( repositoryId ) + "')"; 751 } 752 753 public ProjectMetadata getProject( String repositoryId, String namespace, String projectId ) 754 throws MetadataResolutionException 755 { 756 ProjectMetadata metadata = null; 757 758 try 759 { 760 Node root = getJcrSession().getRootNode(); 761 762 // basically just checking it exists 763 String path = getProjectPath( repositoryId, namespace, projectId ); 764 if ( root.hasNode( path ) ) 765 { 766 metadata = new ProjectMetadata(); 767 metadata.setId( projectId ); 768 metadata.setNamespace( namespace ); 769 } 770 } 771 catch ( RepositoryException e ) 772 { 773 throw new MetadataResolutionException( e.getMessage(), e ); 774 } 775 776 return metadata; 777 } 778 779 public ProjectVersionMetadata getProjectVersion( String repositoryId, String namespace, String projectId, 780 String projectVersion ) 781 throws MetadataResolutionException 782 { 783 ProjectVersionMetadata versionMetadata; 784 785 try 786 { 787 Node root = getJcrSession().getRootNode(); 788 789 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ); 790 if ( !root.hasNode( path ) ) 791 { 792 return null; 793 } 794 795 Node node = root.getNode( path ); 796 797 versionMetadata = new ProjectVersionMetadata(); 798 versionMetadata.setId( projectVersion ); 799 versionMetadata.setName( getPropertyString( node, "name" ) ); 800 versionMetadata.setDescription( getPropertyString( node, "description" ) ); 801 versionMetadata.setUrl( getPropertyString( node, "url" ) ); 802 versionMetadata.setIncomplete( 803 node.hasProperty( "incomplete" ) && node.getProperty( "incomplete" ).getBoolean() ); 804 805 // FIXME: decide how to treat these in the content repo 806 String scmConnection = getPropertyString( node, "scm.connection" ); 807 String scmDeveloperConnection = getPropertyString( node, "scm.developerConnection" ); 808 String scmUrl = getPropertyString( node, "scm.url" ); 809 if ( scmConnection != null || scmDeveloperConnection != null || scmUrl != null ) 810 { 811 Scm scm = new Scm(); 812 scm.setConnection( scmConnection ); 813 scm.setDeveloperConnection( scmDeveloperConnection ); 814 scm.setUrl( scmUrl ); 815 versionMetadata.setScm( scm ); 816 } 817 818 String ciSystem = getPropertyString( node, "ci.system" ); 819 String ciUrl = getPropertyString( node, "ci.url" ); 820 if ( ciSystem != null || ciUrl != null ) 821 { 822 CiManagement ci = new CiManagement(); 823 ci.setSystem( ciSystem ); 824 ci.setUrl( ciUrl ); 825 versionMetadata.setCiManagement( ci ); 826 } 827 828 String issueSystem = getPropertyString( node, "issue.system" ); 829 String issueUrl = getPropertyString( node, "issue.url" ); 830 if ( issueSystem != null || issueUrl != null ) 831 { 832 IssueManagement issueManagement = new IssueManagement(); 833 issueManagement.setSystem( issueSystem ); 834 issueManagement.setUrl( issueUrl ); 835 versionMetadata.setIssueManagement( issueManagement ); 836 } 837 838 String orgName = getPropertyString( node, "org.name" ); 839 String orgUrl = getPropertyString( node, "org.url" ); 840 if ( orgName != null || orgUrl != null ) 841 { 842 Organization org = new Organization(); 843 org.setName( orgName ); 844 org.setUrl( orgUrl ); 845 versionMetadata.setOrganization( org ); 846 } 847 848 boolean done = false; 849 int i = 0; 850 while ( !done ) 851 { 852 String licenseName = getPropertyString( node, "license." + i + ".name" ); 853 String licenseUrl = getPropertyString( node, "license." + i + ".url" ); 854 if ( licenseName != null || licenseUrl != null ) 855 { 856 License license = new License(); 857 license.setName( licenseName ); 858 license.setUrl( licenseUrl ); 859 versionMetadata.addLicense( license ); 860 } 861 else 862 { 863 done = true; 864 } 865 i++; 866 } 867 868 done = false; 869 i = 0; 870 while ( !done ) 871 { 872 String mailingListName = getPropertyString( node, "mailingList." + i + ".name" ); 873 if ( mailingListName != null ) 874 { 875 MailingList mailingList = new MailingList(); 876 mailingList.setName( mailingListName ); 877 mailingList.setMainArchiveUrl( getPropertyString( node, "mailingList." + i + ".archive" ) ); 878 String n = "mailingList." + i + ".otherArchives"; 879 if ( node.hasProperty( n ) ) 880 { 881 mailingList.setOtherArchives( Arrays.asList( getPropertyString( node, n ).split( "," ) ) ); 882 } 883 else 884 { 885 mailingList.setOtherArchives( Collections.<String>emptyList() ); 886 } 887 mailingList.setPostAddress( getPropertyString( node, "mailingList." + i + ".post" ) ); 888 mailingList.setSubscribeAddress( getPropertyString( node, "mailingList." + i + ".subscribe" ) ); 889 mailingList.setUnsubscribeAddress( getPropertyString( node, "mailingList." + i + ".unsubscribe" ) ); 890 versionMetadata.addMailingList( mailingList ); 891 } 892 else 893 { 894 done = true; 895 } 896 i++; 897 } 898 899 if ( node.hasNode( "dependencies" ) ) 900 { 901 Node dependenciesNode = node.getNode( "dependencies" ); 902 for ( Node n : JcrUtils.getChildNodes( dependenciesNode ) ) 903 { 904 if ( n.isNodeType( DEPENDENCY_NODE_TYPE ) ) 905 { 906 Dependency dependency = new Dependency(); 907 // FIXME: correct these properties 908 dependency.setArtifactId( getPropertyString( n, "artifactId" ) ); 909 dependency.setGroupId( getPropertyString( n, "groupId" ) ); 910 dependency.setClassifier( getPropertyString( n, "classifier" ) ); 911 dependency.setOptional( Boolean.valueOf( getPropertyString( n, "optional" ) ) ); 912 dependency.setScope( getPropertyString( n, "scope" ) ); 913 dependency.setSystemPath( getPropertyString( n, "systemPath" ) ); 914 dependency.setType( getPropertyString( n, "type" ) ); 915 dependency.setVersion( getPropertyString( n, "version" ) ); 916 versionMetadata.addDependency( dependency ); 917 } 918 } 919 } 920 921 for ( Node n : JcrUtils.getChildNodes( node ) ) 922 { 923 if ( n.isNodeType( FACET_NODE_TYPE ) ) 924 { 925 String name = n.getName(); 926 MetadataFacetFactory factory = metadataFacetFactories.get( name ); 927 if ( factory == null ) 928 { 929 log.error( "Attempted to load unknown project version metadata facet: {}", name ); 930 } 931 else 932 { 933 MetadataFacet facet = factory.createMetadataFacet(); 934 Map<String, String> map = new HashMap<String, String>(); 935 for ( Property property : JcrUtils.getProperties( n ) ) 936 { 937 String p = property.getName(); 938 if ( !p.startsWith( "jcr:" ) ) 939 { 940 map.put( p, property.getString() ); 941 } 942 } 943 facet.fromProperties( map ); 944 versionMetadata.addFacet( facet ); 945 } 946 } 947 } 948 } 949 catch ( RepositoryException e ) 950 { 951 throw new MetadataResolutionException( e.getMessage(), e ); 952 } 953 954 return versionMetadata; 955 } 956 957 public Collection<String> getArtifactVersions( String repositoryId, String namespace, String projectId, 958 String projectVersion ) 959 throws MetadataResolutionException 960 { 961 Set<String> versions = new LinkedHashSet<String>(); 962 963 try 964 { 965 Node root = getJcrSession().getRootNode(); 966 967 Node node = root.getNode( getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) ); 968 969 for ( Node n : JcrUtils.getChildNodes( node ) ) 970 { 971 versions.add( n.getProperty( "version" ).getString() ); 972 } 973 } 974 catch ( PathNotFoundException e ) 975 { 976 // ignore repo not found for now 977 } 978 catch ( RepositoryException e ) 979 { 980 throw new MetadataResolutionException( e.getMessage(), e ); 981 } 982 983 return versions; 984 } 985 986 public Collection<ProjectVersionReference> getProjectReferences( String repositoryId, String namespace, 987 String projectId, String projectVersion ) 988 throws MetadataResolutionException 989 { 990 List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>(); 991 992 // TODO: bind variables instead 993 String q = "SELECT * FROM [archiva:dependency] WHERE ISDESCENDANTNODE([/repositories/" + repositoryId + 994 "/content]) AND [groupId]='" + namespace + "' AND [artifactId]='" + projectId + "'"; 995 if ( projectVersion != null ) 996 { 997 q += " AND [version]='" + projectVersion + "'"; 998 } 999 try 1000 { 1001 Query query = getJcrSession().getWorkspace().getQueryManager().createQuery( q, Query.JCR_SQL2 ); 1002 QueryResult result = query.execute(); 1003 1004 for ( Node n : JcrUtils.getNodes( result ) ) 1005 { 1006 n = n.getParent(); // dependencies grouping element 1007 1008 n = n.getParent(); // project version 1009 String usedByProjectVersion = n.getName(); 1010 1011 n = n.getParent(); // project 1012 String usedByProject = n.getName(); 1013 1014 n = n.getParent(); // namespace 1015 String usedByNamespace = n.getProperty( "namespace" ).getString(); 1016 1017 ProjectVersionReference ref = new ProjectVersionReference(); 1018 ref.setNamespace( usedByNamespace ); 1019 ref.setProjectId( usedByProject ); 1020 ref.setProjectVersion( usedByProjectVersion ); 1021 ref.setReferenceType( ProjectVersionReference.ReferenceType.DEPENDENCY ); 1022 references.add( ref ); 1023 } 1024 } 1025 catch ( RepositoryException e ) 1026 { 1027 throw new MetadataResolutionException( e.getMessage(), e ); 1028 } 1029 1030 return references; 1031 } 1032 1033 public Collection<String> getRootNamespaces( String repositoryId ) 1034 throws MetadataResolutionException 1035 { 1036 return getNamespaces( repositoryId, null ); 1037 } 1038 1039 public Collection<String> getNamespaces( String repositoryId, String baseNamespace ) 1040 throws MetadataResolutionException 1041 { 1042 String path = baseNamespace != null 1043 ? getNamespacePath( repositoryId, baseNamespace ) 1044 : getRepositoryContentPath( repositoryId ); 1045 1046 return getNodeNames( path, NAMESPACE_NODE_TYPE ); 1047 } 1048 1049 public Collection<String> getProjects( String repositoryId, String namespace ) 1050 throws MetadataResolutionException 1051 { 1052 return getNodeNames( getNamespacePath( repositoryId, namespace ), PROJECT_NODE_TYPE ); 1053 } 1054 1055 public Collection<String> getProjectVersions( String repositoryId, String namespace, String projectId ) 1056 throws MetadataResolutionException 1057 { 1058 return getNodeNames( getProjectPath( repositoryId, namespace, projectId ), PROJECT_VERSION_NODE_TYPE ); 1059 } 1060 1061 public void removeArtifact( ArtifactMetadata artifactMetadata, String baseVersion ) 1062 throws MetadataRepositoryException 1063 { 1064 1065 String repositoryId = artifactMetadata.getRepositoryId(); 1066 1067 try 1068 { 1069 Node root = getJcrSession().getRootNode(); 1070 String path = 1071 getProjectVersionPath( repositoryId, artifactMetadata.getNamespace(), artifactMetadata.getProject(), 1072 baseVersion ); 1073 1074 if ( root.hasNode( path ) ) 1075 { 1076 Node node = root.getNode( path ); 1077 1078 for ( Node n : JcrUtils.getChildNodes( node ) ) 1079 { 1080 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) ) 1081 { 1082 if ( n.hasProperty( "version" ) ) 1083 { 1084 String version = n.getProperty( "version" ).getString(); 1085 if ( StringUtils.equals( version, artifactMetadata.getVersion() ) ) 1086 { 1087 n.remove(); 1088 } 1089 } 1090 1091 } 1092 } 1093 } 1094 } 1095 catch ( RepositoryException e ) 1096 { 1097 throw new MetadataRepositoryException( e.getMessage(), e ); 1098 } 1099 1100 1101 } 1102 1103 1104 public void removeProjectVersion( String repoId, String namespace, String projectId, String projectVersion ) 1105 throws MetadataRepositoryException 1106 { 1107 try 1108 { 1109 1110 String path = getProjectPath( repoId, namespace, projectId ); 1111 Node root = getJcrSession().getRootNode(); 1112 1113 Node nodeAtPath = root.getNode( path ); 1114 1115 for ( Node node : JcrUtils.getChildNodes( nodeAtPath ) ) 1116 { 1117 if ( node.isNodeType( PROJECT_VERSION_NODE_TYPE ) && StringUtils.equals( projectVersion, 1118 node.getName() ) ) 1119 { 1120 node.remove(); 1121 } 1122 } 1123 } 1124 catch ( RepositoryException e ) 1125 { 1126 throw new MetadataRepositoryException( e.getMessage(), e ); 1127 } 1128 } 1129 1130 public void removeArtifact( String repositoryId, String namespace, String projectId, String projectVersion, 1131 String id ) 1132 throws MetadataRepositoryException 1133 { 1134 try 1135 { 1136 Node root = getJcrSession().getRootNode(); 1137 String path = getArtifactPath( repositoryId, namespace, projectId, projectVersion, id ); 1138 if ( root.hasNode( path ) ) 1139 { 1140 root.getNode( path ).remove(); 1141 } 1142 1143 // remove version 1144 1145 path = getProjectPath( repositoryId, namespace, projectId ); 1146 1147 Node nodeAtPath = root.getNode( path ); 1148 1149 for ( Node node : JcrUtils.getChildNodes( nodeAtPath ) ) 1150 { 1151 if ( node.isNodeType( PROJECT_VERSION_NODE_TYPE ) && StringUtils.equals( node.getName(), 1152 projectVersion ) ) 1153 { 1154 node.remove(); 1155 } 1156 } 1157 } 1158 catch ( RepositoryException e ) 1159 { 1160 throw new MetadataRepositoryException( e.getMessage(), e ); 1161 } 1162 } 1163 1164 public void removeArtifact( String repositoryId, String namespace, String project, String projectVersion, 1165 MetadataFacet metadataFacet ) 1166 throws MetadataRepositoryException 1167 { 1168 try 1169 { 1170 Node root = getJcrSession().getRootNode(); 1171 String path = getProjectVersionPath( repositoryId, namespace, project, projectVersion ); 1172 1173 if ( root.hasNode( path ) ) 1174 { 1175 Node node = root.getNode( path ); 1176 1177 for ( Node n : JcrUtils.getChildNodes( node ) ) 1178 { 1179 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) ) 1180 { 1181 ArtifactMetadata artifactMetadata = getArtifactFromNode( repositoryId, n ); 1182 log.debug( "artifactMetadata: {}", artifactMetadata ); 1183 MetadataFacet metadataFacetToRemove = artifactMetadata.getFacet( metadataFacet.getFacetId() ); 1184 if ( metadataFacetToRemove != null && metadataFacet.equals( metadataFacetToRemove ) ) 1185 { 1186 n.remove(); 1187 } 1188 } 1189 } 1190 } 1191 } 1192 catch ( RepositoryException e ) 1193 { 1194 throw new MetadataRepositoryException( e.getMessage(), e ); 1195 } 1196 } 1197 1198 public Collection<ArtifactMetadata> getArtifacts( String repositoryId, String namespace, String projectId, 1199 String projectVersion ) 1200 throws MetadataResolutionException 1201 { 1202 List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>(); 1203 1204 try 1205 { 1206 Node root = getJcrSession().getRootNode(); 1207 String path = getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ); 1208 1209 if ( root.hasNode( path ) ) 1210 { 1211 Node node = root.getNode( path ); 1212 1213 for ( Node n : JcrUtils.getChildNodes( node ) ) 1214 { 1215 if ( n.isNodeType( ARTIFACT_NODE_TYPE ) ) 1216 { 1217 artifacts.add( getArtifactFromNode( repositoryId, n ) ); 1218 } 1219 } 1220 } 1221 } 1222 catch ( RepositoryException e ) 1223 { 1224 throw new MetadataResolutionException( e.getMessage(), e ); 1225 } 1226 1227 return artifacts; 1228 } 1229 1230 public void save() 1231 { 1232 try 1233 { 1234 getJcrSession().save(); 1235 } 1236 catch ( RepositoryException e ) 1237 { 1238 throw new RuntimeException( e.getMessage(), e ); 1239 } 1240 } 1241 1242 public void revert() 1243 { 1244 try 1245 { 1246 getJcrSession().refresh( false ); 1247 } 1248 catch ( RepositoryException e ) 1249 { 1250 throw new RuntimeException( e.getMessage(), e ); 1251 } 1252 } 1253 1254 public boolean canObtainAccess( Class<?> aClass ) 1255 { 1256 return aClass == Session.class; 1257 } 1258 1259 public <T>T obtainAccess( Class<T> aClass ) 1260 throws MetadataRepositoryException 1261 { 1262 if ( aClass == Session.class ) 1263 { 1264 try 1265 { 1266 return (T) getJcrSession(); 1267 } 1268 catch ( RepositoryException e ) 1269 { 1270 log.error( e.getMessage(), e ); 1271 throw new MetadataRepositoryException( e.getMessage(), e ); 1272 } 1273 } 1274 throw new IllegalArgumentException( 1275 "Access using " + aClass + " is not supported on the JCR metadata storage" ); 1276 } 1277 1278 public void close() 1279 throws MetadataRepositoryException 1280 { 1281 try 1282 { 1283 if ( getJcrSession().isLive() ) 1284 { 1285 getJcrSession().logout(); 1286 } 1287 } 1288 catch ( RepositoryException e ) 1289 { 1290 log.error( e.getMessage(), e ); 1291 throw new MetadataRepositoryException( e.getMessage(), e ); 1292 } 1293 } 1294 1295 private ArtifactMetadata getArtifactFromNode( String repositoryId, Node artifactNode ) 1296 throws RepositoryException 1297 { 1298 String id = artifactNode.getName(); 1299 1300 ArtifactMetadata artifact = new ArtifactMetadata(); 1301 artifact.setId( id ); 1302 artifact.setRepositoryId( repositoryId ); 1303 1304 Node projectVersionNode = artifactNode.getParent(); 1305 Node projectNode = projectVersionNode.getParent(); 1306 Node namespaceNode = projectNode.getParent(); 1307 1308 artifact.setNamespace( namespaceNode.getProperty( "namespace" ).getString() ); 1309 artifact.setProject( projectNode.getName() ); 1310 artifact.setProjectVersion( projectVersionNode.getName() ); 1311 artifact.setVersion( artifactNode.hasProperty( "version" ) 1312 ? artifactNode.getProperty( "version" ).getString() 1313 : projectVersionNode.getName() ); 1314 1315 if ( artifactNode.hasProperty( JCR_LAST_MODIFIED ) ) 1316 { 1317 artifact.setFileLastModified( artifactNode.getProperty( JCR_LAST_MODIFIED ).getDate().getTimeInMillis() ); 1318 } 1319 1320 if ( artifactNode.hasProperty( "whenGathered" ) ) 1321 { 1322 artifact.setWhenGathered( artifactNode.getProperty( "whenGathered" ).getDate().getTime() ); 1323 } 1324 1325 if ( artifactNode.hasProperty( "size" ) ) 1326 { 1327 artifact.setSize( artifactNode.getProperty( "size" ).getLong() ); 1328 } 1329 1330 if ( artifactNode.hasProperty( "md5" ) ) 1331 { 1332 artifact.setMd5( artifactNode.getProperty( "md5" ).getString() ); 1333 } 1334 1335 if ( artifactNode.hasProperty( "sha1" ) ) 1336 { 1337 artifact.setSha1( artifactNode.getProperty( "sha1" ).getString() ); 1338 } 1339 1340 for ( Node n : JcrUtils.getChildNodes( artifactNode ) ) 1341 { 1342 if ( n.isNodeType( FACET_NODE_TYPE ) ) 1343 { 1344 String name = n.getName(); 1345 MetadataFacetFactory factory = metadataFacetFactories.get( name ); 1346 if ( factory == null ) 1347 { 1348 log.error( "Attempted to load unknown project version metadata facet: " + name ); 1349 } 1350 else 1351 { 1352 MetadataFacet facet = factory.createMetadataFacet(); 1353 Map<String, String> map = new HashMap<String, String>(); 1354 for ( Property p : JcrUtils.getProperties( n ) ) 1355 { 1356 String property = p.getName(); 1357 if ( !property.startsWith( "jcr:" ) ) 1358 { 1359 map.put( property, p.getString() ); 1360 } 1361 } 1362 facet.fromProperties( map ); 1363 artifact.addFacet( facet ); 1364 } 1365 } 1366 } 1367 return artifact; 1368 } 1369 1370 private static String getPropertyString( Node node, String name ) 1371 throws RepositoryException 1372 { 1373 return node.hasProperty( name ) ? node.getProperty( name ).getString() : null; 1374 } 1375 1376 private Collection<String> getNodeNames( String path, String nodeType ) 1377 throws MetadataResolutionException 1378 { 1379 List<String> names = new ArrayList<String>(); 1380 1381 try 1382 { 1383 Node root = getJcrSession().getRootNode(); 1384 1385 Node nodeAtPath = root.getNode( path ); 1386 1387 for ( Node node : JcrUtils.getChildNodes( nodeAtPath ) ) 1388 { 1389 if ( node.isNodeType( nodeType ) ) 1390 { 1391 names.add( node.getName() ); 1392 } 1393 } 1394 } 1395 catch ( PathNotFoundException e ) 1396 { 1397 // ignore repo not found for now 1398 } 1399 catch ( RepositoryException e ) 1400 { 1401 throw new MetadataResolutionException( e.getMessage(), e ); 1402 } 1403 1404 return names; 1405 } 1406 1407 private static String getRepositoryPath( String repositoryId ) 1408 { 1409 return "repositories/" + repositoryId; 1410 } 1411 1412 private static String getRepositoryContentPath( String repositoryId ) 1413 { 1414 return getRepositoryPath( repositoryId ) + "/content/"; 1415 } 1416 1417 private static String getFacetPath( String repositoryId, String facetId ) 1418 { 1419 return getRepositoryPath( repositoryId ) + "/facets/" + facetId; 1420 } 1421 1422 private static String getNamespacePath( String repositoryId, String namespace ) 1423 { 1424 return getRepositoryContentPath( repositoryId ) + namespace.replace( '.', '/' ); 1425 } 1426 1427 private static String getProjectPath( String repositoryId, String namespace, String projectId ) 1428 { 1429 return getNamespacePath( repositoryId, namespace ) + "/" + projectId; 1430 } 1431 1432 private static String getProjectVersionPath( String repositoryId, String namespace, String projectId, 1433 String projectVersion ) 1434 { 1435 return getProjectPath( repositoryId, namespace, projectId ) + "/" + projectVersion; 1436 } 1437 1438 private static String getArtifactPath( String repositoryId, String namespace, String projectId, 1439 String projectVersion, String id ) 1440 { 1441 return getProjectVersionPath( repositoryId, namespace, projectId, projectVersion ) + "/" + id; 1442 } 1443 1444 private Node getOrAddNodeByPath( Node baseNode, String name ) 1445 throws RepositoryException 1446 { 1447 return getOrAddNodeByPath( baseNode, name, null ); 1448 } 1449 1450 private Node getOrAddNodeByPath( Node baseNode, String name, String nodeType ) 1451 throws RepositoryException 1452 { 1453 Node node = baseNode; 1454 for ( String n : name.split( "/" ) ) 1455 { 1456 node = JcrUtils.getOrAddNode( node, n ); 1457 if ( nodeType != null ) 1458 { 1459 node.addMixin( nodeType ); 1460 } 1461 } 1462 return node; 1463 } 1464 1465 private static String getFacetPath( String repositoryId, String facetId, String name ) 1466 { 1467 return getFacetPath( repositoryId, facetId ) + "/" + name; 1468 } 1469 1470 private Node getOrAddRepositoryNode( String repositoryId ) 1471 throws RepositoryException 1472 { 1473 Node root = getJcrSession().getRootNode(); 1474 Node node = JcrUtils.getOrAddNode( root, "repositories" ); 1475 node = JcrUtils.getOrAddNode( node, repositoryId ); 1476 return node; 1477 } 1478 1479 private Node getOrAddRepositoryContentNode( String repositoryId ) 1480 throws RepositoryException 1481 { 1482 Node node = getOrAddRepositoryNode( repositoryId ); 1483 return JcrUtils.getOrAddNode( node, "content" ); 1484 } 1485 1486 private Node getOrAddNamespaceNode( String repositoryId, String namespace ) 1487 throws RepositoryException 1488 { 1489 Node repo = getOrAddRepositoryContentNode( repositoryId ); 1490 return getOrAddNodeByPath( repo, namespace.replace( '.', '/' ), NAMESPACE_NODE_TYPE ); 1491 } 1492 1493 private Node getOrAddProjectNode( String repositoryId, String namespace, String projectId ) 1494 throws RepositoryException 1495 { 1496 Node namespaceNode = getOrAddNamespaceNode( repositoryId, namespace ); 1497 Node node = JcrUtils.getOrAddNode( namespaceNode, projectId ); 1498 node.addMixin( PROJECT_NODE_TYPE ); 1499 return node; 1500 } 1501 1502 private Node getOrAddProjectVersionNode( String repositoryId, String namespace, String projectId, 1503 String projectVersion ) 1504 throws RepositoryException 1505 { 1506 Node projectNode = getOrAddProjectNode( repositoryId, namespace, projectId ); 1507 Node node = JcrUtils.getOrAddNode( projectNode, projectVersion ); 1508 node.addMixin( PROJECT_VERSION_NODE_TYPE ); 1509 return node; 1510 } 1511 1512 private Node getOrAddArtifactNode( String repositoryId, String namespace, String projectId, String projectVersion, 1513 String id ) 1514 throws RepositoryException 1515 { 1516 Node versionNode = getOrAddProjectVersionNode( repositoryId, namespace, projectId, projectVersion ); 1517 Node node = JcrUtils.getOrAddNode( versionNode, id ); 1518 node.addMixin( ARTIFACT_NODE_TYPE ); 1519 return node; 1520 } 1521 1522 private static Calendar createCalendar( Date time ) 1523 { 1524 Calendar cal = Calendar.getInstance(); 1525 cal.setTime( time ); 1526 return cal; 1527 } 1528 1529 private String join( Collection<String> ids ) 1530 { 1531 if ( ids != null && !ids.isEmpty() ) 1532 { 1533 StringBuilder s = new StringBuilder(); 1534 for ( String id : ids ) 1535 { 1536 s.append( id ); 1537 s.append( "," ); 1538 } 1539 return s.substring( 0, s.length() - 1 ); 1540 } 1541 return null; 1542 } 1543 1544 public Session getJcrSession() 1545 throws RepositoryException 1546 { 1547 if ( this.jcrSession == null || !this.jcrSession.isLive() ) 1548 { 1549 jcrSession = repository.login( new SimpleCredentials( "admin", "admin".toCharArray() ) ); 1550 } 1551 return this.jcrSession; 1552 } 1553 }