Source code: org/apache/slide/structure/StructureImpl.java
1 /*
2 * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/structure/StructureImpl.java,v 1.49.2.3 2004/10/27 15:43:11 ozeigermann Exp $
3 * $Revision: 1.49.2.3 $
4 * $Date: 2004/10/27 15:43:11 $
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.structure;
25
26 import java.util.ArrayList;
27 import java.util.Date;
28 import java.util.Enumeration;
29 import java.util.List;
30 import java.util.Vector;
31
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.common.UriTokenizer;
39 import org.apache.slide.content.NodeRevisionDescriptor;
40 import org.apache.slide.content.NodeRevisionNumber;
41 import org.apache.slide.content.RevisionDescriptorNotFoundException;
42 import org.apache.slide.event.EventDispatcher;
43 import org.apache.slide.event.StructureEvent;
44 import org.apache.slide.event.VetoException;
45 import org.apache.slide.lock.Lock;
46 import org.apache.slide.lock.ObjectLockedException;
47 import org.apache.slide.security.AccessDeniedException;
48 import org.apache.slide.security.Security;
49 import org.apache.slide.store.Store;
50 import org.apache.slide.util.Configuration;
51
52 /**
53 * Default implementation of the Structure interface.
54 *
55 * @version $Revision: 1.49.2.3 $
56 */
57 public final class StructureImpl implements Structure {
58
59
60 // ----------------------------------------------------------- Constructors
61
62
63 /**
64 * Constructor.
65 *
66 * @param namespace the namespace associated with the helper object
67 * @param namespaceConfig configuration of the namespace
68 * @param securityHelper the associated security helper
69 * @param lockHelper the associated lock helper
70 */
71 public StructureImpl(Namespace namespace, NamespaceConfig namespaceConfig,
72 Security securityHelper, Lock lockHelper) {
73 this.namespace = namespace;
74 this.namespaceConfig = namespaceConfig;
75 this.securityHelper = securityHelper;
76 this.lockHelper = lockHelper;
77 }
78
79
80 // ----------------------------------------------------- Instance Variables
81
82
83 /**
84 * Namespace.
85 */
86 private Namespace namespace;
87
88
89 /**
90 * Namespace configuration.
91 */
92 private NamespaceConfig namespaceConfig;
93
94
95 /**
96 * Security helper.
97 */
98 private Security securityHelper;
99
100
101 /**
102 * Lock helper.
103 */
104 private Lock lockHelper;
105
106
107 // ------------------------------------------------------ Structure Methods
108
109 public String generateUniqueUri(SlideToken token, String parentUri) throws ServiceAccessException {
110 String sequenceName = parentUri.replace('/', '-');
111
112 Uri uri = namespace.getUri(token, parentUri);
113 Store store = uri.getStore();
114 if (!store.isSequenceSupported()) {
115 return null;
116 } else {
117 if (!store.sequenceExists(sequenceName)) {
118 store.createSequence(sequenceName);
119 }
120 long next = store.nextSequenceValue(sequenceName);
121 String uniqueUri = parentUri + "/" + next;
122 return uniqueUri;
123 }
124 }
125
126 public Enumeration getChildren(SlideToken token, ObjectNode object)
127 throws ServiceAccessException, ObjectNotFoundException,
128 LinkedObjectNotFoundException, VetoException {
129 Enumeration childrenUri = object.enumerateChildren();
130 Vector result = new Vector();
131 while (childrenUri.hasMoreElements()) {
132 String childUri = (String) childrenUri.nextElement();
133 try {
134 ObjectNode child = retrieve(token, childUri, false);
135 result.addElement(child);
136 } catch (AccessDeniedException e) {
137 }
138 }
139 return result.elements();
140 }
141
142
143 public ObjectNode getParent(SlideToken token, ObjectNode object)
144 throws ServiceAccessException, ObjectNotFoundException,
145 LinkedObjectNotFoundException, AccessDeniedException, VetoException {
146 String objectUriStr = object.getUri();
147 Uri parentUri = namespace.getUri(token, objectUriStr).getParentUri();
148 if (parentUri == null) {
149 return null;
150 }
151 String parentUriStr = parentUri.toString();
152 ObjectNode parent = retrieve(token, parentUriStr);
153 return parent;
154 }
155
156
157 public ObjectNode retrieve(SlideToken token, String strUri)
158 throws ServiceAccessException, ObjectNotFoundException,
159 LinkedObjectNotFoundException, AccessDeniedException, VetoException {
160 return retrieve(token, strUri, true);
161 }
162
163
164 public ObjectNode retrieve(SlideToken token, String strUri,
165 boolean translateLastUriElement)
166 throws ServiceAccessException, ObjectNotFoundException,
167 LinkedObjectNotFoundException, AccessDeniedException, VetoException {
168
169 Uri uri = namespace.getUri(token, strUri);
170
171 ObjectNode result = null;
172
173 // Fire event
174 if ( StructureEvent.RETRIEVE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(StructureEvent.RETRIEVE, new StructureEvent(this, token, namespace, strUri));
175
176 // First of all, we try to load the object directly from the given Uri.
177 try {
178 result = uri.getStore().retrieveObject(uri);
179 securityHelper.checkCredentials
180 (token, result, namespaceConfig.getReadObjectAction());
181 if ((translateLastUriElement) && (result instanceof LinkNode)) {
182 LinkNode link = (LinkNode) result;
183 Uri linkedUri = namespace.getUri(token, link.getLinkedUri());
184 result = linkedUri.getStore()
185 .retrieveObject(linkedUri);
186 securityHelper.checkCredentials
187 (token, result, namespaceConfig.getReadObjectAction());
188 }
189 } catch (ObjectNotFoundException e) {
190 }
191
192 // If the attempt to load the uri failed, it means there is at least
193 // one link in the uri (or that the uri doe'sn't have any associated
194 // object).
195 if (result == null) {
196
197 String resolvedUri = uri.toString();
198
199 // 1 - Tokemization of the Uri
200 UriTokenizer uriTokenizer = new UriTokenizer(token, uri.getNamespace(),
201 resolvedUri);
202
203 // 2 - For each element of the Uri
204 Uri courUri = null;
205 ObjectNode courObject = null;
206 while (uriTokenizer.hasMoreElements()) {
207
208 // 3 - Load object's class from the uri. If the object
209 // does not exist, a DataException is thrown.
210 courUri = uriTokenizer.nextUri();
211 courObject = courUri.getStore()
212 .retrieveObject(courUri);
213
214 // We check to see if the credentials gives access to
215 //the current object
216 securityHelper.checkCredentials
217 (token, courObject, namespaceConfig.getReadObjectAction());
218
219 // 4 - Test if object is a link, ie if it is an instance
220 // of LinkNode or one of its subclasses
221 if (((translateLastUriElement)
222 && (courObject instanceof LinkNode)) ||
223 ((!translateLastUriElement)
224 && (uriTokenizer.hasMoreElements())
225 && (courObject instanceof LinkNode))
226 ) {
227
228 // 5 - If the object is a link, we get the uri of
229 // the linked object
230 // Note : courUri still IS the Uri of the link, and so,
231 // in a way courUri is the parent of linkedUri.
232 Uri linkedUri = namespace
233 .getUri(token, ((LinkNode) courObject).getLinkedUri());
234
235 // 6 - We replace the courUri scope in the original uri
236 String courStrUri = courUri.toString();
237 resolvedUri = linkedUri.toString()
238 + resolvedUri.substring(courStrUri.length());
239
240 // 7 - We tokenize again the uri
241 uriTokenizer = new UriTokenizer(token, uri.getNamespace(),
242 resolvedUri);
243
244 // 8 - We parse it till we get back to the point
245 // where we stopped
246 boolean isUriFound = false;
247 while ((!isUriFound) && (uriTokenizer.hasMoreElements())) {
248 if (linkedUri.equals(uriTokenizer.nextUri())) {
249 isUriFound = true;
250 }
251 }
252 if (!isUriFound) {
253 throw new LinkedObjectNotFoundException(courUri,
254 resolvedUri);
255 }
256
257 }
258
259 // 9 - We continue to go down in the Uri tree
260 }
261
262 // 10 - We return the last object which has been found
263
264 result = courObject;
265 }
266
267 return result;
268
269 }
270
271
272 public void create(SlideToken token, ObjectNode object,
273 String strUri)
274 throws ServiceAccessException, ObjectAlreadyExistsException,
275 ObjectNotFoundException, LinkedObjectNotFoundException,
276 AccessDeniedException, ObjectLockedException, VetoException {
277
278 // Fire event
279 if ( StructureEvent.CREATE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(StructureEvent.CREATE, new StructureEvent(this, token, namespace, strUri));
280
281 // Checking roles
282 Enumeration roles = securityHelper.getRoles(object);
283 while (roles.hasMoreElements()) {
284 if (!securityHelper.hasRole(token, (String)roles.nextElement())) {
285 // Allow only the namespace admin to create roles
286 // he doesn't have
287 Uri rootUri = namespace.getUri(token, "/");
288 ObjectNode rootObject =
289 rootUri.getStore().retrieveObject(rootUri);
290 securityHelper.checkCredentials
291 (token, rootObject,
292 namespaceConfig.getGrantPermissionAction());
293 break;
294 }
295 }
296
297 String resolvedUri = strUri;
298
299 // 1 - Tokenization of the Uri
300 UriTokenizer uriTokenizer = new UriTokenizer(token, namespace, resolvedUri);
301
302 // 2 - For each element of the Uri
303 Uri courUri = null;
304 ObjectNode courObject = null;
305 ObjectNode parentObject = null;
306
307 boolean alreadyExists = false;
308
309 while (uriTokenizer.hasMoreElements()) {
310
311 parentObject = courObject;
312
313 // 3 - Load object's class from the uri. If the object does
314 // not exist, a DataException is thrown.
315 courUri = uriTokenizer.nextUri();
316 try {
317 courObject = courUri.getStore()
318 .retrieveObject(courUri);
319 securityHelper
320 .checkCredentials(token, courObject,
321 namespaceConfig.getReadObjectAction());
322 if (!uriTokenizer.hasMoreElements()) {
323 // The object already exists
324 alreadyExists = true;
325 }
326 } catch (ObjectNotFoundException e) {
327 // Load failed, probably because object was not found
328 // We try to create a new one.
329 // We have to test if the uri is the last in the list,
330 // we must create the requested element.
331 // By default, we create a SubjectNode.
332 ObjectNode newObject = null;
333 if (uriTokenizer.hasMoreElements()) {
334 throw new ObjectNotFoundException(courUri);
335 } else {
336 newObject = object;
337 }
338 if (parentObject != null) {
339
340 // lock exclusively before anyone can get a read lock
341 // do not lock in external transaction because this might lead to distributed deadlocks
342 // between Slide and store
343 if (!token.isExternalTransaction()) {
344 namespace.getUri(token, parentObject.getUri()).getStore().exclusiveTransientLock(
345 parentObject.getUri().toString());
346 }
347
348 securityHelper
349 .checkCredentials(token, courObject, namespaceConfig
350 .getBindMemberAction());
351
352 // Now creating the new object
353 newObject.setUri(courUri.toString());
354 courUri.getStore().createObject(courUri, newObject);
355
356 // re-read to obtain UURI
357 // newObject = courUri.getStore().retrieveObject(courUri);
358
359 // re-read the parent taking the forceEnlistment flag into account
360 Uri parentUri = namespace.getUri(token, parentObject.getUri());
361 parentObject = parentUri.getStore().retrieveObject(parentUri);
362 // Add the newly created object to its parent's
363 // children list
364 ObjectNode oldChild = null;
365 // we can check the parentUri, it's in the same store as newObject
366 if (Configuration.useBinding(parentUri.getStore())) {
367 String bindingName = newObject.getPath().lastSegment();
368 if (parentObject.hasBinding(bindingName)) {
369 oldChild = retrieve(token, parentObject.getUri()+"/"+bindingName, false);
370 parentObject.removeChild(oldChild);
371 store(token, oldChild);
372 }
373 }
374 lockHelper.checkLock
375 (token, parentObject, namespaceConfig.getCreateObjectAction());
376 parentObject.addChild(newObject);
377 //namespace.getUri(token, parentObject.getUri())
378 //.getDataSource().storeObject(parentObject, false);
379 store(token, parentObject, true);
380 store(token, newObject);
381
382 } else {
383 throw new ObjectNotFoundException(courUri);
384 }
385 courObject = newObject;
386 }
387
388 // 4 - Test if object is a link, ie if it is an instance of
389 // LinkNode or one of its subclasses
390 if ((uriTokenizer.hasMoreElements())
391 && (courObject instanceof LinkNode)) {
392
393 // 5 - If the object is a link, we get the uri of the
394 // linked object
395 // Note : courUri still IS the Uri of the link, and so,
396 // in a way courUri is the parent of linkedUri.
397 Uri linkedUri = namespace
398 .getUri(token, ((LinkNode) courObject).getLinkedUri());
399
400 // 6 - We replace the courUri scope in the original uri
401 String courStrUri = courUri.toString();
402 resolvedUri = linkedUri.toString()
403 + resolvedUri.substring(courStrUri.length());
404
405 // 7 - We tokenize again the uri
406 uriTokenizer = new UriTokenizer(token, namespace, resolvedUri);
407
408 // 8 - We parse it till we get back to the point
409 // where we stopped
410 boolean isUriFound = false;
411 while ((!isUriFound) && (uriTokenizer.hasMoreElements())) {
412 if (linkedUri.equals(uriTokenizer.nextUri())) {
413 isUriFound = true;
414 }
415 }
416 if (!isUriFound) {
417 throw new LinkedObjectNotFoundException
418 (courUri, resolvedUri);
419 }
420
421 }
422
423 // 9 - We continue to go down in the Uri tree
424 }
425
426 if (alreadyExists) {
427 if (courUri.isStoreRoot()) {
428 // if the object already exists map it anyway into
429 // the node hierarchy, to prevent loose of nodes
430 // during start up
431 if (parentObject != null && !parentObject.hasChild(courObject)) {
432 parentObject.addChild(courObject);
433 store(token, parentObject, true);
434 }
435 }
436 throw new ObjectAlreadyExistsException(strUri);
437 }
438 }
439
440 public void createLink(SlideToken token, LinkNode link,
441 String linkUri, ObjectNode linkedObject)
442 throws ServiceAccessException, ObjectAlreadyExistsException,
443 ObjectNotFoundException, LinkedObjectNotFoundException,
444 AccessDeniedException, ObjectLockedException, VetoException {
445 link.setLinkedUri(linkedObject.getUri());
446
447 // Fire event
448 if ( StructureEvent.CREATE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(StructureEvent.CREATE_LINK, new StructureEvent(this, token, link, linkUri));
449
450 create(token, link, linkUri);
451 }
452
453
454 public void store(SlideToken token, ObjectNode object)
455 throws ServiceAccessException, ObjectNotFoundException,
456 AccessDeniedException, LinkedObjectNotFoundException, VetoException {
457
458 store(token, object, false);
459 }
460
461
462 protected void store(SlideToken token, ObjectNode object, boolean setModificationDate)
463 throws ServiceAccessException, ObjectNotFoundException,
464 AccessDeniedException, LinkedObjectNotFoundException, VetoException {
465
466 // Fire event
467 if ( StructureEvent.STORE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(StructureEvent.STORE, new StructureEvent(this, token, namespace, object));
468
469 // Checking roles
470 Enumeration roles = securityHelper.getRoles(object);
471 while (roles.hasMoreElements()) {
472 if (!securityHelper.hasRole(token, (String)roles.nextElement())) {
473 // Allow only the namespace admin to create roles
474 // he doesn't have
475 Uri rootUri = namespace.getUri(token, "/");
476 ObjectNode rootObject =
477 rootUri.getStore().retrieveObject(rootUri);
478 securityHelper.checkCredentials
479 (token, rootObject,
480 namespaceConfig.getGrantPermissionAction());
481 break;
482 }
483 }
484
485 // working on realObject, we will lose changes immediatly done before call of store
486 // i observerd this with some BIND testcases
487 //ObjectNode realObject = retrieve(token, object.getUri(), false);
488 securityHelper
489 .checkCredentials(token, object,
490 namespaceConfig.getCreateObjectAction());
491 Uri uri = namespace.getUri(token, object.getUri());
492 Store store = uri.getStore();
493 store.storeObject(uri, object);
494
495 if (setModificationDate) {
496 try {
497 NodeRevisionDescriptor revisionDescriptor = store.retrieveRevisionDescriptor(uri, new NodeRevisionNumber());
498 revisionDescriptor.setModificationDate(new Date());
499 revisionDescriptor.setModificationUser(
500 securityHelper.getPrincipal(token).getPath().lastSegment());
501 store.storeRevisionDescriptor(uri, revisionDescriptor );
502 }
503 catch (RevisionDescriptorNotFoundException e) {
504 // ignore silently
505 }
506 }
507 }
508
509
510 /**
511 * Method remove
512 *
513 * @param token a SlideToken
514 * @param object an ObjectNode
515 *
516 * @throws ServiceAccessException
517 * @throws ObjectNotFoundException
518 * @throws ObjectHasChildrenException
519 * @throws AccessDeniedException
520 * @throws LinkedObjectNotFoundException
521 * @throws ObjectLockedException
522 *
523 */
524 public void remove(SlideToken token, ObjectNode object)
525 throws ServiceAccessException, ObjectNotFoundException,
526 ObjectHasChildrenException, AccessDeniedException,
527 LinkedObjectNotFoundException, ObjectLockedException, VetoException {
528
529 ObjectNode nodeToDelete = retrieve(token, object.getUri(), false);
530 Uri uri = namespace.getUri(token, nodeToDelete.getUri());
531
532 // Fire event
533 if ( StructureEvent.REMOVE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(StructureEvent.REMOVE, new StructureEvent(this, token, object, uri.toString()));
534
535 if (!object.getUri().equals("/")) {
536 Uri curUri = namespace.getUri(token, nodeToDelete.getUri());
537 Uri parentUri = curUri.getParentUri();
538
539 // lock exclusively before anyone can get a read lock
540 // do not lock in external transaction because this might lead to distributed deadlocks
541 // between Slide and store
542 if (!token.isExternalTransaction()) {
543 parentUri.getStore().exclusiveTransientLock(parentUri.toString());
544 }
545
546 ObjectNode parentNode = parentUri.getStore().retrieveObject(parentUri);
547
548 securityHelper.checkCredentials
549 (token, nodeToDelete, namespaceConfig.getRemoveObjectAction());
550 securityHelper.checkCredentials
551 (token, parentNode, namespaceConfig.getUnbindMemberAction());
552 lockHelper.checkLock
553 (token, nodeToDelete, namespaceConfig.getRemoveObjectAction());
554 lockHelper.checkLock
555 (token, parentNode, namespaceConfig.getUnbindMemberAction());
556
557 parentNode.removeChild(nodeToDelete);
558 store(token, parentNode, true);
559
560 if (Configuration.useBinding(curUri.getStore()) && nodeToDelete.numberOfParentBindings() > 0) {
561 store(token, nodeToDelete);
562 }
563 else {
564 Enumeration enum = nodeToDelete.enumerateChildren();
565 if (enum.hasMoreElements()) {
566 throw new ObjectHasChildrenException(uri);
567 }
568 uri.getStore().removeObject(uri, nodeToDelete);
569 }
570 }
571 }
572
573
574 /**
575 * Modifies the collection identified by <b>collectionNode</b>, by adding a new binding
576 * from the specified segment to the resource identified by <b>sourceNode</b>.
577 *
578 * @param token a SlideToken
579 * @param collectionNode an ObjectNode
580 * @param segment a String
581 * @param sourceNode an ObjectNode
582 *
583 * @throws ServiceAccessException
584 * @throws ObjectNotFoundException
585 * @throws AccessDeniedException
586 * @throws LinkedObjectNotFoundException
587 * @throws ObjectLockedException
588 *
589 */
590 public void addBinding(SlideToken token, ObjectNode collectionNode, String segment, ObjectNode sourceNode) throws ServiceAccessException, ObjectNotFoundException, AccessDeniedException, LinkedObjectNotFoundException, ObjectLockedException, CrossServerBindingException, VetoException {
591 if (Configuration.useBinding(namespace.getUri(token, collectionNode.getUri()).getStore())) {
592 collectionNode = retrieve(token, collectionNode.getUri(), false);
593 sourceNode = retrieve(token, sourceNode.getUri(), false);
594 Uri collectionUri = namespace.getUri(token, collectionNode.getUri());
595 // Uri sourceUri = namespace.getUri(token, sourceNode.getUri());
596
597 // Fire event
598 if ( StructureEvent.ADD_BINDING.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(StructureEvent.ADD_BINDING, new StructureEvent(this, token, sourceNode, collectionUri.toString()));
599
600 // if (collectionUri.getStore() != sourceUri.getStore()) {
601 // throw new CrossServerBindingException(collectionNode.getUri(), sourceNode.getUri());
602 // }
603
604 lockHelper.checkLock
605 (token, collectionNode, namespaceConfig.getCreateObjectAction());
606
607 ObjectNode oldChild = null;
608 if (collectionNode.hasBinding(segment)) {
609 oldChild = retrieve(token, collectionNode.getUri()+"/"+segment, false);
610 lockHelper.checkLock
611 (token, oldChild, namespaceConfig.getCreateObjectAction());
612 collectionNode.removeChild(oldChild);
613 store( token, oldChild );
614 }
615 collectionNode.addBinding( segment, sourceNode );
616
617 store( token, collectionNode, true );
618 store( token, sourceNode );
619 }
620 }
621
622
623 /**
624 * Modifies the collection identified by <b>collectionNode</b>, by removing the binding
625 * for the specified segment.
626 *
627 * @param token a SlideToken
628 * @param collectionNode an ObjectNode
629 * @param segment a String
630 *
631 * @throws ServiceAccessException
632 * @throws ObjectNotFoundException
633 * @throws AccessDeniedException
634 * @throws LinkedObjectNotFoundException
635 * @throws ObjectLockedException
636 *
637 */
638 public void removeBinding(SlideToken token, ObjectNode collectionNode, String segment) throws ServiceAccessException, ObjectNotFoundException, AccessDeniedException, LinkedObjectNotFoundException, ObjectLockedException, VetoException {
639 if (Configuration.useBinding(namespace.getUri(token, collectionNode.getUri()).getStore())) {
640 collectionNode = retrieve(token, collectionNode.getUri(), false);
641 ObjectNode childNode = retrieve(token, collectionNode.getUri()+"/"+segment, false);
642
643 // Fire event
644 if ( StructureEvent.REMOVE_BINDING.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(StructureEvent.REMOVE_BINDING, new StructureEvent(this, token, childNode, collectionNode.getUri()));
645
646 lockHelper.checkLock
647 (token, collectionNode, namespaceConfig.getCreateObjectAction());
648 lockHelper.checkLock
649 (token, childNode, namespaceConfig.getCreateObjectAction());
650
651 collectionNode.removeChild( childNode );
652
653 store( token, childNode );
654 store( token, collectionNode, true );
655 }
656 }
657
658
659 /**
660 * Return all parents of this object node. If pathOnly=true, only parents
661 * on the path of the specified ObjectNode are returned, all parents (binding!)
662 * otherwise. If storeOnly=true, only parents within the scope of the store
663 * in charge of the specified ObjectNode are returned, parents up to the root
664 * ObjectNode (uri="/") otherwise.
665 *
666 * @param token a SlideToken
667 * @param object an ObjectNode
668 * @param pathOnly if true, only parents on the path of the specified
669 * ObjectNode are returned, all parents (binding!)
670 * otherwise
671 * @param storeOnly if true, only parents within the scope of the store
672 * in charge of the specified ObjectNode are returned,
673 * parents up to the root ObjectNode (uri="/") otherwise
674 * @param includeSelf if true, the ObjectNode specified by object is included,
675 * otherwise, it is excluded
676 *
677 * @return a List of ObjectNode instances
678 *
679 * @throws ServiceAccessException
680 * @throws ObjectNotFoundException
681 * @throws LinkedObjectNotFoundException
682 * @throws AccessDeniedException
683 *
684 */
685 public List getParents(SlideToken token, ObjectNode object, boolean pathOnly, boolean storeOnly, boolean includeSelf) throws ServiceAccessException, ObjectNotFoundException, LinkedObjectNotFoundException, AccessDeniedException, VetoException {
686 List result = new ArrayList();
687
688 if (pathOnly) {
689 String[] uriTokens = object.getPath().tokens();
690 UriPath path = new UriPath("/");
691 Uri currentUri = namespace.getUri(token, path.toString());
692 Uri objectUri = namespace.getUri(token, object.getUri());
693 if (!storeOnly || currentUri.getStore() == objectUri.getStore()) {
694 result.add( retrieve(token, path.toString()) );
695 }
696
697 for (int i = 0; i < uriTokens.length; i++) {
698 path = path.child( uriTokens[i] );
699 currentUri = namespace.getUri(token, path.toString());
700 if (i == uriTokens.length - 1 && !includeSelf) {
701 break;
702 }
703 if (!storeOnly || currentUri.getStore() == objectUri.getStore()) {
704 result.add( retrieve(token, path.toString()) );
705 }
706 }
707 }
708 else {
709 // TODO
710 }
711
712 return result;
713 }
714 }
715