KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > info > magnolia > cms > core > Content


1 /**
2  *
3  * Magnolia and its source-code is licensed under the LGPL.
4  * You may copy, adapt, and redistribute this file for commercial or non-commercial use.
5  * When copying, adapting, or redistributing this document in keeping with the guidelines above,
6  * you are required to provide proper attribution to obinary.
7  * If you reproduce or distribute the document without making any substantive modifications to its content,
8  * please use the following attribution line:
9  *
10  * Copyright 1993-2005 obinary Ltd. (http://www.obinary.com) All rights reserved.
11  *
12  */

13 package info.magnolia.cms.core;
14
15 import info.magnolia.cms.beans.config.Server;
16 import info.magnolia.cms.security.AccessDeniedException;
17 import info.magnolia.cms.security.AccessManager;
18 import info.magnolia.cms.security.Authenticator;
19 import info.magnolia.cms.security.Permission;
20
21 import java.util.ArrayList JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.Comparator JavaDoc;
25 import java.util.Date JavaDoc;
26 import java.util.List JavaDoc;
27
28 import javax.jcr.Item;
29 import javax.jcr.Node;
30 import javax.jcr.NodeIterator;
31 import javax.jcr.PathNotFoundException;
32 import javax.jcr.Property;
33 import javax.jcr.PropertyIterator;
34 import javax.jcr.RepositoryException;
35 import javax.jcr.UnsupportedRepositoryOperationException;
36 import javax.jcr.Value;
37 import javax.jcr.lock.Lock;
38 import javax.jcr.lock.LockException;
39 import javax.jcr.nodetype.NodeType;
40 import javax.jcr.version.Version;
41 import javax.jcr.version.VersionException;
42 import javax.jcr.version.VersionHistory;
43 import javax.jcr.version.VersionIterator;
44 import javax.servlet.http.HttpServletRequest JavaDoc;
45
46 import org.apache.commons.lang.StringUtils;
47 import org.apache.log4j.Logger;
48 import org.doomdark.uuid.UUIDGenerator;
49
50
51 /**
52  * @author Sameer Charles
53  * @version $Revision $ ($Author $)
54  */

