1 package org.apache.archiva.metadata.repository.jcr;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.archiva.metadata.model.ArtifactMetadata;
23 import org.apache.archiva.metadata.model.CiManagement;
24 import org.apache.archiva.metadata.model.Dependency;
25 import org.apache.archiva.metadata.model.IssueManagement;
26 import org.apache.archiva.metadata.model.License;
27 import org.apache.archiva.metadata.model.MailingList;
28 import org.apache.archiva.metadata.model.MetadataFacet;
29 import org.apache.archiva.metadata.model.MetadataFacetFactory;
30 import org.apache.archiva.metadata.model.Organization;
31 import org.apache.archiva.metadata.model.ProjectMetadata;
32 import org.apache.archiva.metadata.model.ProjectVersionMetadata;
33 import org.apache.archiva.metadata.model.ProjectVersionReference;
34 import org.apache.archiva.metadata.model.Scm;
35 import org.apache.archiva.metadata.repository.MetadataRepository;
36 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
37 import org.apache.archiva.metadata.repository.MetadataResolutionException;
38 import org.apache.commons.lang.StringUtils;
39 import org.apache.jackrabbit.commons.JcrUtils;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import javax.jcr.NamespaceRegistry;
44 import javax.jcr.Node;
45 import javax.jcr.NodeIterator;
46 import javax.jcr.PathNotFoundException;
47 import javax.jcr.Property;
48 import javax.jcr.Repository;
49 import javax.jcr.RepositoryException;
50 import javax.jcr.Session;
51 import javax.jcr.SimpleCredentials;
52 import javax.jcr.ValueFactory;
53 import javax.jcr.Workspace;
54 import javax.jcr.nodetype.NodeTypeManager;
55 import javax.jcr.nodetype.NodeTypeTemplate;
56 import javax.jcr.query.Query;
57 import javax.jcr.query.QueryResult;
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.Calendar;
61 import java.util.Collection;
62 import java.util.Collections;
63 import java.util.Date;
64 import java.util.HashMap;
65 import java.util.Iterator;
66 import java.util.LinkedHashSet;
67 import java.util.List;
68 import java.util.Map;
69 import java.util.Set;
70
71
72
73
74
75 public class JcrMetadataRepository
76 implements MetadataRepository
77 {
78
79 private static final String JCR_LAST_MODIFIED = "jcr:lastModified";
80
81 static final String NAMESPACE_NODE_TYPE = "archiva:namespace";
82
83 static final String PROJECT_NODE_TYPE = "archiva:project";
84
85 static final String PROJECT_VERSION_NODE_TYPE = "archiva:projectVersion";
86
87 static final String ARTIFACT_NODE_TYPE = "archiva:artifact";
88
89 static final String FACET_NODE_TYPE = "archiva:facet";
90
91 private static final String DEPENDENCY_NODE_TYPE = "archiva:dependency";
92
93 private final Map<String, MetadataFacetFactory> metadataFacetFactories;
94
95 private Logger log = LoggerFactory.getLogger( JcrMetadataRepository.class );
96
97 private Repository repository;
98
99 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
114
115
116
117
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
146
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
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
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
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
295
296
297
298
299
300
301
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
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
324
325
326
327
328
329
330
331
332
333
334
335 }
336 }
337
338 for ( MetadataFacet facet : versionMetadata.getFacetList() )
339 {
340
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
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
431
432 Node node = getJcrSession().getRootNode().getNode( getFacetPath( repositoryId, facetId ) );
433
434
435
436 recurse( facets, "", node );
437 }
438 catch ( PathNotFoundException e )
439 {
440
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
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
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
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
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
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
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
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
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();
1007
1008 n = n.getParent();
1009 String usedByProjectVersion = n.getName();
1010
1011 n = n.getParent();
1012 String usedByProject = n.getName();
1013
1014 n = n.getParent();
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
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
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 }