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