55 public class Content extends ContentHandler implements Cloneable JavaDoc {
56
57     /**
58      * Logger.
59      */

60     private static Logger log = Logger.getLogger(Content.class);
61
62     /**
63      * UUID property added on creation of object
64      */

65     private static final String JavaDoc PROPERTY_UUID = "mgnl:uuid"; //$NON-NLS-1$
66

67     /**
68      * Wrapped jcr node.
69      */

70     protected Node node;
71
72     /**
73      * Path for the jcr node.
74      */

75     private String JavaDoc path;
76
77     /**
78      * root node.
79      */

80     private Node rootNode;
81
82     /**
83      * node metadata.
84      */

85     private MetaData metaData;
86
87     /**
88      * Empty constructor. Should NEVER be used for standard use, test only.
89      */

90     protected Content() {
91     }
92
93     /**
94      * Constructor to get existing node.
95      * @param rootNode node to start with
96      * @param path absolute (primary) path to this <code>Node</code>
97      * @param manager AccessManager instance
98      * @throws PathNotFoundException if the node at <code>path</code> does not exist
99      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
100      * operation
101      * @throws RepositoryException if an error occurs
102      */

103     public Content(Node rootNode, String JavaDoc path, AccessManager manager)
104         throws PathNotFoundException,
105         RepositoryException,
106         AccessDeniedException {
107         Access.isGranted(manager, Path.getAbsolutePath(rootNode.getPath(), path), Permission.READ);
108         this.setPath(path);
109         this.setRootNode(rootNode);
110         this.setNode(this.rootNode.getNode(this.path));
111         this.setAccessManager(manager);
112     }
113
114     /**
115      * Constructor to get existing node.
116      * @param elem initialized node object
117      * @param manager AccessManager instance
118      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
119      * operation
120      * @throws RepositoryException if an error occurs
121      */

122     public Content(Item elem, AccessManager manager) throws RepositoryException, AccessDeniedException {
123         Access.isGranted(manager, Path.getAbsolutePath(elem.getPath()), Permission.READ);
124         this.setNode((Node) elem);
125         this.setPath(this.getHandle());
126         this.setAccessManager(manager);
127     }
128
129     /**
130      * creates contentNode of type <b>contentType </b> contentType must be defined in item type definition of magnolia
131      * as well as JCR implementation
132      * @param rootNode node to start with
133      * @param path absolute (primary) path to this <code>Node</code>
134      * @param contentType JCR node type as configured
135      * @param manager AccessManager instance
136      * @throws PathNotFoundException if the node at <code>path</code> does not exist
137      * @throws RepositoryException if an error occurs
138      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
139      * operation
140      */

141     public Content(Node rootNode, String JavaDoc path, String JavaDoc contentType, AccessManager manager)
142         throws PathNotFoundException,
143         RepositoryException,
144         AccessDeniedException {
145         Access.isGranted(manager, Path.getAbsolutePath(rootNode.getPath(), path), Permission.WRITE);
146         this.setPath(path);
147         this.setRootNode(rootNode);
148         this.node = this.rootNode.addNode(this.path, contentType);
149         this.addUUID();
150         this.setAccessManager(manager);
151         this.addMixin(ItemType.MIX_VERSIONABLE);
152     }
153
154     /**
155      * bit by bit copy of the current object. Warning: this doesn't clone wrapped jcr nodes.
156      * @return Object cloned object
157      */

158     public Object JavaDoc clone() { // don't add throws CloneNotSupportedException! the super class ContentHandler doesn't throw
159
// it anymore, so it will not compile
160
return super.clone();
161     }
162
163     /**
164      * @param node
165      */

166     protected void setNode(Node node) {
167         this.node = node;
168     }
169
170     /**
171      * @param node
172      */

173     protected void setRootNode(Node node) {
174         this.rootNode = node;
175     }
176
177     /**
178      * @param path
179      */

180     protected void setPath(String JavaDoc path) {
181         this.path = path;
182     }
183
184     /**
185      * get ContentNode node of the current node with the specified name
186      * @param path of the node acting as <code>ContentNode</code>
187      * @return ContentNode
188      * @throws PathNotFoundException if the node at <code>path</code> does not exist
189      * @throws RepositoryException if an error occurs
190      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
191      * operation
192      * @deprecated use getContent(String name) instead
193      */

194     public Content getContentNode(String JavaDoc path) throws PathNotFoundException, RepositoryException, AccessDeniedException {
195         Content content = new Content(this.node, path, this.accessManager);
196         return content;
197     }
198
199     /**
200      * create ContentNode node under the current node with the specified name
201      * @param name of the node to be created as <code>ContentNode</code>
202      * @return newly created <node>ContentNode </node>
203      * @throws PathNotFoundException
204      * @throws RepositoryException if an error occurs
205      * @deprecated use createContent(String name, String contentType) instead
206      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
207      * operation
208      */

209     public Content createContentNode(String JavaDoc name) throws PathNotFoundException, RepositoryException,
210         AccessDeniedException {
211         return this.createContent(name, ItemType.CONTENTNODE);
212     }
213
214     /**
215      * get Content node of the current node with the specified name
216      * @param name of the node acting as <code>Content</code>
217      * @return <node>Content </node>
218      * @throws PathNotFoundException
219      * @throws RepositoryException if an error occurs
220      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
221      * operation
222      */

223     public Content getContent(String JavaDoc name) throws PathNotFoundException, RepositoryException, AccessDeniedException {
224         return (new Content(this.node, name, this.accessManager));
225     }
226
227     /**
228      * create Content node under the current node with the specified name
229      * @param name of the node to be created as <code>Content</code>
230      * @return newly created <node>Content </node>
231      * @throws PathNotFoundException
232      * @throws RepositoryException if an error occurs
233      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
234      * operation
235      */

236     public Content createContent(String JavaDoc name) throws PathNotFoundException, RepositoryException, AccessDeniedException {
237         return this.createContent(name, ItemType.CONTENT);
238     }
239
240     /**
241      * create Content node under the current node with the specified name
242      * @param name of the node to be created as <code>Content</code>
243      * @param contentType JCR node type as configured
244      * @return newly created <node>Content </node>
245      * @throws PathNotFoundException
246      * @throws RepositoryException if an error occurs
247      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
248      * operation
249      */

250     public Content createContent(String JavaDoc name, String JavaDoc contentType) throws PathNotFoundException, RepositoryException,
251         AccessDeniedException {
252         Content content = (new Content(this.node, name, contentType, this.accessManager));
253         MetaData metaData = content.getMetaData();
254         metaData.setCreationDate();
255         return content;
256     }
257
258     /**
259      * Create Content node under the current node with the specified name.
260      * @param name of the node to be created as <code>Content</code>
261      * @param contentType ItemType
262      * @return newly created <node>Content </node>
263      * @throws PathNotFoundException
264      * @throws RepositoryException if an error occurs
265      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
266      * operation
267      */

268     public Content createContent(String JavaDoc name, ItemType contentType) throws PathNotFoundException, RepositoryException,
269         AccessDeniedException {
270         Content content = (new Content(this.node, name, contentType.getSystemName(), this.accessManager));
271         MetaData metaData = content.getMetaData();
272         metaData.setCreationDate();
273         return content;
274     }
275
276     /**
277      * @return String, template name
278      */

279     public String JavaDoc getTemplate() {
280         return this.getMetaData().getTemplate();
281     }
282
283     /**
284      * @return String, title
285      */

286     public String JavaDoc getTitle() {
287         return this.getNodeData("title").getString(); //$NON-NLS-1$
288
}
289
290     /**
291      * get meta data of the current node
292      * @return MetaData meta information of the content <code>Node</code>
293      */

294     public MetaData getMetaData() {
295         if (this.metaData == null) {
296             this.metaData = new MetaData(this.node, this.accessManager);
297         }
298         return this.metaData;
299     }
300
301     /**
302      * get meta data of the current node
303      * @return MetaData meta information of the context under the content <code>Node</code>
304      */

305     public MetaData getMetaData(String JavaDoc context) {
306         return new MetaData(this.node, context, this.accessManager);
307     }
308
309     /**
310      * get top level NodeData
311      * @return NodeData requested <code>NodeData</code> object
312      */

313
314     public NodeData getNodeData(String JavaDoc name) {
315         return getNodeData(name, false);
316     }
317
318     /**
319      * @param name
320      * @param create
321      * @return
322      */

323     public NodeData getNodeData(String JavaDoc name, boolean create) {
324         try {
325             return (new NodeData(this.node, name, this.accessManager));
326         }
327         catch (PathNotFoundException e) {
328             if (create) {
329                 try {
330                     return this.createNodeData(name);
331                 }
332                 catch (Exception JavaDoc e1) {
333                     log.error("can't create property [" + name + "]"); //$NON-NLS-1$ //$NON-NLS-2$
334
}
335             }
336             if (log.isDebugEnabled()) {
337                 String JavaDoc nodepath = null;
338                 try {
339                     nodepath = this.node.getPath();
340                 }
341                 catch (RepositoryException e1) {
342                     // ignore, debug only
343
}
344                 if (log.isDebugEnabled()) {
345                     log.debug("Path not found for property [" + name + "] in node " + nodepath); //$NON-NLS-1$ //$NON-NLS-2$
346
}
347             }
348
349             return (new NodeData());
350         }
351         catch (RepositoryException re) {
352             String JavaDoc nodepath = null;
353             try {
354                 nodepath = this.node.getPath();
355             }
356             catch (RepositoryException e1) {
357                 // ignore, debug only
358
}
359             log.warn("Repository exception while trying to read property [" + name + "] for node " + nodepath, re); //$NON-NLS-1$ //$NON-NLS-2$
360
return (new NodeData());
361         }
362     }
363
364     /**
365      * get node name
366      * @return String name of the current <code>Node</code>
367      */

368     public String JavaDoc getName() {
369         try {
370             return this.node.getName();
371         }
372         catch (RepositoryException e) {
373             log.error(e.getMessage(), e);
374         }
375         return StringUtils.EMPTY;
376     }
377
378     /**
379      * create top level NodeData object
380      * @param name to be created
381      * @return NodeData requested <code>NodeData</code> object
382      * @throws PathNotFoundException
383      * @throws RepositoryException if an error occurs
384      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
385      * operation
386      */

387     public NodeData createNodeData(String JavaDoc name) throws PathNotFoundException, RepositoryException,
388         AccessDeniedException {
389         return (new NodeData(this.node, name, true, this.accessManager));
390     }
391
392     /**
393      * Create NodeData with the given value and type.
394      * @param name to be created
395      * @param value to be set initially
396      * @return NodeData requested <code>NodeData</code> object
397      * @throws PathNotFoundException
398      * @throws RepositoryException if an error occurs
399      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
400      * operation
401      */

402     public NodeData createNodeData(String JavaDoc name, Value value) throws PathNotFoundException, RepositoryException,
403         AccessDeniedException {
404         return (new NodeData(this.node, name, value, this.accessManager));
405     }
406
407     /**
408      * Create NodeData with the given value and type.
409      * @param name to be created
410      * @param value to be set initially
411      * @param type propertyType
412      * @return NodeData requested <code>NodeData</code> object
413      * @throws PathNotFoundException
414      * @throws RepositoryException if an error occurs
415      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
416      * operation
417      */

418     public NodeData createNodeData(String JavaDoc name, Value value, int type) throws PathNotFoundException,
419         RepositoryException, AccessDeniedException {
420         return createNodeData(name, value);
421     }
422
423     /**
424      * delete NodeData with the specified name
425      * @throws PathNotFoundException
426      * @throws RepositoryException if an error occurs
427      */

428     public void deleteNodeData(String JavaDoc name) throws PathNotFoundException, RepositoryException {
429         this.node.getProperty(name).remove();
430     }
431
432     /**
433      * you could call this method anytime to update working page properties - Modification date & Author ID
434      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
435      * operation
436      * @throws RepositoryException if an error occurs
437      */

438     public void updateMetaData(HttpServletRequest JavaDoc request) throws RepositoryException, AccessDeniedException {
439         MetaData md = this.getMetaData();
440         md.setModificationDate();
441         md.setAuthorId(Authenticator.getUserId(request));
442         md = null;
443     }
444
445     /**
446      * gets a Collection containing all child nodes of the same NodeType as "this" object.
447      * @return Collection of content nodes
448      */

449     public Collection JavaDoc getChildren() {
450         String JavaDoc type = null;
451
452         try {
453             type = this.getNodeType().getName();
454         }
455         catch (RepositoryException re) {
456             log.error(re.getMessage());
457             log.debug(re);
458         }
459         // @todo workaround
460
// fix all getChildren calls from the root node
461
if ("rep:root".equalsIgnoreCase(type)) { //$NON-NLS-1$
462
type = ItemType.CONTENT.getSystemName();
463         }
464         // --------------------------------------------------
465
return this.getChildren(StringUtils.defaultString(type));
466     }
467
468     /**
469      * Get collection of specified content type.
470      * @param contentType JCR node type as configured
471      * @return Collection of content nodes
472      */

473     public Collection JavaDoc getChildren(String JavaDoc contentType) {
474         return this.getChildren(contentType, ContentHandler.IGNORE_SORT);
475     }
476
477     /**
478      * Get collection of specified content type.
479      * @param contentType ItemType
480      * @return Collection of content nodes
481      */

482     public Collection JavaDoc getChildren(ItemType contentType) {
483         return this.getChildren(contentType.getSystemName(), ContentHandler.IGNORE_SORT);
484     }
485
486     /**
487      * Get collection of specified content type.
488      * @param contentType JCR node type as configured
489      * @param namePattern
490      * @return Collection of content nodes
491      */

492     public Collection JavaDoc getChildren(String JavaDoc contentType, String JavaDoc namePattern) {
493         return this.getChildren(contentType, namePattern, ContentHandler.IGNORE_SORT);
494     }
495
496     /**
497      * Get collection of specified content type
498      * @param contentType JCR node type as configured
499      * @param sortCriteria which can be either ContentHandler.SORT_BY_SEQUENCE , ContentHandler.SORT_BY_DATE or
500      * ContentHandler.SORT_BY_NAME
501      * @return Collection of content nodes
502      */

503     public Collection JavaDoc getChildren(String JavaDoc contentType, int sortCriteria) {
504         return this.getChildren(contentType, "*", sortCriteria); //$NON-NLS-1$
505
}
506
507     /**
508      * Get collection of specified content type
509      * @param contentType ItemType
510      * @param sortCriteria which can be either ContentHandler.SORT_BY_SEQUENCE , ContentHandler.SORT_BY_DATE or
511      * ContentHandler.SORT_BY_NAME
512      * @return Collection of content nodes
513      */

514     public Collection JavaDoc getChildren(ItemType contentType, int sortCriteria) {
515         return this.getChildren(contentType.getSystemName(), sortCriteria);
516     }
517
518     /**
519      * Get collection of specified content type.
520      * @param contentType JCR node type as configured
521      * @param namePattern
522      * @param sortCriteria which can be either ContentHandler.SORT_BY_SEQUENCE , ContentHandler.SORT_BY_DATE or
523      * ContentHandler.SORT_BY_NAME
524      * @return Collection of content nodes
525      */

526     public Collection JavaDoc getChildren(String JavaDoc contentType, String JavaDoc namePattern, int sortCriteria) {
527         Collection JavaDoc children = new ArrayList JavaDoc();
528         try {
529             children = this.getChildContent(contentType, namePattern);
530             children = sort(children, sortCriteria);
531         }
532         catch (RepositoryException e) {
533             log.error(e.getMessage(), e);
534         }
535         return children;
536     }
537
538     /**
539      * @param collection Collection of content nodes
540      * @param sortCriteria
541      * @return
542      */

543     private Collection JavaDoc sort(Collection JavaDoc collection, int sortCriteria) {
544         if (sortCriteria == ContentHandler.SORT_BY_DATE) {
545             return sortByDate(collection);
546         }
547         else if (sortCriteria == ContentHandler.SORT_BY_SEQUENCE) {
548             return sortBySequence(collection);
549         }
550         return collection;
551     }
552
553     /**
554      * @param contentType JCR node type as configured
555      * @param namePattern
556      * @return
557      * @throws RepositoryException if an error occurs
558      */

559     private Collection JavaDoc getChildContent(String JavaDoc contentType, String JavaDoc namePattern) throws RepositoryException {
560         Collection JavaDoc children = new ArrayList JavaDoc();
561         NodeIterator nodeIterator = this.node.getNodes(namePattern);
562         while (nodeIterator.hasNext()) {
563             Node subNode = (Node) nodeIterator.next();
564             try {
565                 if (subNode.isNodeType(contentType)) {
566                     children.add(new Content(subNode, this.accessManager));
567                 }
568             }
569             catch (PathNotFoundException e) {
570                 log.error(e);
571             }
572             catch (AccessDeniedException e) {
573                 // ignore, simply wont add content in a list
574
}
575         }
576         return children;
577     }
578
579     /**
580      * Gets all properties bind in NodeData object excluding JCR system properties
581      */

582     public Collection JavaDoc getNodeDataCollection() {
583         Collection JavaDoc children = new ArrayList JavaDoc();
584         try {
585             PropertyIterator propertyIterator = this.node.getProperties();
586             while (propertyIterator.hasNext()) {
587                 Property property = (Property) propertyIterator.next();
588                 try {
589                     if (!property.getName().startsWith("jcr:") && !property.getName().startsWith("mgnl:")) { //$NON-NLS-1$ //$NON-NLS-2$
590
children.add(new NodeData(property, this.accessManager));
591                     }
592                 }
593                 catch (PathNotFoundException e) {
594                     log.error(e);
595                 }
596                 catch (AccessDeniedException e) {
597                     // ignore, simply wont add content in a list
598
}
599             }
600         }
601         catch (RepositoryException re) {
602             log.error(re);
603         }
604         return children;
605     }
606
607     /**
608      * Gets all properties bind in NodeData object which qualify the given namePattern
609      * @param namePattern
610      */

611     public Collection JavaDoc getNodeDataCollection(String JavaDoc namePattern) {
612         Collection JavaDoc children = new ArrayList JavaDoc();
613         try {
614             PropertyIterator propertyIterator = this.node.getProperties(namePattern);
615             if (propertyIterator == null) {
616                 return children;
617             }
618             while (propertyIterator.hasNext()) {
619                 Property property = (Property) propertyIterator.next();
620                 try {
621                     children.add(new NodeData(property, this.accessManager));
622                 }
623                 catch (PathNotFoundException e) {
624                     log.error(e);
625                 }
626                 catch (AccessDeniedException e) {
627                     // ignore, simply wont add content in a list
628
}
629             }
630         }
631         catch (RepositoryException re) {
632             log.error(re);
633         }
634         return children;
635     }
636
637     /**
638      * @return Boolean, if sub node(s) exists
639      */

640     public boolean hasChildren() {
641         return (this.getChildren().size() > 0);
642     }
643
644     /**
645      * @param contentType JCR node type as configured
646      * @return Boolean, if sub <code>collectionType</code> exists
647      */

648     public boolean hasChildren(String JavaDoc contentType) {
649         return (this.getChildren(contentType).size() > 0);
650     }
651
652     /**
653      * @param name
654      * @return
655      * @throws RepositoryException if an error occurs
656      */

657     public boolean hasContent(String JavaDoc name) throws RepositoryException {
658         return this.node.hasNode(name);
659     }
660
661     /**
662      * @param name
663      * @return
664      * @throws RepositoryException if an error occurs
665      */

666     public boolean hasNodeData(String JavaDoc name) throws RepositoryException {
667         return this.node.hasProperty(name);
668     }
669
670     /**
671      * Gets a Collection containing all child nodes at the current level+1 level
672      * @param contentCollection collection of content nodes
673      * @return sorted collection
674      */

675     public Collection JavaDoc sortByDate(Collection JavaDoc contentCollection) {
676         try {
677             if (contentCollection == null) {
678                 return contentCollection;
679             }
680             Collections.sort((List JavaDoc) contentCollection, new Comparator JavaDoc() {
681
682                 public int compare(Object JavaDoc o1, Object JavaDoc o2) {
683                     Date JavaDoc date1 = ((Content) o1).getMetaData().getCreationDate().getTime();
684                     Date JavaDoc date2 = ((Content) o2).getMetaData().getCreationDate().getTime();
685                     return date1.compareTo(date2);
686                 }
687             });
688         }
689         catch (Exception JavaDoc e) {
690             log.error(e.getMessage());
691         }
692         return contentCollection;
693     }
694
695     /**
696      * Gets a Collection containing all child nodes at the current level+1 level
697      * @param contentCollection collection of content nodes
698      * @return sorted collection
699      */

700     public Collection JavaDoc sortBySequence(Collection JavaDoc contentCollection) {
701         try {
702             if (contentCollection == null) {
703                 return contentCollection;
704             }
705             Collections.sort((List JavaDoc) contentCollection, new Comparator JavaDoc() {
706
707                 public int compare(Object JavaDoc o0, Object JavaDoc o1) {
708                     try {
709                         long pos0 = (((Content) o0).getMetaData().getSequencePosition());
710                         long pos1 = (((Content) o1).getMetaData().getSequencePosition());
711                         String JavaDoc s0 = "0"; //$NON-NLS-1$
712
String JavaDoc s1 = "0"; //$NON-NLS-1$
713
if (pos0 > pos1) {
714                             s0 = "1"; //$NON-NLS-1$
715
}
716                         else if (pos0 < pos1) {
717                             s1 = "1"; //$NON-NLS-1$
718
}
719                         return s0.compareTo(s1);
720                     }
721                     catch (Exception JavaDoc e) {
722                         return 0;
723                     }
724                 }
725
726             });
727         }
728         catch (Exception JavaDoc e) {
729             log.error(e.getMessage(), e);
730         }
731         return contentCollection;
732     }
733
734     /**
735      * get a handle representing path relative to the content repository
736      * @return String representing path (handle) of the content
737      */

738     public String JavaDoc getHandle() {
739         try {
740             return this.node.getPath();
741         }
742         catch (RepositoryException e) {
743             log.error("Failed to get handle: " + e.getMessage(), e); //$NON-NLS-1$
744
return StringUtils.EMPTY;
745         }
746     }
747
748     /**
749      * get a handle representing path relative to the content repository with the default extension
750      * @return String representing path (handle) of the content
751      * @throws RepositoryException if an error occurs
752      */

753     public String JavaDoc getHandleWithDefaultExtension() throws PathNotFoundException, RepositoryException {
754         return (this.node.getPath() + "." + Server.getDefaultExtension()); //$NON-NLS-1$
755
}
756
757     /**
758      * get parent content object
759      * @throws javax.jcr.PathNotFoundException
760      * @return Content representing parent node
761      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
762      * operation
763      * @throws RepositoryException if an error occurs
764      */

765     public Content getParent() throws PathNotFoundException, RepositoryException, AccessDeniedException {
766         return (new Content(this.node.getParent(), this.accessManager));
767     }
768
769     /**
770      * get absolute parent object starting from the root node
771      * @param digree level at which the requested node exist, relative to the ROOT node
772      * @return Content representing parent node
773      * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
774      * operation
775      * @throws RepositoryException if an error occurs
776      */

777     public Content getAncestor(int digree) throws PathNotFoundException, RepositoryException, AccessDeniedException {
778         if (digree > this.getLevel()) {
779             throw new PathNotFoundException();
780         }
781         return (new Content(this.node.getAncestor(digree), this.accessManager));
782     }
783
784     /**
785      * Convenience method for taglib
786      * @return Content representing node on level 0
787      * @throws RepositoryException if an error occurs
788      */

789     public Collection JavaDoc getAncestors() throws PathNotFoundException, RepositoryException {
790         List JavaDoc allAncestors = new ArrayList JavaDoc();
791         int level = this.getLevel();
792         while (level != 0) {
793             try {
794                 allAncestors.add(new Content(this.node.getAncestor(--level), this.accessManager));
795             }
796             catch (AccessDeniedException e) {
797                 // valid
798
}
799         }
800         return allAncestors;
801     }
802
803     /**
804      * get node level from the ROOT node : FIXME implement getDepth in javax.jcr
805      * @throws javax.jcr.PathNotFoundException
806      * @return level at which current node exist, relative to the ROOT node
807      * @throws RepositoryException if an error occurs
808      */

809     public int getLevel() throws PathNotFoundException, RepositoryException {
810         return this.node.getPath().split("/").length - 1; //$NON-NLS-1$
811
}
812
813     /**
814      * move current node to the specified location above the named <code>beforename</code>
815      * @param srcName where current node has to be moved
816      * @param beforeName name of the node before the current node has to be placed
817      * @throws RepositoryException if an error occurs
818      */

819     public void orderBefore(String JavaDoc srcName, String JavaDoc beforeName) throws RepositoryException {
820         this.node.orderBefore(srcName, beforeName);
821     }
822
823     /**
824      * This method returns the index of this node within the ordered set of its same-name sibling nodes. This index is
825      * the one used to address same-name siblings using the square-bracket notation, e.g., /a[3]/b[4]. Note that the
826      * index always starts at 1 (not 0), for compatibility with XPath. As a result, for nodes that do not have
827      * same-name-siblings, this method will always return 1.
828      * @return The index of this node within the ordered set of its same-name sibling nodes.
829      * @throws RepositoryException if an error occurs
830      */

831     public int getIndex() throws RepositoryException {
832         return this.node.getIndex();
833     }
834
835     /**
836      * utility method to get Node object used to create current content object
837      * @return Node
838      */

839     public Node getJCRNode() {
840         return this.node;
841     }
842
843     /**
844      * evaluate primary node type of the associated Node of this object
845      */

846     public boolean isNodeType(String JavaDoc type) {
847         try {
848             return this.node.isNodeType(type);
849         }
850         catch (RepositoryException re) {
851             log.error(re.getMessage());
852             log.debug(re);
853         }
854         return false;
855     }
856
857     /**
858      * returns primary node type definition of the associated Node of this object
859      * @throws RepositoryException if an error occurs
860      */

861     public NodeType getNodeType() throws RepositoryException {
862         return this.node.getPrimaryNodeType();
863     }
864
865     /**
866      * Restores this node to the state defined by the version with the specified versionName.
867      * @param versionName
868      * @param removeExisting
869      * @throws VersionException if the specified <code>versionName</code> does not exist in this node's version
870      * history
871      * @throws RepositoryException if an error occurs
872      * @see javax.jcr.Node#restore(String, boolean)
873      */

874     public void restore(String JavaDoc versionName, boolean removeExisting) throws VersionException,
875         UnsupportedRepositoryOperationException, RepositoryException {
876         this.node.restore(versionName, removeExisting);
877     }
878
879     /**
880      * Restores this node to the state defined by the specified version.
881      * @param version
882      * @param removeExisting
883      * @throws VersionException if the specified <code>version</code> is not part of this node's version history
884      * @throws RepositoryException if an error occurs
885      * @see javax.jcr.Node#restore(javax.jcr.version.Version, boolean)
886      */

887     public void restore(Version version, boolean removeExisting) throws VersionException,
888         UnsupportedRepositoryOperationException, RepositoryException {
889         this.node.restore(version, removeExisting);
890     }
891
892     /**
893      * Restores the specified version to relPath, relative to this node.
894      * @param version
895      * @param relPath
896      * @param removeExisting
897      * @throws VersionException if the specified <code>version</code> is not part of this node's version history
898      * @throws RepositoryException if an error occurs
899      * @see javax.jcr.Node#restore(javax.jcr.version.Version, String, boolean)
900      */

901     public void restore(Version version, String JavaDoc relPath, boolean removeExisting) throws VersionException,
902         UnsupportedRepositoryOperationException, RepositoryException {
903         this.node.restore(version, relPath, removeExisting);
904     }
905
906     /**
907      * Restores this node to the state recorded in the version specified by versionLabel.
908      * @param versionLabel
909      * @param removeExisting
910      * @throws VersionException if the specified <code>versionLabel</code> does not exist in this node's version
911      * history
912      * @throws RepositoryException if an error occurs
913      * @see javax.jcr.Node#restoreByLabel(String, boolean)
914      */

915     public void restoreByLabel(String JavaDoc versionLabel, boolean removeExisting) throws VersionException,
916         UnsupportedRepositoryOperationException, RepositoryException {
917         this.node.restoreByLabel(versionLabel, removeExisting);
918     }
919
920     /**
921      * add version leaving the node checked out
922      * @throws RepositoryException if an error occurs
923      */

924     public Version addVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
925         Version version = this.checkIn();
926         this.checkOut();
927         return version;
928     }
929
930     /**
931      * @return checked in version
932      * @throws RepositoryException if an error occurs
933      */

