View Javadoc

1   /**
2    * This file Copyright (c) 2011-2014 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.jcr.wrapper;
35  
36  import info.magnolia.jcr.util.NodeUtil;
37  
38  import java.io.InputStream;
39  import java.math.BigDecimal;
40  import java.util.Calendar;
41  
42  import javax.jcr.AccessDeniedException;
43  import javax.jcr.Binary;
44  import javax.jcr.InvalidItemStateException;
45  import javax.jcr.InvalidLifecycleTransitionException;
46  import javax.jcr.Item;
47  import javax.jcr.ItemExistsException;
48  import javax.jcr.ItemNotFoundException;
49  import javax.jcr.ItemVisitor;
50  import javax.jcr.MergeException;
51  import javax.jcr.NoSuchWorkspaceException;
52  import javax.jcr.Node;
53  import javax.jcr.NodeIterator;
54  import javax.jcr.PathNotFoundException;
55  import javax.jcr.Property;
56  import javax.jcr.PropertyIterator;
57  import javax.jcr.ReferentialIntegrityException;
58  import javax.jcr.RepositoryException;
59  import javax.jcr.Session;
60  import javax.jcr.UnsupportedRepositoryOperationException;
61  import javax.jcr.Value;
62  import javax.jcr.ValueFormatException;
63  import javax.jcr.lock.Lock;
64  import javax.jcr.lock.LockException;
65  import javax.jcr.nodetype.ConstraintViolationException;
66  import javax.jcr.nodetype.NoSuchNodeTypeException;
67  import javax.jcr.nodetype.NodeDefinition;
68  import javax.jcr.nodetype.NodeType;
69  import javax.jcr.version.ActivityViolationException;
70  import javax.jcr.version.Version;
71  import javax.jcr.version.VersionException;
72  import javax.jcr.version.VersionHistory;
73  
74  /**
75   * Wrapper for JCR node.
76   */
77  public abstract class DelegateNodeWrapper implements Node, Cloneable {
78  
79      protected Node wrapped;
80  
81      protected DelegateNodeWrapper() {
82      }
83  
84      protected DelegateNodeWrapper(Node node) {
85          setWrappedNode(node);
86      }
87  
88      public Node getWrappedNode() {
89          return this.wrapped;
90      }
91  
92      public void setWrappedNode(Node node) {
93          if (NodeUtil.isWrappedWith(node, this.getClass())) {
94              throw new IllegalArgumentException(node + " is already wrapped by " + this.getClass().getName() + " and double wrapping is not supported.");
95          }
96          this.wrapped = node;
97      }
98  
99      @Override
100     public String toString() {
101         return wrapped != null ? wrapped.toString() : "";
102     }
103 
104     /////////////
105     //
106     //  Delegating method stubs
107     //
108     /////////////
109 
110     @Override
111     public void addMixin(String mixinName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
112         getWrappedNode().addMixin(mixinName);
113     }
114 
115     @Override
116     public Node addNode(String relPath) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, RepositoryException {
117         return getWrappedNode().addNode(relPath);
118     }
119 
120     @Override
121     public Node addNode(String relPath, String primaryNodeTypeName) throws ItemExistsException, PathNotFoundException, NoSuchNodeTypeException, LockException, VersionException, ConstraintViolationException, RepositoryException {
122         return getWrappedNode().addNode(relPath, primaryNodeTypeName);
123     }
124 
125     @Override
126     public boolean canAddMixin(String mixinName) throws NoSuchNodeTypeException, RepositoryException {
127         return getWrappedNode().canAddMixin(mixinName);
128     }
129 
130     @Override
131     public void cancelMerge(Version version) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException {
132         getWrappedNode().cancelMerge(version);
133     }
134 
135     @Override
136     public Version checkin() throws VersionException, UnsupportedRepositoryOperationException, InvalidItemStateException, LockException, RepositoryException {
137         return getWrappedNode().checkin();
138     }
139 
140     @Override
141     public void checkout() throws UnsupportedRepositoryOperationException, LockException, ActivityViolationException, RepositoryException {
142         getWrappedNode().checkout();
143     }
144 
145     @Override
146     public void doneMerge(Version version) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException {
147 
148     }
149 
150     @Override
151     public void followLifecycleTransition(String transition) throws UnsupportedRepositoryOperationException, InvalidLifecycleTransitionException, RepositoryException {
152         getWrappedNode().followLifecycleTransition(transition);
153     }
154 
155     @Override
156     public String[] getAllowedLifecycleTransistions() throws UnsupportedRepositoryOperationException, RepositoryException {
157         return getWrappedNode().getAllowedLifecycleTransistions();
158     }
159 
160     @Override
161     public Version getBaseVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
162         return getWrappedNode().getBaseVersion();
163     }
164 
165     @Override
166     public String getCorrespondingNodePath(String workspaceName) throws ItemNotFoundException, NoSuchWorkspaceException, AccessDeniedException, RepositoryException {
167         return getWrappedNode().getCorrespondingNodePath(workspaceName);
168     }
169 
170     @Override
171     public NodeDefinition getDefinition() throws RepositoryException {
172         return getWrappedNode().getDefinition();
173     }
174 
175     @Override
176     public String getIdentifier() throws RepositoryException {
177         return getWrappedNode().getIdentifier();
178     }
179 
180     @Override
181     public int getIndex() throws RepositoryException {
182         return getWrappedNode().getIndex();
183     }
184 
185     @Override
186     public Lock getLock() throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, RepositoryException {
187         return getWrappedNode().getLock();
188     }
189 
190     @Override
191     public NodeType[] getMixinNodeTypes() throws RepositoryException {
192         return getWrappedNode().getMixinNodeTypes();
193     }
194 
195     @Override
196     public Node getNode(String relPath) throws PathNotFoundException, RepositoryException {
197         return getWrappedNode().getNode(relPath);
198     }
199 
200     @Override
201     public NodeIterator getNodes() throws RepositoryException {
202         return getWrappedNode().getNodes();
203     }
204 
205     @Override
206     public NodeIterator getNodes(String namePattern) throws RepositoryException {
207         return getWrappedNode().getNodes(namePattern);
208     }
209 
210     @Override
211     public NodeIterator getNodes(String[] nameGlobs) throws RepositoryException {
212         return getWrappedNode().getNodes(nameGlobs);
213     }
214 
215     @Override
216     public Item getPrimaryItem() throws ItemNotFoundException, RepositoryException {
217         return getWrappedNode().getPrimaryItem();
218     }
219 
220     @Override
221     public NodeType getPrimaryNodeType() throws RepositoryException {
222         return getWrappedNode().getPrimaryNodeType();
223     }
224 
225     @Override
226     public PropertyIterator getProperties() throws RepositoryException {
227         return getWrappedNode().getProperties();
228     }
229 
230     @Override
231     public PropertyIterator getProperties(String namePattern) throws RepositoryException {
232         return getWrappedNode().getProperties(namePattern);
233     }
234 
235     @Override
236     public PropertyIterator getProperties(String[] nameGlobs) throws RepositoryException {
237         return getWrappedNode().getProperties(nameGlobs);
238     }
239 
240     @Override
241     public Property getProperty(String relPath) throws PathNotFoundException, RepositoryException {
242         return getWrappedNode().getProperty(relPath);
243     }
244 
245     @Override
246     public PropertyIterator getReferences() throws RepositoryException {
247         return getWrappedNode().getReferences();
248     }
249 
250     @Override
251     public PropertyIterator getReferences(String name) throws RepositoryException {
252         return getWrappedNode().getReferences(name);
253     }
254 
255     @Override
256     public NodeIterator getSharedSet() throws RepositoryException {
257         return getWrappedNode().getSharedSet();
258     }
259 
260     @Override
261     public String getUUID() throws UnsupportedRepositoryOperationException, RepositoryException {
262         return getWrappedNode().getUUID();
263     }
264 
265     @Override
266     public VersionHistory getVersionHistory() throws UnsupportedRepositoryOperationException, RepositoryException {
267         return getWrappedNode().getVersionHistory();
268     }
269 
270     @Override
271     public PropertyIterator getWeakReferences() throws RepositoryException {
272         return getWrappedNode().getWeakReferences();
273     }
274 
275     @Override
276     public PropertyIterator getWeakReferences(String name) throws RepositoryException {
277         return getWrappedNode().getWeakReferences(name);
278     }
279 
280     @Override
281     public boolean hasNode(String relPath) throws RepositoryException {
282         return getWrappedNode().hasNode(relPath);
283     }
284 
285     @Override
286     public boolean hasNodes() throws RepositoryException {
287         return getWrappedNode().hasNodes();
288     }
289 
290     @Override
291     public boolean hasProperties() throws RepositoryException {
292         return getWrappedNode().hasProperties();
293     }
294 
295     @Override
296     public boolean hasProperty(String relPath) throws RepositoryException {
297         return getWrappedNode().hasProperty(relPath);
298     }
299 
300     @Override
301     public boolean holdsLock() throws RepositoryException {
302         return getWrappedNode().holdsLock();
303     }
304 
305     @Override
306     public boolean isCheckedOut() throws RepositoryException {
307         return getWrappedNode().isCheckedOut();
308     }
309 
310     @Override
311     public boolean isLocked() throws RepositoryException {
312         return getWrappedNode().isLocked();
313     }
314 
315     @Override
316     public boolean isNodeType(String nodeTypeName) throws RepositoryException {
317         return getWrappedNode().isNodeType(nodeTypeName);
318     }
319 
320     @Override
321     public Lock lock(boolean isDeep, boolean isSessionScoped) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException {
322         return getWrappedNode().lock(isDeep, isSessionScoped);
323     }
324 
325     @Override
326     public NodeIterator merge(String srcWorkspace, boolean bestEffort) throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException {
327         return getWrappedNode().merge(srcWorkspace, bestEffort);
328     }
329 
330     @Override
331     public void orderBefore(String srcChildRelPath, String destChildRelPath) throws UnsupportedRepositoryOperationException, VersionException, ConstraintViolationException, ItemNotFoundException, LockException, RepositoryException {
332         getWrappedNode().orderBefore(srcChildRelPath, destChildRelPath);
333     }
334 
335     @Override
336     public void removeMixin(String mixinName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
337         getWrappedNode().removeMixin(mixinName);
338     }
339 
340     @Override
341     public void removeShare() throws VersionException, LockException, ConstraintViolationException, RepositoryException {
342         getWrappedNode().removeShare();
343     }
344 
345     @Override
346     public void removeSharedSet() throws VersionException, LockException, ConstraintViolationException, RepositoryException {
347         getWrappedNode().removeSharedSet();
348     }
349 
350     @Override
351     public void restore(String versionName, boolean removeExisting) throws VersionException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException {
352         getWrappedNode().restore(versionName, removeExisting);
353     }
354 
355     @Override
356     public void restore(Version version, boolean removeExisting) throws VersionException, ItemExistsException, InvalidItemStateException, UnsupportedRepositoryOperationException, LockException, RepositoryException {
357         getWrappedNode().restore(version, removeExisting);
358     }
359 
360     @Override
361     public void restore(Version version, String relPath, boolean removeExisting) throws PathNotFoundException, ItemExistsException, VersionException, ConstraintViolationException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException {
362         getWrappedNode().restore(version, relPath, removeExisting);
363     }
364 
365     @Override
366     public void restoreByLabel(String versionLabel, boolean removeExisting) throws VersionException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException {
367         getWrappedNode().restoreByLabel(versionLabel, removeExisting);
368     }
369 
370     @Override
371     public void setPrimaryType(String nodeTypeName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
372         getWrappedNode().setPrimaryType(nodeTypeName);
373     }
374 
375     @Override
376     public Property setProperty(String name, Value value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
377         return getWrappedNode().setProperty(name, value);
378     }
379 
380     @Override
381     public Property setProperty(String name, Value[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
382         return getWrappedNode().setProperty(name, values);
383     }
384 
385     @Override
386     public Property setProperty(String name, String[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
387         return getWrappedNode().setProperty(name, values);
388     }
389 
390     @Override
391     public Property setProperty(String name, String value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
392         return getWrappedNode().setProperty(name, value);
393     }
394 
395     @Override
396     public Property setProperty(String name, InputStream value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
397         return getWrappedNode().setProperty(name, value);
398     }
399 
400     @Override
401     public Property setProperty(String name, Binary value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
402         return getWrappedNode().setProperty(name, value);
403     }
404 
405     @Override
406     public Property setProperty(String name, boolean value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
407         return getWrappedNode().setProperty(name, value);
408     }
409 
410     @Override
411     public Property setProperty(String name, double value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
412         return getWrappedNode().setProperty(name, value);
413     }
414 
415     @Override
416     public Property setProperty(String name, BigDecimal value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
417         return getWrappedNode().setProperty(name, value);
418     }
419 
420     @Override
421     public Property setProperty(String name, long value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
422         return getWrappedNode().setProperty(name, value);
423     }
424 
425     @Override
426     public Property setProperty(String name, Calendar value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
427         return getWrappedNode().setProperty(name, value);
428     }
429 
430     @Override
431     public Property setProperty(String name, Node value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
432         return getWrappedNode().setProperty(name, value);
433     }
434 
435     @Override
436     public Property setProperty(String name, Value value, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
437         return getWrappedNode().setProperty(name, value, type);
438     }
439 
440     @Override
441     public Property setProperty(String name, Value[] values, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
442         return getWrappedNode().setProperty(name, values, type);
443     }
444 
445     @Override
446     public Property setProperty(String name, String[] values, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
447         return getWrappedNode().setProperty(name, values, type);
448     }
449 
450     @Override
451     public Property setProperty(String name, String value, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
452         return getWrappedNode().setProperty(name, value, type);
453     }
454 
455     @Override
456     public void unlock() throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException {
457         getWrappedNode().unlock();
458     }
459 
460     @Override
461     public void update(String srcWorkspace) throws NoSuchWorkspaceException, AccessDeniedException, LockException, InvalidItemStateException, RepositoryException {
462         getWrappedNode().update(srcWorkspace);
463     }
464 
465     @Override
466     public void accept(ItemVisitor visitor) throws RepositoryException {
467         getWrappedNode().accept(visitor);
468     }
469 
470     @Override
471     public Item getAncestor(int depth) throws ItemNotFoundException, AccessDeniedException, RepositoryException {
472         return getWrappedNode().getAncestor(depth);
473     }
474 
475     @Override
476     public int getDepth() throws RepositoryException {
477         return getWrappedNode().getDepth();
478     }
479 
480     @Override
481     public String getName() throws RepositoryException {
482         return getWrappedNode().getName();
483     }
484 
485     @Override
486     public Node getParent() throws ItemNotFoundException, AccessDeniedException, RepositoryException {
487         return getWrappedNode().getParent();
488     }
489 
490     @Override
491     public String getPath() throws RepositoryException {
492         return getWrappedNode().getPath();
493     }
494 
495     @Override
496     public Session getSession() throws RepositoryException {
497         return getWrappedNode().getSession();
498     }
499 
500     @Override
501     public boolean isModified() {
502         return getWrappedNode().isModified();
503     }
504 
505     @Override
506     public boolean isNew() {
507         return getWrappedNode().isNew();
508     }
509 
510     @Override
511     public boolean isNode() {
512         return getWrappedNode().isNode();
513     }
514 
515     @Override
516     public boolean isSame(Item otherItem) throws RepositoryException {
517 
518         if (this == otherItem) {
519             return true;
520         }
521         if (otherItem instanceof Node) {
522             return this.getIdentifier().equals(((Node) otherItem).getIdentifier())
523                     && getSession().getWorkspace().getName().equals(
524                             otherItem.getSession().getWorkspace().getName());
525         }
526         return false;
527     }
528 
529     @Override
530     public void refresh(boolean keepChanges) throws InvalidItemStateException, RepositoryException {
531         getWrappedNode().refresh(keepChanges);
532     }
533 
534     @Override
535     public void remove() throws VersionException, LockException, ConstraintViolationException, AccessDeniedException, RepositoryException {
536         getWrappedNode().remove();
537     }
538 
539     @Override
540     public void save() throws AccessDeniedException, ItemExistsException, ConstraintViolationException, InvalidItemStateException, ReferentialIntegrityException, VersionException, LockException, NoSuchNodeTypeException, RepositoryException {
541         getWrappedNode().save();
542     }
543 
544     /**
545      * Removes a wrapper by type. The wrapper can be deep in a chain of wrappers in which case wrappers before it will
546      * be cloned creating a new chain that leads to the same real node.
547      */
548     public Node deepUnwrap(Class<? extends DelegateNodeWrapper> wrapper)  {
549 
550         if (this.getClass().equals(wrapper)) {
551             return getWrappedNode();
552         }
553 
554         Node next = getWrappedNode();
555 
556         // If the next node is the real node then we can skip cloning ourselves.
557         // This happens when the wrapper to remove isn't present
558         if (!(next instanceof DelegateNodeWrapper)) {
559             return this;
560         }
561 
562         // We let the next wrapper do deepUnwrap first, if it returns itself then the wrapper isn't in the chain and cloning is not necessary
563         Node deepUnwrappedNext = ((DelegateNodeWrapper) next).deepUnwrap(wrapper);
564         if (deepUnwrappedNext == next) {
565             return this;
566         }
567 
568         try {
569             DelegateNodeWrapper clone = ((DelegateNodeWrapper) this.clone());
570             clone.initClone(deepUnwrappedNext);
571             return clone;
572         } catch (CloneNotSupportedException e) {
573             throw new RuntimeException("Failed to unwrap " + this.getClass().getName() + " due to " + e.getMessage(), e);
574         }
575     }
576 
577     protected void initClone(Node newNode) {
578         setWrappedNode(newNode);
579     }
580 
581     @Override
582     protected Object clone() throws CloneNotSupportedException {
583         // just shallow clone ... keep it that way at least for wrappedNode otherwise deepUnwrap generates zillions of objects unnecessarily
584         return super.clone();
585     }
586 }