Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/slide/content/ContentImpl.java


1   /*
2    * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/content/ContentImpl.java,v 1.60 2004/08/05 15:44:57 unico Exp $
3    * $Revision: 1.60 $
4    * $Date: 2004/08/05 15:44:57 $
5    *
6    * ====================================================================
7    *
8    * Copyright 1999-2002 The Apache Software Foundation 
9    *
10   * Licensed under the Apache License, Version 2.0 (the "License");
11   * you may not use this file except in compliance with the License.
12   * You may obtain a copy of the License at
13   *
14   *     http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing, software
17   * distributed under the License is distributed on an "AS IS" BASIS,
18   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   * See the License for the specific language governing permissions and
20   * limitations under the License.
21   *
22   */
23  
24  package org.apache.slide.content;
25  
26  import java.lang.reflect.Method;
27  import java.util.Date;
28  import java.util.Enumeration;
29  import java.util.Vector;
30  
31  import org.apache.slide.common.Domain;
32  import org.apache.slide.common.Namespace;
33  import org.apache.slide.common.NamespaceConfig;
34  import org.apache.slide.common.ServiceAccessException;
35  import org.apache.slide.common.SlideToken;
36  import org.apache.slide.common.Uri;
37  import org.apache.slide.common.UriPath;
38  import org.apache.slide.lock.Lock;
39  import org.apache.slide.lock.ObjectLockedException;
40  import org.apache.slide.security.AccessDeniedException;
41  import org.apache.slide.security.Security;
42  import org.apache.slide.structure.ActionNode;
43  import org.apache.slide.structure.LinkedObjectNotFoundException;
44  import org.apache.slide.structure.ObjectNode;
45  import org.apache.slide.structure.ObjectNotFoundException;
46  import org.apache.slide.structure.Structure;
47  import org.apache.slide.structure.SubjectNode;
48  import org.apache.slide.util.Configuration;
49  import org.apache.slide.event.EventDispatcher;
50  import org.apache.slide.event.ContentEvent;
51  import org.apache.slide.event.VetoException;
52  
53  /**
54   * Implementation of the content interface.
55   *
56   * @version $Revision: 1.60 $
57   */
58  public final class ContentImpl implements Content {
59      
60      
61      // -------------------------------------------------------------- Constants
62      protected static final String I_URIREDIRECTORCLASS         = "uriRedirectorClass";
63      protected static final String I_URIREDIRECTORCLASS_DEFAULT = "org.apache.slide.webdav.util.DeltavUriRedirector";
64      
65      
66      protected static final int PRE_STORE = 0;
67      protected static final int POST_STORE = 1;
68      protected static final int POST_RETRIEVE = 2;
69      protected static final int PRE_REMOVE = 3;
70      protected static final int POST_REMOVE = 4;
71      
72      protected static Class uriRedirectorClass;
73      static {
74          try {
75              String uriRedirectorClassName = Domain.getParameter(I_URIREDIRECTORCLASS, I_URIREDIRECTORCLASS_DEFAULT);
76              uriRedirectorClass = Class.forName( uriRedirectorClassName );
77          }
78          catch( Exception x ) {
79              Domain.warn( "Loading of redirector class failed: "+x.getMessage() );
80          }
81      }
82      
83      // ----------------------------------------------------------- Constructors
84      
85      
86      /**
87       * Constructor.
88       *
89       * @param namespace Namespace
90       * @param namespaceConfig Namespace configuration
91       * @param securityHelper Security helper
92       * @param structureHelper Structure helper
93       * @param lockHelper lockHelper
94       */
95      public ContentImpl(Namespace namespace, NamespaceConfig namespaceConfig,
96                         Security securityHelper, Structure structureHelper,
97                         Lock lockHelper) {
98          this.namespace = namespace;
99          this.namespaceConfig = namespaceConfig;
100         this.securityHelper = securityHelper;
101         this.structureHelper = structureHelper;
102         this.lockHelper = lockHelper;
103     }
104     
105     
106     // ----------------------------------------------------- Instance Variables
107     
108     
109     /**
110      * Namespace.
111      */
112     private Namespace namespace;
113     
114     
115     /**
116      * Namespace configuration.
117      */
118     private NamespaceConfig namespaceConfig;
119     
120     
121     /**
122      * Security helper.
123      */
124     private Security securityHelper;
125     
126     
127     /**
128      * Structure helper.
129      */
130     private Structure structureHelper;
131     
132     
133     /**
134      * Lock helper.
135      */
136     private Lock lockHelper;
137     
138     
139     // -------------------------------------------------------- Content Methods
140     
141     
142     /**
143      * Retrieve revision descriptors.
144      *
145      * @param strUri Uri
146      * @return NodeRevisionDescriptors
147      */
148     public NodeRevisionDescriptors retrieve(SlideToken token, String strUri)
149         throws ObjectNotFoundException, AccessDeniedException,
150         LinkedObjectNotFoundException, ServiceAccessException, ObjectLockedException, VetoException {
151         
152         String originalUri = strUri;
153         strUri = redirectUri( originalUri ); // security token null - is ignored anyway
154         
155         ObjectNode associatedObject =
156             structureHelper.retrieve(token, strUri, false);
157         
158         // Checking security and locking
159         securityHelper.checkCredentials
160             (token, associatedObject,
161              namespaceConfig.getReadRevisionMetadataAction());
162         lockHelper.checkLock(token, associatedObject,
163                              namespaceConfig.getReadRevisionMetadataAction());
164         
165         Uri objectUri = namespace.getUri(token, strUri);
166         NodeRevisionDescriptors revisionDescriptors = null;
167         try {
168             revisionDescriptors = objectUri.getStore()
169                 .retrieveRevisionDescriptors(objectUri);
170         } catch (RevisionDescriptorNotFoundException e) {
171             // No revision descriptors. We have to create some.
172             revisionDescriptors = new NodeRevisionDescriptors();
173             revisionDescriptors.setUri(objectUri.toString());
174             // FIXME: createRevisionDescriptors shouldn't be done in this read-only method
175             objectUri.getStore()
176                 .createRevisionDescriptors(objectUri, revisionDescriptors);
177         }
178         
179         revisionDescriptors.setOriginalUri( originalUri );
180 
181         return revisionDescriptors;
182     }
183     
184     
185     /**
186      * Retrieve revision descriptor of the latest revision
187      * from a branch.
188      *
189      * @param revisionDescriptors Node revision descriptors
190      * @param branch String branch
191      */
192     public NodeRevisionDescriptor retrieve
193         (SlideToken token, NodeRevisionDescriptors revisionDescriptors,
194          String branch)
195         throws ObjectNotFoundException, AccessDeniedException,
196         LinkedObjectNotFoundException, ServiceAccessException,
197         RevisionDescriptorNotFoundException, ObjectLockedException,
198         BranchNotFoundException, NodeNotVersionedException, VetoException {
199         
200         NodeRevisionDescriptor result;
201         Uri objectUri = namespace.getUri(token, revisionDescriptors.getUri());
202         NodeRevisionNumber latestNrn =
203             redirectLatestRevisionNumber( revisionDescriptors.getOriginalUri() );
204         
205         NodeRevisionDescriptors realRevisionDescriptors = objectUri.getStore()
206             .retrieveRevisionDescriptors(objectUri);
207         
208         if (!realRevisionDescriptors.isVersioned()) {
209             // Invalid function call : we try to create a revision, but the
210             // descriptors won't allow it
211             throw new NodeNotVersionedException
212                 (realRevisionDescriptors.getUri().toString());
213         }
214         
215         if( latestNrn == null ) {
216             // Retrieving latest revision numbers
217             NodeRevisionNumber branchLatestRevisionNumber =
218                 realRevisionDescriptors.getLatestRevision(branch);
219             
220             if (branchLatestRevisionNumber == null) {
221                 throw new BranchNotFoundException
222                     (realRevisionDescriptors.getUri().toString(), branch);
223             }
224             result = retrieve(token, realRevisionDescriptors,
225                               branchLatestRevisionNumber);
226         }
227         else {
228             result = retrieve( token, revisionDescriptors,
229                               latestNrn );
230         }
231 
232         return result;
233     }
234     
235     
236     /**
237      * Retrieve revision descriptor.
238      *
239      * @param revisionDescriptors Node revision descriptors
240      * @param revisionNumber Node revision number
241      */
242     public NodeRevisionDescriptor retrieve
243         (SlideToken token, NodeRevisionDescriptors revisionDescriptors,
244          NodeRevisionNumber revisionNumber)
245         throws ObjectNotFoundException, AccessDeniedException,
246         LinkedObjectNotFoundException, ServiceAccessException,
247         RevisionDescriptorNotFoundException, ObjectLockedException, VetoException {
248         
249         ObjectNode associatedObject = structureHelper.retrieve
250             (token, revisionDescriptors.getUri(), false);
251         
252         // Checking security and locking
253         securityHelper.checkCredentials
254             (token, associatedObject,
255              namespaceConfig.getReadRevisionMetadataAction());
256         lockHelper.checkLock(token, associatedObject,
257                              namespaceConfig.getReadRevisionMetadataAction());
258         
259         Uri objectUri = namespace.getUri(token, revisionDescriptors.getUri());
260         
261         NodeRevisionDescriptor revisionDescriptor =
262             objectUri.getStore().retrieveRevisionDescriptor
263             (objectUri, revisionNumber);
264         
265         // Invoke interceptors
266         invokeInterceptors(token, revisionDescriptors, revisionDescriptor,
267                            null, POST_RETRIEVE);
268         
269         // Fire event
270         if ( ContentEvent.RETRIEVE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.RETRIEVE, new ContentEvent(this, token, namespace,  objectUri.toString(), revisionDescriptors, revisionDescriptor));
271 
272         return revisionDescriptor;
273     }
274     
275     
276     /**
277      * Retrieve revision descriptor from the latest revision
278      * in the main branch.
279      *
280      * @param revisionDescriptors Node revision descriptors
281      */
282     public NodeRevisionDescriptor retrieve
283         (SlideToken token, NodeRevisionDescriptors revisionDescriptors)
284         throws ObjectNotFoundException, AccessDeniedException,
285         LinkedObjectNotFoundException, ServiceAccessException,
286         RevisionDescriptorNotFoundException, ObjectLockedException, VetoException {
287         
288         NodeRevisionDescriptor result;
289         Uri objectUri = namespace.getUri(token, revisionDescriptors.getUri());
290         NodeRevisionNumber latestNrn =
291             redirectLatestRevisionNumber( revisionDescriptors.getOriginalUri() );
292         
293         NodeRevisionDescriptors realRevisionDescriptors = objectUri.getStore()
294             .retrieveRevisionDescriptors(objectUri);
295         
296         if( latestNrn == null ) {
297             result = retrieve( token, revisionDescriptors,
298                               realRevisionDescriptors.getLatestRevision());
299         }
300         else {
301             result = retrieve( token, revisionDescriptors,
302                               latestNrn );
303         }
304 
305         return result;
306     }
307     
308     
309     /**
310      * Retrieve revision content.
311      *
312      * @param revisionDescriptors Node revision descriptors
313      * @param revisionDescriptor Node revision descriptor
314      */
315     public NodeRevisionContent retrieve
316         (SlideToken token, NodeRevisionDescriptors revisionDescriptors,
317          NodeRevisionDescriptor revisionDescriptor)
318         throws ObjectNotFoundException, AccessDeniedException,
319         LinkedObjectNotFoundException, ServiceAccessException,
320         RevisionNotFoundException, RevisionContentNotFoundException,
321         ObjectLockedException, VetoException {
322         return retrieve(token, revisionDescriptors.getUri(),
323                         revisionDescriptor);
324     }
325     
326     
327     /**
328      * Retrieve revision content.
329      *
330      * @param strUri Uri
331      * @param revisionDescriptor Node revision descriptor
332      */
333     public NodeRevisionContent retrieve
334         (SlideToken token, String strUri,
335          NodeRevisionDescriptor revisionDescriptor)
336         throws ObjectNotFoundException, AccessDeniedException,
337         LinkedObjectNotFoundException, ServiceAccessException,
338         RevisionNotFoundException, RevisionContentNotFoundException,
339         ObjectLockedException, VetoException {
340         
341         ObjectNode associatedObject =
342             structureHelper.retrieve(token, strUri, false);
343         
344         // Checking security and locking
345         securityHelper.checkCredentials
346             (token, associatedObject,
347              namespaceConfig.getReadRevisionContentAction());
348         lockHelper.checkLock(token, associatedObject,
349                              namespaceConfig.getReadRevisionContentAction());
350         
351         Uri objectUri = namespace.getUri(token, strUri);
352         NodeRevisionContent revisionContent =
353             objectUri.getStore().retrieveRevisionContent(objectUri,
354                                                          revisionDescriptor);
355         
356         // Invoke interceptors
357         invokeInterceptors(token, null, revisionDescriptor,
358                            revisionContent, POST_RETRIEVE);
359         
360         // Fire event
361         if ( ContentEvent.RETRIEVE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.RETRIEVE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptor, revisionContent));
362 
363         return revisionContent;
364     }
365     
366     
367     /**
368      * Create new revision descriptors.
369      *
370      * @param strUri Uri
371      * @param isVersioned true is the resource is versioned
372      */
373     public void create(SlideToken token, String strUri,
374                        boolean isVersioned)
375         throws ObjectNotFoundException, AccessDeniedException,
376         LinkedObjectNotFoundException, ServiceAccessException,
377         ObjectLockedException, VetoException {
378         
379         // Check parent exists and is not lock-null
380         checkParentExists(strUri, token);
381         
382         // Retrieve the associated object
383         ObjectNode associatedObject =
384             structureHelper.retrieve(token, strUri, false);
385         
386         // Next we do a security check and a locking check for modifyRevisions
387         securityHelper.checkCredentials
388             (token, associatedObject,
389              namespaceConfig.getCreateRevisionMetadataAction());
390         lockHelper.checkLock
391             (token, associatedObject,
392              namespaceConfig.getCreateRevisionMetadataAction());
393         if (namespaceConfig.getCreateRevisionMetadataAction() !=
394             namespaceConfig.getCreateRevisionContentAction()) {
395             securityHelper.checkCredentials
396                 (token, associatedObject,
397                  namespaceConfig.getCreateRevisionContentAction());
398             lockHelper.checkLock
399                 (token, associatedObject,
400                  namespaceConfig.getCreateRevisionContentAction());
401         }
402         
403         Uri objectUri = namespace.getUri(token, strUri);
404         
405         NodeRevisionDescriptors revisionDescriptors =
406             new NodeRevisionDescriptors(isVersioned);
407         revisionDescriptors.setUri(strUri);
408 
409         objectUri.getStore()
410             .createRevisionDescriptors(objectUri, revisionDescriptors);
411     }
412     
413     
414     /**
415      * Create new revision in main branch.
416      *
417      * @param strUri Uri
418      * @param revisionDescriptor New Node revision descriptor
419      * @param revisionContent New Node revision content
420      */
421     public void create(SlideToken token, String strUri,
422                        NodeRevisionDescriptor revisionDescriptor,
423                        NodeRevisionContent revisionContent)
424         throws ObjectNotFoundException, AccessDeniedException,
425         RevisionAlreadyExistException, LinkedObjectNotFoundException,
426         ServiceAccessException, ObjectLockedException, VetoException {
427         
428         // Check parent exists and is not lock-null
429         checkParentExists(strUri, token);
430         
431         // Retrieve the associated object
432         ObjectNode associatedObject =
433             structureHelper.retrieve(token, strUri, false);
434         
435         // Next we do a security check and a locking check for modifyRevisions
436         securityHelper.checkCredentials
437             (token, associatedObject,
438              namespaceConfig.getCreateRevisionMetadataAction());
439         lockHelper.checkLock
440             (token, associatedObject,
441              namespaceConfig.getCreateRevisionMetadataAction());
442         if (namespaceConfig.getCreateRevisionMetadataAction() !=
443             namespaceConfig.getCreateRevisionContentAction()) {
444             securityHelper.checkCredentials
445                 (token, associatedObject,
446                  namespaceConfig.getCreateRevisionContentAction());
447             lockHelper.checkLock
448                 (token, associatedObject,
449                  namespaceConfig.getCreateRevisionContentAction());
450         }
451         
452         setDefaultProperties(associatedObject, revisionDescriptor);
453         // set the creation date if not already set
454         if (revisionDescriptor.getCreationDate() == null) {
455             revisionDescriptor.setCreationDate(new Date());
456             
457             // Set the creation user
458             setCreationUser(token, revisionDescriptor);
459         }
460         // set the display name (in case of copy)
461         if (!Configuration.useBinding(namespace.getUri(token, strUri).getStore())) {
462             if (revisionDescriptor.getName() == null || revisionDescriptor.getName().length() == 0) {
463                 revisionDescriptor.setName(new UriPath(strUri).lastSegment());
464             }
465         }
466         
467         Uri objectUri = namespace.getUri(token, strUri);
468         
469         NodeRevisionDescriptors revisionDescriptors = null;
470         try {
471             revisionDescriptors = objectUri.getStore()
472                 .retrieveRevisionDescriptors(objectUri);
473         } catch (RevisionDescriptorNotFoundException e) {
474             // No revision descriptors. We have to create some.
475             revisionDescriptors = new NodeRevisionDescriptors();
476             revisionDescriptors.setUri(objectUri.toString());
477             objectUri.getStore()
478                 .createRevisionDescriptors(objectUri, revisionDescriptors);
479         }
480         
481         // Retrieve the latest revision from the descriptor,
482         // unless there is no revisions. We generate a new revision number,
483         // basing on an existing revision, if any.
484         NodeRevisionNumber newRevisionNumber = null;
485         if (revisionDescriptors.isVersioned()) {
486             
487             if (revisionDescriptors.hasRevisions()) {
488                 newRevisionNumber = new NodeRevisionNumber
489                     (revisionDescriptors.getLatestRevision());
490                 revisionDescriptors
491                     .addSuccessor(revisionDescriptors.getLatestRevision(),
492                                   newRevisionNumber);
493                 revisionDescriptors
494                     .setSuccessors(newRevisionNumber, new Vector());
495             } else {
496                 newRevisionNumber = new NodeRevisionNumber();
497                 revisionDescriptors
498                     .setSuccessors(newRevisionNumber, new Vector());
499             }
500             // We now set the newly created revision as the latest revison
501             revisionDescriptors.setLatestRevision(newRevisionNumber);
502             
503             // We update the descriptor
504             revisionDescriptor.setRevisionNumber(newRevisionNumber);
505 
506             // Fire event
507             if ( ContentEvent.CREATE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.CREATE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptors, revisionDescriptor, revisionContent));
508 
509             // Invoke interceptors
510             invokeInterceptors(token, revisionDescriptors, revisionDescriptor,
511                                revisionContent, PRE_STORE);
512             
513             if (revisionContent != null) {
514                 // Storing the new revision contents
515                 objectUri.getStore()
516                     .createRevisionContent(objectUri, revisionDescriptor,
517                                            revisionContent);
518             }
519             // Now creating the revision desriptor in the store
520             revisionDescriptor.setModificationDate(revisionDescriptor.getCreationDate());
521             revisionDescriptor.setModificationUser(
522                 securityHelper.getPrincipal(token).getPath().lastSegment());
523             objectUri.getStore()
524                 .createRevisionDescriptor(objectUri, revisionDescriptor);
525             
526         } else {
527             // We don't use versioning for this object.
528             // Two options :
529             // - The object already has one (and only one) revision,
530             //   so we update it
531             // - The object dooesn't have any revisions right now, so we create
532             //   the initial revision
533             newRevisionNumber = new NodeRevisionNumber();
534             revisionDescriptor.setRevisionNumber(newRevisionNumber);
535             
536             if (!revisionDescriptors.hasRevisions()) {
537 
538                 // Fire event
539                 if ( ContentEvent.CREATE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.CREATE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptors, revisionDescriptor, revisionContent));
540 
541                 // Invoke interceptors
542                 invokeInterceptors(token, revisionDescriptors,
543                                    revisionDescriptor,
544                                    revisionContent, PRE_STORE);
545                 
546                 if (revisionContent != null) {
547                     // Storing the new revision contents
548                     objectUri.getStore()
549                         .createRevisionContent(objectUri, revisionDescriptor,
550                                                revisionContent);
551                 }
552                 // Now creating the revision desriptor in the store
553                 revisionDescriptor.setModificationDate(revisionDescriptor.getCreationDate());
554                 revisionDescriptor.setModificationUser(
555                     securityHelper.getPrincipal(token).getPath().lastSegment());
556                 objectUri.getStore()
557                     .createRevisionDescriptor(objectUri, revisionDescriptor);
558                 
559             } else {
560                 
561                 try { {
562                         // merge the new received properties into the
563                         // revisionDescriptor
564                         
565                         // We update the descriptor's properties
566                         NodeRevisionDescriptor oldRevisionDescriptor =
567                             objectUri.getStore()
568                             .retrieveRevisionDescriptor
569                             (objectUri, newRevisionNumber);
570                         Enumeration newPropertiesList =
571                             revisionDescriptor.enumerateProperties();
572                         while (newPropertiesList.hasMoreElements()) {
573                             oldRevisionDescriptor
574                                 .setProperty((NodeProperty) newPropertiesList
575                                                  .nextElement() );
576                         }
577                         
578                         // now use the merged revision descriptor
579                         revisionDescriptor = oldRevisionDescriptor;
580                     } // end of merge
581 
582                     // Fire event
583                     if ( ContentEvent.CREATE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.CREATE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptors, revisionDescriptor, revisionContent));
584 
585                     // Invoke interceptors
586                     invokeInterceptors(token, revisionDescriptors,
587                                        revisionDescriptor,
588                                        revisionContent, PRE_STORE);
589                     
590                     if (revisionContent != null) {
591                         // Storing the new revision contents
592                         try {
593                             objectUri.getStore()
594                                 .storeRevisionContent(objectUri,
595                                                       revisionDescriptor,
596                                                       revisionContent);
597                         } catch (RevisionNotFoundException e) {
598                             objectUri.getStore()
599                                 .createRevisionContent(objectUri,
600                                                        revisionDescriptor,
601                                                        revisionContent);
602                         }
603                     }
604                     
605                     revisionDescriptor.setModificationDate(revisionDescriptor.getCreationDate());
606                     revisionDescriptor.setModificationUser(
607                         securityHelper.getPrincipal(token).getPath().lastSegment());
608                     objectUri.getStore()
609                         .storeRevisionDescriptor
610                         (objectUri, revisionDescriptor);
611                     
612                 } catch (RevisionDescriptorNotFoundException e) {
613                     // Should NEVER happen.
614                     // Basically, it would mean that there is no initial
615                     // revision, which is incorrect since the object
616                     // HAS revisions.
617 
618                     // Fire event
619                     if ( ContentEvent.CREATE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.CREATE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptors, revisionDescriptor, revisionContent));
620 
621                     // Invoke interceptors
622                     invokeInterceptors(token, revisionDescriptors,
623                                        revisionDescriptor,
624                                        revisionContent, PRE_STORE);
625                     
626                     revisionDescriptor.setModificationDate(revisionDescriptor.getCreationDate());
627                     revisionDescriptor.setModificationUser(
628                         securityHelper.getPrincipal(token).getPath().lastSegment());
629                     objectUri.getStore()
630                         .createRevisionDescriptor(objectUri,
631                                                   revisionDescriptor);
632                 }
633             }
634             // Updating the descriptors object
635             revisionDescriptors
636                 .setSuccessors(newRevisionNumber, new Vector());
637             revisionDescriptors.setLatestRevision(newRevisionNumber);
638         }
639         
640         // We now store the updated revision descriptors
641         try {
642             objectUri.getStore()
643                 .storeRevisionDescriptors(objectUri, revisionDescriptors);
644         } catch (RevisionDescriptorNotFoundException e) {
645             // Problem ...
646             e.printStackTrace();
647         }
648         
649         // Invoke interceptors
650         invokeInterceptors(token, revisionDescriptors, revisionDescriptor,
651                            revisionContent, POST_STORE);
652     }
653     
654     
655     /**
656      * Create new revision based on a previous revision.
657      *
658      * @param strUri Uri
659      * @param branch Branch in which to create the revision
660      * @param newRevisionDescriptor New revision descriptor
661      * @param revisionContent Node revision content
662      */
663     public void create(SlideToken token, String strUri, String branch,
664                        NodeRevisionDescriptor newRevisionDescriptor,
665                        NodeRevisionContent revisionContent)
666         throws ObjectNotFoundException, AccessDeniedException,
667         RevisionAlreadyExistException, LinkedObjectNotFoundException,
668         ServiceAccessException, RevisionDescriptorNotFoundException,
669         ObjectLockedException, NodeNotVersionedException,
670         BranchNotFoundException, VetoException {
671         
672         // Check parent exists and is not lock-null
673         checkParentExists(strUri, token);
674         
675         Uri objectUri = namespace.getUri(token, strUri);
676         
677         NodeRevisionDescriptors revisionDescriptors = objectUri.getStore()
678             .retrieveRevisionDescriptors(objectUri);
679         
680         if( branch != null ) {
681             // Retrieving latest revision numbers
682             NodeRevisionNumber branchLatestRevisionNumber =
683                 revisionDescriptors.getLatestRevision(branch);
684             
685             if (branchLatestRevisionNumber == null) {
686                 throw new BranchNotFoundException(strUri, branch);
687             }
688             
689             create(token, strUri, branchLatestRevisionNumber,
690                    newRevisionDescriptor, revisionContent);
691         }
692         else {
693             // special handling for DeltaV used for the creation of the
694             // branch-less VHR descriptor at version 0.0
695             create( token, strUri, newRevisionDescriptor );
696         }
697         
698         
699     }
700     
701     
702     /**
703      * Create a branch based on specified revision.
704      *
705      * @param strUri Uri
706      * @param branchName Name of the new branch
707      * @param basedOnRevisionDescriptor Node revision descriptor of
708      *                                  the revision on which the new branch
709      *                                  is based on.
710      *
711      * @return the NodeRevisionNumber of the created revision.
712      */
713     public NodeRevisionNumber fork(SlideToken token, String strUri, String branchName,
714                                    NodeRevisionDescriptor basedOnRevisionDescriptor)
715         throws ObjectNotFoundException, AccessDeniedException,
716         LinkedObjectNotFoundException, ServiceAccessException,
717         RevisionDescriptorNotFoundException, ObjectLockedException,
718         NodeNotVersionedException, RevisionAlreadyExistException, VetoException {
719         
720         return fork(token, strUri, branchName,
721                     basedOnRevisionDescriptor.getRevisionNumber());
722         
723     }
724     
725     
726     /**
727      * Create a branch based on specified revision.
728      *
729      * @param strUri Uri
730      * @param branchName Name of the new branch
731      * @param basedOnRevisionNumber NodeRevisionNumber revision descriptor of
732      *                                  the revision on which the new branch
733      *                                  is based on.
734      *
735      * @return the NodeRevisionNumber of the created revision.
736      */
737     public NodeRevisionNumber fork(SlideToken token, String strUri, String branchName,
738                                    NodeRevisionNumber basedOnRevisionNumber)
739         throws ObjectNotFoundException, AccessDeniedException,
740         LinkedObjectNotFoundException, ServiceAccessException,
741         RevisionDescriptorNotFoundException, ObjectLockedException,
742         NodeNotVersionedException, RevisionAlreadyExistException, VetoException {
743         
744         if (branchName.equals(NodeRevisionDescriptors.MAIN_BRANCH))
745             return null;
746         
747         // Retrieve the associated object
748         ObjectNode associatedObject =
749             structureHelper.retrieve(token, strUri, false);
750         
751         // Next we do a security check and a locking check for modifyRevisions
752         securityHelper.checkCredentials
753             (token, associatedObject,
754              namespaceConfig.getCreateRevisionMetadataAction());
755         lockHelper.checkLock
756             (token, associatedObject,
757              namespaceConfig.getCreateRevisionMetadataAction());
758         securityHelper.checkCredentials
759             (token, associatedObject,
760              namespaceConfig.getCreateRevisionContentAction());
761         lockHelper.checkLock(token, associatedObject,
762                              namespaceConfig.getCreateRevisionContentAction());
763         
764         Uri objectUri = namespace.getUri(token, strUri);
765         
766         // Retrieve the revision table
767         NodeRevisionDescriptors revisionDescriptors =
768             objectUri.getStore()
769             .retrieveRevisionDescriptors(objectUri);
770         
771         if (!revisionDescriptors.isVersioned()) {
772             // Invalid function call : we try to create a revision, but the
773             // descriptors won't allow it
774             throw new NodeNotVersionedException(strUri);
775         }
776         
777         // Retrieving the revision on which the new branch is based.
778         NodeRevisionDescriptor basedOnRevisionDescriptor =
779             objectUri.getStore().retrieveRevisionDescriptor
780             (objectUri, basedOnRevisionNumber);
781         NodeRevisionContent basedOnRevisionContent = null;
782         try {
783             basedOnRevisionContent =
784                 objectUri.getStore().retrieveRevisionContent
785                 (objectUri,
786                  basedOnRevisionDescriptor);
787         } catch (RevisionNotFoundException e) {
788         }
789         
790         // Create a revision number suited for the new branch
791         NodeRevisionNumber branchedRevisionNumber =
792             new NodeRevisionNumber(basedOnRevisionNumber, true);
793         
794         basedOnRevisionDescriptor.setRevisionNumber(branchedRevisionNumber);
795         basedOnRevisionDescriptor.setBranchName(branchName);
796         
797         revisionDescriptors.setUri(strUri);
798         revisionDescriptors.setLatestRevision
799             (branchName, branchedRevisionNumber);
800         revisionDescriptors.addSuccessor
801             (basedOnRevisionNumber, branchedRevisionNumber);
802         
803         // Fire event
804         if ( ContentEvent.FORK.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.FORK, new ContentEvent(this, token, namespace, strUri, revisionDescriptors));
805 
806         // Invoke interceptors
807         invokeInterceptors(token, revisionDescriptors,
808                            basedOnRevisionDescriptor,
809                            basedOnRevisionContent, PRE_STORE);
810         
811         // Storing back everything
812         // TODO: setModificationDate
813         //       clone of NRD required??
814         if (basedOnRevisionContent != null) {
815             objectUri.getStore().createRevisionContent
816                 (objectUri, basedOnRevisionDescriptor, basedOnRevisionContent);
817         }
818         objectUri.getStore().createRevisionDescriptor
819             (objectUri, basedOnRevisionDescriptor);
820         objectUri.getStore().storeRevisionDescriptors
821             (objectUri, revisionDescriptors);
822         
823         // Invoke interceptors
824         invokeInterceptors(token, revisionDescriptors,
825                            basedOnRevisionDescriptor,
826                            basedOnRevisionContent, POST_STORE);
827 
828         return branchedRevisionNumber;
829     }
830     
831     
832     /**
833      * Merge specified branches into a single branch.
834      *
835      * @param strUri Uri
836      * @param mainBranch Branch into which the other branch will be merged
837      * @param branch Branch to merge into main branch
838      * @param newRevisionDescriptor New revision descriptor
839      * @param revisionContent Node revision content
840      */
841     public void merge(SlideToken token, String strUri,
842                       NodeRevisionDescriptor mainBranch,
843                       NodeRevisionDescriptor branch,
844                       NodeRevisionDescriptor newRevisionDescriptor,
845                       NodeRevisionContent revisionContent)
846         throws ObjectNotFoundException, AccessDeniedException,
847         LinkedObjectNotFoundException, ServiceAccessException,
848         RevisionDescriptorNotFoundException, ObjectLockedException,
849         NodeNotVersionedException, BranchNotFoundException,
850         RevisionAlreadyExistException, VetoException {
851         
852         merge(token, strUri, mainBranch.getBranchName(),
853               branch.getBranchName(), newRevisionDescriptor, revisionContent);
854         
855     }
856     
857     
858     /**
859      * Merge specified branches into a single branch.
860      *
861      * @param strUri Uri
862      * @param mainBranch Branch into which the other branch will be merged
863      * @param branch Branch to merge into main branch
864      * @param newRevisionDescriptor New revision descriptor
865      * @param revisionContent Node revision content
866      */
867     public void merge(SlideToken token, String strUri,
868                       String mainBranch, String branch,
869                       NodeRevisionDescriptor newRevisionDescriptor,
870                       NodeRevisionContent revisionContent)
871         throws ObjectNotFoundException, AccessDeniedException,
872         LinkedObjectNotFoundException, ServiceAccessException,
873         RevisionDescriptorNotFoundException, ObjectLockedException,
874         NodeNotVersionedException, BranchNotFoundException,
875         RevisionAlreadyExistException, VetoException {
876         
877         // Retrieve the associated object
878         ObjectNode associatedObject =
879             structureHelper.retrieve(token, strUri, false);
880         
881         // Next we do a security check and a locking check for modifyRevisions
882         securityHelper.checkCredentials
883             (token, associatedObject,
884              namespaceConfig.getCreateRevisionMetadataAction());
885         lockHelper.checkLock
886             (token, associatedObject,
887              namespaceConfig.getCreateRevisionMetadataAction());
888         securityHelper.checkCredentials
889             (token, associatedObject,
890              namespaceConfig.getCreateRevisionContentAction());
891         lockHelper.checkLock(token, associatedObject,
892                              namespaceConfig.getCreateRevisionContentAction());
893         
894         setDefaultProperties(associatedObject, newRevisionDescriptor);
895         
896         Uri objectUri = namespace.getUri(token, strUri);
897         
898         // Retrieve the revision table
899         NodeRevisionDescriptors revisionDescriptors =
900             objectUri.getStore().retrieveRevisionDescriptors(objectUri);
901         
902         if (!revisionDescriptors.isVersioned()) {
903             // Invalid function call : we try to create a revision, but the
904             // descriptors won't allow it
905             throw new NodeNotVersionedException(strUri);
906         }
907         
908         // Retrieving latest revision numbers
909         NodeRevisionNumber mainBranchLatestRevisionNumber =
910             revisionDescriptors.getLatestRevision(mainBranch);
911         NodeRevisionNumber branchLatestRevisionNumber =
912             revisionDescriptors.getLatestRevision(branch);
913         
914         if (mainBranchLatestRevisionNumber == null) {
915             throw new BranchNotFoundException(strUri, mainBranch);
916         }
917         if (branchLatestRevisionNumber == null) {
918             throw new BranchNotFoundException(strUri, branch);
919         }
920         
921         NodeRevisionNumber newRevisionNumber =
922             new NodeRevisionNumber(mainBranchLatestRevisionNumber);
923         
924         newRevisionDescriptor.setRevisionNumber(newRevisionNumber);
925         newRevisionDescriptor.setBranchName(branch);
926         
927         revisionDescriptors.addSuccessor
928             (mainBranchLatestRevisionNumber, newRevisionNumber);
929         revisionDescriptors.addSuccessor
930             (branchLatestRevisionNumber, newRevisionNumber);
931         revisionDescriptors.setLatestRevision(mainBranch, newRevisionNumber);
932         
933         // Fire event
934         if ( ContentEvent.MERGE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.MERGE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptors, newRevisionDescriptor, revisionContent));
935 
936         // Invoke interceptors
937         invokeInterceptors(token, revisionDescriptors, newRevisionDescriptor,
938                            revisionContent, PRE_STORE);
939         
940         // Storing back everything
941         if (revisionContent != null) {
942             objectUri.getStore().createRevisionContent
943                 (objectUri, newRevisionDescriptor, revisionContent);
944         }
945         newRevisionDescriptor.setModificationDate(newRevisionDescriptor.getCreationDate());
946         newRevisionDescriptor.setModificationUser(
947             securityHelper.getPrincipal(token).getPath().lastSegment());
948         objectUri.getStore().createRevisionDescriptor
949             (objectUri, newRevisionDescriptor);
950         objectUri.getStore().storeRevisionDescriptors
951             (objectUri, revisionDescriptors);
952         
953         // Invoke interceptors
954         invokeInterceptors(token, revisionDescriptors, newRevisionDescriptor,
955                            revisionContent, POST_STORE);
956     }
957     
958     
959     /**
960      * Update contents of an existing revision.
961      *
962      * @param strUri Uri
963      * @param revisionDescriptor Revision descriptor
964      * @param revisionContent Revision content
965      */
966     public void store(SlideToken token, String strUri,
967                       NodeRevisionDescriptor revisionDescriptor,
968                       NodeRevisionContent revisionContent)
969         throws ObjectNotFoundException, AccessDeniedException,
970         LinkedObjectNotFoundException, ServiceAccessException,
971         RevisionDescriptorNotFoundException, ObjectLockedException,
972         RevisionNotFoundException, VetoException {
973         
974         // Retrieve the associated object
975         ObjectNode associatedObject =
976             structureHelper.retrieve(token, strUri, false);
977         
978         // Next we do a security check and a locking check for modifyRevisions
979         securityHelper.checkCredentials
980             (token, associatedObject,
981              namespaceConfig.getModifyRevisionMetadataAction());
982         lockHelper.checkLock
983             (token, associatedObject,
984              namespaceConfig.getModifyRevisionMetadataAction());
985         securityHelper.checkCredentials
986             (token, associatedObject,
987              namespaceConfig.getModifyRevisionContentAction());
988         lockHelper.checkLock(token, associatedObject,
989                              namespaceConfig.getModifyRevisionContentAction());
990         
991         setDefaultProperties(associatedObject, revisionDescriptor);
992         
993         Uri objectUri = namespace.getUri(token, strUri);
994         
995         // Retrieve the revision table
996         NodeRevisionDescriptors revisionDescriptors =
997             objectUri.getStore().retrieveRevisionDescriptors(objectUri);
998 
999         // Fire event
1000        if ( revisionDescriptor.getRevisionNumber() != NodeRevisionNumber.HIDDEN_0_0 && ContentEvent.STORE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.STORE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptors, revisionDescriptor, revisionContent));
1001
1002        // Invoke interceptors
1003        invokeInterceptors(token, revisionDescriptors, revisionDescriptor,
1004                           revisionContent, PRE_STORE);
1005        
1006        if (revisionContent != null) {
1007            try {
1008                // Removed retrieveContent call [pnever, 25-APR-2003].
1009                // Reasons:
1010                // - it is not necessary to check existence because storeRevisionContent also throws RevisionNotFoundException
1011                // - it is harmful for filesystem-based stores, as the input streams created by retrieveRevisionContent never are closed
1012                // Simple scenario:
1013                // Use the FileContentStore, create a file, update it and then try to delete it.
1014                // It will not be deleted from the filesystem.
1015                //
1016                //                objectUri.getStore().retrieveRevisionContent
1017                //                    (objectUri, revisionDescriptor);
1018                objectUri.getStore().storeRevisionContent
1019                    (objectUri, revisionDescriptor, revisionContent);
1020            } catch (RevisionNotFoundException e) {
1021                try {
1022                    objectUri.getStore().createRevisionContent
1023                        (objectUri, revisionDescriptor, revisionContent);
1024                } catch (RevisionAlreadyExistException ex) {
1025                    // Should never happen
1026                    ex.printStackTrace();
1027                }
1028            }
1029        }
1030        revisionDescriptor.setModificationDate(new Date());
1031        revisionDescriptor.setModificationUser(
1032            securityHelper.getPrincipal(token).getPath().lastSegment());
1033        objectUri.getStore().storeRevisionDescriptor
1034            (objectUri, revisionDescriptor);
1035        
1036        // Invoke interceptors
1037        invokeInterceptors(token, revisionDescriptors, revisionDescriptor,
1038                           revisionContent, POST_STORE);
1039    }
1040    
1041    
1042    /**
1043     * Remove all revisions at this Uri.
1044     *
1045     * @param revisionDescriptors Node revision descriptors
1046     */
1047    public void remove(SlideToken token,
1048                       NodeRevisionDescriptors revisionDescriptors)
1049        throws ObjectNotFoundException, AccessDeniedException,
1050        LinkedObjectNotFoundException, ServiceAccessException,
1051        RevisionDescriptorNotFoundException, ObjectLockedException, VetoException {
1052        
1053        // Invoke interceptors
1054        invokeInterceptors(token, revisionDescriptors, null, null, PRE_REMOVE);
1055
1056        // Retrieve the associated object
1057        ObjectNode associatedObject = structureHelper.retrieve
1058            (token, revisionDescriptors.getUri(), false);
1059        
1060        // Next we do a security check and a locking check for modifyRevisions
1061        securityHelper.checkCredentials
1062            (token, associatedObject,
1063             namespaceConfig.getRemoveRevisionMetadataAction());
1064        lockHelper.checkLock
1065            (token, associatedObject,
1066             namespaceConfig.getRemoveRevisionMetadataAction());
1067        securityHelper.checkCredentials
1068            (token, associatedObject,
1069             namespaceConfig.getRemoveRevisionContentAction());
1070        lockHelper.checkLock(token, associatedObject,
1071                             namespaceConfig.getRemoveRevisionContentAction());
1072        
1073        Uri objectUri = namespace.getUri(token, revisionDescriptors.getUri());
1074
1075        // Fire event
1076        if ( ContentEvent.REMOVE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.REMOVE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptors));
1077
1078        objectUri.getStore().removeRevisionDescriptors(objectUri);
1079        
1080        // Invoke interceptors
1081        invokeInterceptors(token, revisionDescriptors, null, null,
1082                           POST_REMOVE);
1083    }
1084    
1085    
1086    /**
1087     * Remove specified revision.
1088     *
1089     * @param strUri Uri
1090     * @param revisionDescriptor Node revision descriptor
1091     */
1092    public void remove(SlideToken token, String strUri,
1093                       NodeRevisionDescriptor revisionDescriptor)
1094        throws ObjectNotFoundException, AccessDeniedException,
1095        LinkedObjectNotFoundException, ServiceAccessException,
1096        RevisionDescriptorNotFoundException, ObjectLockedException, VetoException {
1097        
1098        remove(token, strUri, revisionDescriptor.getRevisionNumber());
1099        
1100    }
1101    
1102    
1103    /**
1104     * Remove specified revision.
1105     *
1106     * @param strUri Uri
1107     * @param revisionNumber Revision number
1108     */
1109    public void remove(SlideToken token, String strUri,
1110                       NodeRevisionNumber revisionNumber)
1111        throws ObjectNotFoundException, AccessDeniedException,
1112        LinkedObjectNotFoundException, ServiceAccessException,
1113        RevisionDescriptorNotFoundException, ObjectLockedException, VetoException {
1114        
1115        // Retrieve the associated object
1116        ObjectNode associatedObject =
1117            structureHelper.retrieve(token, strUri, false);
1118        
1119        // Next we do a security check and a locking check for modifyRevisions
1120        securityHelper.checkCredentials
1121            (token, associatedObject,
1122             namespaceConfig.getRemoveRevisionMetadataAction());
1123        lockHelper.checkLock
1124            (token, associatedObject,
1125             namespaceConfig.getRemoveRevisionMetadataAction());
1126        securityHelper.checkCredentials
1127            (token, associatedObject,
1128             namespaceConfig.getRemoveRevisionContentAction());
1129        lockHelper.checkLock(token, associatedObject,
1130                             namespaceConfig.getRemoveRevisionContentAction());
1131        
1132        Uri objectUri = namespace.getUri(token, strUri);
1133        
1134        NodeRevisionDescriptor revisionDescriptor =
1135            objectUri.getStore().retrieveRevisionDescriptor
1136            (objectUri, revisionNumber);
1137
1138        // Fire event
1139        if ( revisionNumber != NodeRevisionNumber.HIDDEN_0_0 && ContentEvent.REMOVE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.REMOVE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptor));
1140
1141        // Invoke interceptors
1142        invokeInterceptors(token, null, revisionDescriptor, null, PRE_REMOVE);
1143        
1144        objectUri.getStore().removeRevisionContent
1145            (objectUri, revisionDescriptor);
1146        objectUri.getStore()
1147            .removeRevisionDescriptor(objectUri, revisionNumber);
1148        
1149        // Invoke interceptors
1150        invokeInterceptors(token, null, revisionDescriptor, null, POST_REMOVE);
1151    }
1152    
1153    
1154    // ------------------------------------------------------ Protected Methods
1155    
1156    
1157    /**
1158     * Create new revision based on a previous revision.
1159     *
1160     * @param strUri Uri
1161     * @param basedOnRevisionNumber Number of revision on which the
1162     * new revision is based
1163     * @param newRevisionDescriptor New revision descriptor
1164     * @param revisionContent Node revision content
1165     */
1166    protected void create(SlideToken token, String strUri,
1167                          NodeRevisionNumber basedOnRevisionNumber,
1168                          NodeRevisionDescriptor newRevisionDescriptor,
1169                          NodeRevisionContent revisionContent)
1170        throws ObjectNotFoundException, AccessDeniedException,
1171        RevisionAlreadyExistException, LinkedObjectNotFoundException,
1172        ServiceAccessException, RevisionDescriptorNotFoundException,
1173        ObjectLockedException, NodeNotVersionedException, VetoException {
1174        
1175        // Retrieve the associated object
1176        ObjectNode associatedObject =
1177            structureHelper.retrieve(token, strUri, false);
1178        
1179        // Next we do a security check and a locking check for modifyRevisions
1180        securityHelper.checkCredentials
1181            (token, associatedObject,
1182             namespaceConfig.getCreateRevisionMetadataAction());
1183        lockHelper.checkLock
1184            (token, associatedObject,
1185             namespaceConfig.getCreateRevisionMetadataAction());
1186        securityHelper.checkCredentials
1187            (token, associatedObject,
1188             namespaceConfig.getCreateRevisionContentAction());
1189        lockHelper.checkLock(token, associatedObject,
1190                             namespaceConfig.getCreateRevisionContentAction());
1191        
1192        setDefaultProperties(associatedObject, newRevisionDescriptor);
1193        
1194        Uri objectUri = namespace.getUri(token, strUri);
1195        
1196        // Retrieve the revision table
1197        NodeRevisionDescriptors revisionDescriptors =
1198            objectUri.getStore()
1199            .retrieveRevisionDescriptors(objectUri);
1200        
1201        if (!revisionDescriptors.isVersioned()) {
1202            // Invalid function call : we try to create a revision, but the
1203            // descriptors won't allow it
1204            throw new NodeNotVersionedException(strUri);
1205        }
1206        
1207        // Retrieve the old revision descriptor, just to make sure that the old
1208        //  revision we base the new one upon really exists
1209        NodeRevisionDescriptor realOldRevisionDescriptor =
1210            objectUri.getStore().retrieveRevisionDescriptor
1211            (objectUri, basedOnRevisionNumber);
1212        
1213        // We check that the old revision doesn't have successors, that is we :
1214        // - check to see if it's the latest revision in a branch
1215        // - store that information for later use
1216        NodeRevisionNumber latestNumberInBranch =
1217            revisionDescriptors.getLatestRevision
1218            (realOldRevisionDescriptor.getBranchName());
1219        if (!realOldRevisionDescriptor.getRevisionNumber()
1220            .equals(latestNumberInBranch)) {
1221            throw new RevisionAlreadyExistException
1222                (objectUri.toString(), new NodeRevisionNumber
1223                     (basedOnRevisionNumber));
1224        }
1225        
1226        // Next, generate the new revision's number
1227        newRevisionDescriptor.setRevisionNumber
1228            (new NodeRevisionNumber(basedOnRevisionNumber));
1229        // Set the creation date
1230        newRevisionDescriptor.setCreationDate(new Date());
1231        
1232        // Set the creation user
1233        setCreationUser(token, newRevisionDescriptor);
1234        
1235        // Initialize the branch name in the new descriptor
1236        newRevisionDescriptor.setBranchName
1237            (realOldRevisionDescriptor.getBranchName());
1238
1239        // Fire event
1240        if ( ContentEvent.CREATE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.CREATE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptors, newRevisionDescriptor, revisionContent));
1241
1242        // Invoke interceptors
1243        invokeInterceptors(token, revisionDescriptors, newRevisionDescriptor,
1244                           revisionContent, PRE_STORE);
1245        
1246        // Update the revision graph in the revision descriptors
1247        revisionDescriptors
1248            .addSuccessor(revisionDescriptors.getLatestRevision(newRevisionDescriptor.getBranchName()),
1249                          newRevisionDescriptor.getRevisionNumber());
1250        revisionDescriptors
1251            .setSuccessors(newRevisionDescriptor.getRevisionNumber(), new Vector());
1252        revisionDescriptors
1253            .setLatestRevision(newRevisionDescriptor.getBranchName(),
1254                               newRevisionDescriptor.getRevisionNumber());
1255        if (revisionContent != null) {
1256            // Storing the new revision contents
1257            objectUri.getStore()
1258                .createRevisionContent(objectUri, newRevisionDescriptor,
1259                                       revisionContent);
1260        }
1261        // Now creating the revision desriptor in the store
1262        newRevisionDescriptor.setModificationDate(newRevisionDescriptor.getCreationDate());
1263        newRevisionDescriptor.setModificationUser(
1264            securityHelper.getPrincipal(token).getPath().lastSegment());
1265        objectUri.getStore()
1266            .createRevisionDescriptor(objectUri, newRevisionDescriptor);
1267        
1268        // We now store the updated revision descriptors
1269        try {
1270            objectUri.getStore()
1271                .storeRevisionDescriptors(objectUri, revisionDescriptors);
1272        } catch (RevisionDescriptorNotFoundException e) {
1273            // Problem ...
1274            e.printStackTrace();
1275        }
1276        
1277        // Invoke interceptors
1278        invokeInterceptors(token, revisionDescriptors, newRevisionDescriptor,
1279                           revisionContent, POST_STORE);
1280    }
1281    
1282    
1283    /**
1284     * Create new branch-less revision descriptor.
1285     * This is used only by DeltaV to store the VHR-specific descriptor at
1286     * revision 0.0, or to backup the properties of a VCR for checkout/uncheckout
1287     * at revision 0.0.
1288     */
1289    protected void create( SlideToken token, String strUri,
1290                          NodeRevisionDescriptor revisionDescriptor )
1291        throws ObjectNotFoundException, AccessDeniedException,
1292        RevisionAlreadyExistException, LinkedObjectNotFoundException,
1293        ServiceAccessException, RevisionDescriptorNotFoundException,
1294        ObjectLockedException, NodeNotVersionedException, VetoException {
1295        
1296        // Retrieve the associated object
1297        ObjectNode associatedObject =
1298            structureHelper.retrieve(token, strUri, false);
1299        
1300        // Next we do a security check and a locking check for modifyRevisions
1301        securityHelper.checkCredentials
1302            (token, associatedObject,
1303             namespaceConfig.getCreateRevisionMetadataAction());
1304        lockHelper.checkLock
1305            (token, associatedObject,
1306             namespaceConfig.getCreateRevisionMetadataAction());
1307        securityHelper.checkCredentials
1308            (token, associatedObject,
1309             namespaceConfig.getCreateRevisionContentAction());
1310        lockHelper.checkLock(token, associatedObject,
1311                             namespaceConfig.getCreateRevisionContentAction());
1312        
1313        setDefaultProperties(associatedObject, revisionDescriptor);
1314        
1315        Uri objectUri = namespace.getUri(token, strUri);
1316        
1317        // Retrieve the revision table
1318        NodeRevisionDescriptors revisionDescriptors =
1319            objectUri.getStore()
1320            .retrieveRevisionDescriptors(objectUri);
1321        
1322        // Set the creation date
1323        revisionDescriptor.setCreationDate(new Date());
1324        
1325        // Set the creation user
1326        setCreationUser(token, revisionDescriptor);
1327        
1328        // Initialize the branch name in the new descriptor
1329        String branchName = "backup";
1330        NodeProperty rootVersionProperty = revisionDescriptor.getProperty("version-set");
1331        if (rootVersionProperty != null) {
1332            branchName = "version-history";
1333        }
1334        revisionDescriptor.setBranchName(branchName);
1335
1336        // Fire event
1337        if ( revisionDescriptor.getRevisionNumber() != NodeRevisionNumber.HIDDEN_0_0 && ContentEvent.CREATE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(ContentEvent.CREATE, new ContentEvent(this, token, namespace, objectUri.toString(), revisionDescriptors, revisionDescriptor));
1338
1339        // Invoke interceptors
1340        invokeInterceptors(token, revisionDescriptors, revisionDescriptor,
1341                           null, PRE_STORE);
1342        
1343        // Now creating the revision desriptor in the store
1344        revisionDescriptor.setModificationDate(revisionDescriptor.getCreationDate());
1345        revisionDescriptor.setModificationUser(
1346            securityHelper.getPrincipal(token).getPath().lastSegment());
1347        objectUri.getStore()
1348            .createRevisionDescriptor(objectUri, revisionDescriptor);
1349        
1350        // We now store the updated revision descriptors
1351        try {
1352            objectUri.getStore()
1353                .storeRevisionDescriptors(objectUri, revisionDescriptors);
1354        } catch (RevisionDescriptorNotFoundException e) {
1355            // Problem ...
1356            e.printStackTrace();
1357        }
1358        
1359        // Invoke interceptors
1360        invokeInterceptors(token, revisionDescriptors, revisionDescriptor,
1361                           null, POST_STORE);
1362    }
1363    
1364    private void setCreationUser(SlideToken token, NodeRevisionDescriptor revisionDescriptor) throws ServiceAccessException, ObjectNotFoundException {
1365        String creationUser = ((SubjectNode)securityHelper.getPrincipal(token)).getPath().lastSegment();
1366        revisionDescriptor.setCreationUser(creationUser);
1367        revisionDescriptor.setOwner(creationUser);
1368    }
1369    
1370    
1371    /**
1372     * Set default properties for a revision descriptors.
1373     */
1374    protected void setDefaultProperties
1375        (ObjectNode associatedObject,
1376         NodeRevisionDescriptor revisionDescriptor) {
1377        // Retrieving the roles of the associated object
1378        Enumeration roles = securityHelper.getRoles(associatedObject);
1379        while (roles.hasMoreElements()) {
1380            String role = (String) roles.nextElement();
1381            Enumeration defaultProperties =
1382                namespaceConfig.getDefaultProperties(role);
1383            revisionDescriptor.setDefaultProperties(defaultProperties);
1384        }
1385        if (namespaceConfig.isPrincipal(associatedObject.getUri())) {
1386            // principals must have DAV:displayname
1387            if (revisionDescriptor.getName() == null || revisionDescriptor.getName().length() == 0) {
1388                UriPath uripath = new UriPath(associatedObject.getUri());
1389                revisionDescriptor.setName(uripath.lastSegment());
1390            }
1391            // principals must have DAV:principal in resourcetype
1392            String rt = revisionDescriptor.getResourceType();
1393            if (rt.indexOf("principal") < 0) {
1394                revisionDescriptor.setResourceType(rt+"<principal/>");
1395            }
1396        }
1397    }
1398    
1399    
1400    /**
1401     * Invoke content interceptors.
1402     */
1403    protected void invokeInterceptors
1404        (SlideToken token, NodeRevisionDescriptors revisionDescriptors,
1405         NodeRevisionDescriptor revisionDescriptor,
1406         NodeRevisionContent revisionContent, int type)
1407        throws AccessDeniedException, ObjectNotFoundException,
1408        LinkedObjectNotFoundException, ObjectLockedException,
1409        ServiceAccessException {
1410        ContentInterceptor[] contentInterceptors =
1411            namespace.getContentInterceptors();
1412        for (int i = 0; i < contentInterceptors.length; i++) {
1413            switch (type) {
1414                case PRE_STORE:
1415                    contentInterceptors[i].preStoreContent
1416                        (token, revisionDescriptors,
1417                         revisionDescriptor, revisionContent);
1418                    break;
1419                case POST_STORE:
1420                    contentInterceptors[i].postStoreContent
1421                        (token, revisionDescriptors,
1422                         revisionDescriptor, revisionContent);
1423                    break;
1424                case POST_RETRIEVE:
1425                    contentInterceptors[i].postRetrieveContent
1426                        (token, revisionDescriptors,
1427                         revisionDescriptor, revisionContent);
1428                    break;
1429                case PRE_REMOVE:
1430                    contentInterceptors[i].preRemoveContent
1431                        (token, revisionDescriptors, revisionDescriptor);
1432                    break;
1433                case POST_REMOVE:
1434                    contentInterceptors[i].postRemoveContent
1435                        (token, revisionDescriptors, revisionDescriptor);
1436                    break;
1437            }
1438        }
1439    }
1440    
1441    /**
1442     *
1443     */
1444    protected String redirectUri( String uri ) {
1445        String result = uri;
1446        
1447        if( uriRedirectorClass != null ) {
1448            try {
1449                Method ru = uriRedirectorClass.getMethod(
1450                    "redirectUri", new Class[]{String.class} );
1451                result = (String)ru.invoke( null, new Object[]{uri} ); // obj=null since method is static
1452            }
1453            catch( Exception x ) {
1454                Domain.warn( "Redirecting of URI "+uri+" failed: "+x.getMessage() );
1455            }
1456        }
1457        
1458        return result;
1459    }
1460    
1461    /**
1462     *
1463     */
1464    protected NodeRevisionNumber redirectLatestRevisionNumber( String uri ) {
1465        NodeRevisionNumber result = null;
1466        
1467        if( uriRedirectorClass != null ) {
1468            try {
1469                Method ru = uriRedirectorClass.getMethod(
1470                    "redirectLatestRevisionNumber", new Class[]{String.class} );
1471                result = (NodeRevisionNumber)ru.invoke( null, new Object[]{uri} ); // obj=null since method is static
1472            }
1473            catch( Exception x ) {
1474                Domain.warn( "Redirecting of latest revision number for "+uri+" failed: "+x.getMessage() );
1475            }
1476        }
1477        
1478        return result;
1479    }
1480    
1481    private boolean isLockNull( NodeRevisionDescriptor nrd ) {
1482        return nrd.propertyValueContains("resourcetype", "lock-null");
1483    }
1484    
1485    private void checkParentExists(String strUri, SlideToken token)
1486        throws ServiceAccessException, ObjectLockedException, AccessDeniedException,
1487        LinkedObjectNotFoundException, ObjectNotFoundException, VetoException {
1488        
1489        if (namespaceConfig.getCreateObjectAction().equals(ActionNode.DEFAULT)) {
1490            // do not check during start-up
1491            return;
1492        }
1493        
1494        String parentUri = String.valueOf(new UriPath(strUri).parent());
1495        try {
1496            NodeRevisionDescriptor parentNrd =
1497                retrieve(token, retrieve(token, parentUri));
1498            if (isLockNull(parentNrd)) {
1499                throw new ObjectNotFoundException(parentUri);
1500            }
1501        }
1502        catch (RevisionDescriptorNotFoundException e) {
1503            throw new ObjectNotFoundException(parentUri);
1504        }
1505    }
1506}
1507
1508