934     public Version checkIn() throws UnsupportedRepositoryOperationException, RepositoryException {
935         return this.node.checkin();
936     }
937
938     /**
939      * check out for further write operations
940      * @throws RepositoryException if an error occurs
941      */

942     public void checkOut() throws UnsupportedRepositoryOperationException, RepositoryException {
943         this.node.checkout();
944     }
945
946     /**
947      * @return version history
948      * @throws RepositoryException if an error occurs
949      */

950     public VersionHistory getVersionHistory() throws UnsupportedRepositoryOperationException, RepositoryException {
951         return this.node.getVersionHistory();
952     }
953
954     /**
955      * @return Version iterator retreived from version history
956      * @throws RepositoryException if an error occurs
957      */

958     public VersionIterator getAllVersions() throws UnsupportedRepositoryOperationException, RepositoryException {
959         return this.getVersionHistory().getAllVersions();
960     }
961
962     /**
963      * Persists all changes to the repository if validation succeds
964      * @throws RepositoryException if an error occurs
965      */

966     public void save() throws RepositoryException {
967         this.node.getSession().save();
968     }
969
970     /**
971      * checks for the allowed access rights
972      * @param permissions as defined in javax.jcr.Permission
973      * @return true is the current user has specified access on this node.
974      */

975     public boolean isGranted(long permissions) {
976         try {
977             Access.isGranted(this.accessManager, Path.getAbsolutePath(node.getPath()), permissions);
978             return true;
979         }
980         catch (RepositoryException re) {
981             log.debug(this.getHandle() + " says: no access"); //$NON-NLS-1$
982
}
983         return false;
984     }
985
986     /**
987      * Remove this path
988      * @throws RepositoryException if an error occurs
989      */

990     public void delete() throws RepositoryException {
991         Access.isGranted(this.accessManager, Path.getAbsolutePath(this.node.getPath()), Permission.REMOVE);
992         this.node.remove();
993     }
994
995     /**
996      * Remove specified path
997      * @throws RepositoryException if an error occurs
998      */

999     public void delete(String JavaDoc path) throws RepositoryException {
1000        Access.isGranted(this.accessManager, Path.getAbsolutePath(this.node.getPath(), path), Permission.REMOVE);
1001        if (this.isNodeData(path)) {
1002            this.node.getProperty(path).remove();
1003        }
1004        else {
1005            this.node.getNode(path).remove();
1006        }
1007    }
1008
1009    /**
1010     * checks if the requested resource is an NodeData (Property)
1011     * @param path of the requested NodeData
1012     * @return boolean true is the requested content is an NodeData
1013     * @throws AccessDeniedException
1014     * @throws AccessDeniedException if the current session does not have sufficient access rights to complete the
1015     * operation
1016     * @throws RepositoryException if an error occurs
1017     */

1018    public boolean isNodeData(String JavaDoc path) throws AccessDeniedException, RepositoryException {
1019        Access.isGranted(this.accessManager, Path.getAbsolutePath(this.node.getPath(), path), Permission.READ);
1020        try {
1021            return this.node.hasProperty(path);
1022        }
1023        catch (RepositoryException e) {
1024            log.debug("isNodeData(): " + e.getMessage()); //$NON-NLS-1$
1025
}
1026        return false;
1027    }
1028
1029    /**
1030     * If keepChanges is false, this method discards all pending changes recorded in this session.
1031     * @see javax.jcr.Node#refresh(boolean)
1032     * @throws RepositoryException if an error occurs
1033     */

1034    public void refresh(boolean keepChanges) throws RepositoryException {
1035        this.node.refresh(keepChanges);
1036    }
1037
1038    /**
1039     * UUID of the node refrenced by this object
1040     * @return uuid
1041     */

1042    public String JavaDoc getUUID() {
1043        return this.getNodeData(PROPERTY_UUID).getString();
1044    }
1045
1046    /**
1047     * add specified mixin type if allowed
1048     * @param type mixin type to be added
1049     * @throws RepositoryException if an error occurs
1050     */

1051    public void addMixin(String JavaDoc type) throws RepositoryException {
1052        Access.isGranted(this.accessManager, Path.getAbsolutePath(this.node.getPath()), Permission.SET);
1053        if (this.node.canAddMixin(type)) {
1054            this.node.addMixin(type);
1055        }
1056        else {
1057            log.error("Node - " + this.node.getPath() + " does not allow mixin type - " + type); //$NON-NLS-1$ //$NON-NLS-2$
1058
}
1059    }
1060
1061    /**
1062     * Removes the specified mixin node type from this node. Also removes mixinName from this node's jcr:mixinTypes
1063     * property. <b>The mixin node type removal takes effect on save</b>.
1064     * @param type , mixin type to be removed
1065     * @throws RepositoryException if an error occurs
1066     */

1067    public void removeMixin(String JavaDoc type) throws RepositoryException {
1068        Access.isGranted(this.accessManager, Path.getAbsolutePath(this.node.getPath()), Permission.SET);
1069        this.node.removeMixin(type);
1070    }
1071
1072    /**
1073     * Returns an array of NodeType objects representing the mixin node types assigned to this node. This includes only
1074     * those mixin types explicitly assigned to this node, and therefore listed in the property jcr:mixinTypes. It does
1075     * not include mixin types inherited through the additon of supertypes to the primary type hierarchy.
1076     * @return an array of mixin NodeType objects.
1077     * @throws RepositoryException if an error occurs
1078     */

1079    public NodeType[] getMixinNodeTypes() throws RepositoryException {
1080        return this.node.getMixinNodeTypes();
1081    }
1082
1083    /**
1084     * places a lock on this object
1085     * @param isDeep if true this lock will apply to this node and all its descendants; if false, it applies only to
1086     * this node.
1087     * @param isSessionScoped if true, this lock expires with the current session; if false it expires when explicitly
1088     * or automatically unlocked for some other reason.
1089     * @return A Lock object containing a lock token.
1090     * @throws LockException if this node is already locked or <code>isDeep</code> is true and a descendant node of
1091     * this node already holds a lock.
1092     * @throws RepositoryException if an error occurs
1093     * @see javax.jcr.Node#lock(boolean, boolean)
1094     */

1095    public Lock lock(boolean isDeep, boolean isSessionScoped) throws LockException, RepositoryException {
1096        return this.node.lock(isDeep, isSessionScoped);
1097    }
1098
1099    /**
1100     * Returns the Lock object that applies to this node. This may be either a lock on this node itself or a deep lock
1101     * on a node above this node.
1102     * @throws LockException If no lock applies to this node, a LockException is thrown.
1103     * @throws RepositoryException if an error occurs
1104     */

1105    public Lock getLock() throws LockException, RepositoryException {
1106        return this.node.getLock();
1107    }
1108
1109    /**
1110     * Removes the lock on this node. Also removes the properties jcr:lockOwner and jcr:lockIsDeep from this node. These
1111     * changes are persisted automatically; <b>there is no need to call save</b>.
1112     * @throws LockException if either does not currently hold a lock, or holds a lock for which this Session does not
1113     * have the correct lock token
1114     * @throws RepositoryException if an error occurs
1115     */

1116    public void unlock() throws LockException, RepositoryException {
1117        this.node.unlock();
1118    }
1119
1120    /**
1121     * Returns true if this node holds a lock; otherwise returns false. To hold a lock means that this node has actually
1122     * had a lock placed on it specifically, as opposed to just having a lock apply to it due to a deep lock held by a
1123     * node above.
1124     * @throws RepositoryException if an error occurs
1125     */

1126    public boolean holdsLock() throws RepositoryException {
1127        return this.node.holdsLock();
1128    }
1129
1130    /**
1131     * Add a UUID property to the existing node
1132     * @throws RepositoryException
1133     */

1134    private void addUUID() throws RepositoryException {
1135        this.node.setProperty(PROPERTY_UUID, UUIDGenerator.getInstance().generateTimeBasedUUID().toString());
1136    }
1137}
1138
Popular Tags