1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cms.core;
35
36 import info.magnolia.cms.core.version.ContentVersion;
37 import info.magnolia.cms.core.version.VersionManager;
38 import info.magnolia.cms.security.AccessDeniedException;
39 import info.magnolia.cms.security.Permission;
40 import info.magnolia.cms.util.Rule;
41 import info.magnolia.logging.AuditLoggingUtil;
42
43 import java.util.ArrayList;
44 import java.util.Collection;
45 import java.util.Comparator;
46 import java.util.List;
47 import java.util.TreeSet;
48
49 import javax.jcr.Item;
50 import javax.jcr.Node;
51 import javax.jcr.NodeIterator;
52 import javax.jcr.PathNotFoundException;
53 import javax.jcr.Property;
54 import javax.jcr.PropertyIterator;
55 import javax.jcr.PropertyType;
56 import javax.jcr.RepositoryException;
57 import javax.jcr.UnsupportedRepositoryOperationException;
58 import javax.jcr.lock.Lock;
59 import javax.jcr.lock.LockException;
60 import javax.jcr.nodetype.NodeType;
61 import javax.jcr.version.Version;
62 import javax.jcr.version.VersionException;
63 import javax.jcr.version.VersionHistory;
64 import javax.jcr.version.VersionIterator;
65
66 import org.apache.commons.lang.StringUtils;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
69
70
71
72
73
74
75
76
77 public class DefaultContent extends AbstractContent {
78 private static final Logger log = LoggerFactory.getLogger(DefaultContent.class);
79
80
81
82
83 protected Node node;
84
85
86
87
88 private String path;
89
90
91
92
93 private Node rootNode;
94
95
96
97
98 private MetaData metaData;
99
100
101
102
103 protected DefaultContent() {
104 }
105
106
107
108
109
110
111
112
113
114
115
116 DefaultContent(Node rootNode, String path, HierarchyManager hierarchyManager) throws PathNotFoundException, RepositoryException, AccessDeniedException {
117 this.setHierarchyManager(hierarchyManager);
118 Access.isGranted(hierarchyManager.getAccessManager(), Path.getAbsolutePath(rootNode.getPath(), path), Permission.READ);
119 this.setPath(path);
120 this.setRootNode(rootNode);
121 this.setNode(this.rootNode.getNode(this.path));
122 }
123
124
125
126
127
128
129
130
131
132 public DefaultContent(Item elem,HierarchyManager hierarchyManager) throws RepositoryException, AccessDeniedException {
133 this.setHierarchyManager(hierarchyManager);
134 Access.isGranted(hierarchyManager.getAccessManager(), Path.getAbsolutePath(elem.getPath()), Permission.READ);
135 this.setNode((Node) elem);
136 this.setPath(this.getHandle());
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150
151 DefaultContent(Node rootNode, String path, String contentType, HierarchyManager hierarchyManager)
152 throws PathNotFoundException,
153 RepositoryException,
154 AccessDeniedException {
155 this.setHierarchyManager(hierarchyManager);
156 Access.isGranted(hierarchyManager.getAccessManager(), Path.getAbsolutePath(rootNode.getPath(), path), Permission.WRITE);
157 this.setPath(path);
158 this.setRootNode(rootNode);
159 this.node = this.rootNode.addNode(this.path, contentType);
160
161
162
163 this.addMixin(ItemType.MIX_LOCKABLE);
164 AuditLoggingUtil.log( AuditLoggingUtil.ACTION_CREATE, hierarchyManager.getName(), this.getItemType(), Path.getAbsolutePath(node.getPath()));
165 }
166
167
168
169
170 protected void setNode(Node node) {
171 this.node = node;
172 }
173
174
175
176
177 protected void setRootNode(Node node) {
178 this.rootNode = node;
179 }
180
181
182
183
184 protected void setPath(String path) {
185 this.path = path;
186 }
187
188 public Content getContent(String name) throws PathNotFoundException, RepositoryException, AccessDeniedException {
189 return (new DefaultContent(this.node, name, this.hierarchyManager));
190 }
191
192 public Content createContent(String name, String contentType) throws PathNotFoundException, RepositoryException,
193 AccessDeniedException {
194 Content content = new DefaultContent(this.node, name, contentType, this.hierarchyManager);
195 MetaData metaData = content.getMetaData();
196 metaData.setCreationDate();
197 return content;
198 }
199
200 @Override
201 public boolean hasNodeData(String name) throws RepositoryException {
202 if (this.node.hasProperty(name)) {
203 return true;
204 }
205 else {
206 if (this.node.hasNode(name) && (this.node.getNode(name).isNodeType(ItemType.NT_RESOURCE) || (this.node.hasProperty("jcr:frozenPrimaryType") && this.node.getNode(name).getProperty("jcr:frozenPrimaryType").getValue().getString().equals(ItemType.NT_RESOURCE)))) {
207 return true;
208 }
209 }
210 return false;
211 }
212
213 public NodeData newNodeDataInstance(String name, int type, boolean createIfNotExisting) throws AccessDeniedException, RepositoryException {
214 try {
215 Access.isGranted(getAccessManager(), Path.getAbsolutePath(getHandle(), name), Permission.READ);
216 }
217
218 catch (AccessDeniedException e) {
219 return new NonExistingNodeData(this, name);
220 }
221
222
223 if(!hasNodeData(name) && !createIfNotExisting){
224 return new NonExistingNodeData(this, name);
225 }
226
227 if(type == PropertyType.UNDEFINED){
228 type = determineNodeDataType(name);
229 }
230
231 if(type == PropertyType.BINARY){
232 return new BinaryNodeData(this, name);
233 }
234 else{
235 return new DefaultNodeData(this, name);
236 }
237 }
238
239 protected int determineNodeDataType(String name) {
240
241 try {
242 if (this.node.hasProperty(name)) {
243 return this.node.getProperty(name).getType();
244 }
245 else {
246 if (this.node.hasNode(name) && (this.node.getNode(name).isNodeType(ItemType.NT_RESOURCE) || (this.node.getNode(name).hasProperty("jcr:frozenPrimaryType") && this.node.getNode(name).getProperty("jcr:frozenPrimaryType").getValue().getString().equals(ItemType.NT_RESOURCE)))) {
247 return PropertyType.BINARY;
248 }
249 }
250 }
251 catch (RepositoryException e) {
252 throw new IllegalStateException("Can't determine property type of [" + getHandle() + "/" + name + "]", e);
253 }
254 return PropertyType.UNDEFINED;
255 }
256
257
258 public MetaData getMetaData() {
259 if (this.metaData == null) {
260 this.metaData = new MetaData(this.node, this.hierarchyManager.getAccessManager());
261 }
262 return this.metaData;
263 }
264
265 public String getName() {
266 try {
267 return this.node.getName();
268 }
269 catch (RepositoryException e) {
270 log.error(e.getMessage(), e);
271 }
272 return StringUtils.EMPTY;
273 }
274
275 public Collection<Content> getChildren(ContentFilter filter, String namePattern, Comparator<Content> orderCriteria) {
276 Collection<Content> children;
277 if (orderCriteria == null) {
278 children = new ArrayList<Content>();
279 }
280 else {
281 children = new TreeSet<Content>(orderCriteria);
282 }
283
284 try {
285 final NodeIterator nodeIterator;
286 if (namePattern == null) {
287 nodeIterator = this.node.getNodes();
288 } else {
289 nodeIterator = this.node.getNodes(namePattern);
290 }
291
292 while (nodeIterator.hasNext()) {
293 Node subNode = (Node) nodeIterator.next();
294 try {
295 Content content = new DefaultContent(subNode, this.hierarchyManager);
296 if (filter.accept(content)) {
297 children.add(content);
298 }
299 }
300 catch (PathNotFoundException e) {
301 log.error("Exception caught", e);
302 }
303 catch (AccessDeniedException e) {
304
305 }
306 }
307 }
308 catch (RepositoryException re) {
309 log.error("Exception caught", re);
310 }
311
312 return children;
313 }
314
315 public Collection<NodeData> getNodeDataCollection(String namePattern) {
316 final ArrayList<NodeData> all = new ArrayList<NodeData>();
317 try {
318 all.addAll(getPrimitiveNodeDatas(namePattern));
319 all.addAll(getBinaryNodeDatas(namePattern));
320 }
321 catch (RepositoryException e) {
322 throw new IllegalStateException("Can't read node datas of " + toString(), e);
323 }
324 return all;
325 }
326
327 protected Collection<NodeData> getPrimitiveNodeDatas(String namePattern) throws RepositoryException {
328 final Collection<NodeData> nodeDatas = new ArrayList<NodeData>();
329 final PropertyIterator propertyIterator;
330 if (namePattern == null) {
331 propertyIterator = this.node.getProperties();
332 } else {
333 propertyIterator = this.node.getProperties(namePattern);
334 }
335 while (propertyIterator.hasNext()) {
336 Property property = (Property) propertyIterator.next();
337 try {
338 if (!property.getName().startsWith("jcr:") && !property.getName().startsWith("mgnl:")) {
339 nodeDatas.add(getNodeData(property.getName()));
340 }
341 }
342 catch (PathNotFoundException e) {
343 log.error("Exception caught", e);
344 }
345 catch (AccessDeniedException e) {
346
347 }
348 }
349 return nodeDatas;
350 }
351
352
353 public boolean hasContent(String name) throws RepositoryException {
354 return this.node.hasNode(name);
355 }
356
357 public String getHandle() {
358 try {
359 return this.node.getPath();
360 }
361 catch (RepositoryException e) {
362 log.error("Failed to get handle: " + e.getMessage(), e);
363 return StringUtils.EMPTY;
364 }
365 }
366
367 public Content getParent() throws PathNotFoundException, RepositoryException, AccessDeniedException {
368 return (new DefaultContent(this.node.getParent(), this.hierarchyManager));
369 }
370
371 public Content getAncestor(int level) throws PathNotFoundException, RepositoryException, AccessDeniedException {
372 if (level > this.getLevel()) {
373 throw new PathNotFoundException();
374 }
375 return (new DefaultContent(this.node.getAncestor(level), this.hierarchyManager));
376 }
377
378 public Collection<Content> getAncestors() throws PathNotFoundException, RepositoryException {
379 List<Content> allAncestors = new ArrayList<Content>();
380 int level = this.getLevel();
381 while (level != 0) {
382 try {
383 allAncestors.add(getAncestor(--level));
384 }
385 catch (AccessDeniedException e) {
386
387 }
388 }
389 return allAncestors;
390 }
391
392 public int getLevel() throws PathNotFoundException, RepositoryException {
393 return this.node.getDepth();
394 }
395
396 public void orderBefore(String srcName, String beforeName) throws RepositoryException {
397 this.node.orderBefore(srcName, beforeName);
398 }
399
400 public int getIndex() throws RepositoryException {
401 return this.node.getIndex();
402 }
403
404 public Node getJCRNode() {
405 return this.node;
406 }
407
408 public boolean isNodeType(String type) {
409 return isNodeType(this.node, type);
410 }
411
412
413
414
415
416
417 protected boolean isNodeType(Node node, String type) {
418 try {
419 final String actualType = node.getProperty(ItemType.JCR_PRIMARY_TYPE).getString();
420
421 if (ItemType.NT_FROZENNODE.equals(actualType) && !(ItemType.NT_FROZENNODE.equals(type))) {
422 final Property p = node.getProperty(ItemType.JCR_FROZEN_PRIMARY_TYPE);
423 final String s = p.getString();
424 return s.equalsIgnoreCase(type);
425 } else {
426 return node.isNodeType(type);
427 }
428 }
429 catch (RepositoryException re) {
430 log.error(re.getMessage());
431 log.debug(re.getMessage(), re);
432 return false;
433 }
434 }
435
436 public NodeType getNodeType() throws RepositoryException {
437 return this.node.getPrimaryNodeType();
438 }
439
440 public String getNodeTypeName() throws RepositoryException {
441
442 if (this.node.hasProperty(ItemType.JCR_FROZEN_PRIMARY_TYPE)) {
443 return this.node.getProperty(ItemType.JCR_FROZEN_PRIMARY_TYPE).getString();
444 }
445 return this.node.getProperty(ItemType.JCR_PRIMARY_TYPE).getString();
446 }
447
448 public ItemType getItemType() throws RepositoryException {
449 return new ItemType(getNodeTypeName());
450 }
451
452 public void restore(String versionName, boolean removeExisting) throws VersionException, UnsupportedRepositoryOperationException, RepositoryException {
453 Access.isGranted(this.hierarchyManager.getAccessManager(), this.getHandle(), Permission.WRITE);
454 Version version = this.getVersionHistory().getVersion(versionName);
455 this.restore(version, removeExisting);
456 }
457
458 public void restore(Version version, boolean removeExisting) throws VersionException, UnsupportedRepositoryOperationException, RepositoryException {
459 Access.isGranted(this.hierarchyManager.getAccessManager(), this.getHandle(), Permission.WRITE);
460 VersionManager.getInstance().restore(this, version, removeExisting);
461 }
462
463 public void restore(Version version, String relPath, boolean removeExisting) throws VersionException, UnsupportedRepositoryOperationException, RepositoryException {
464 throw new UnsupportedRepositoryOperationException("Not implemented in 3.0 Beta");
465 }
466
467 public void restoreByLabel(String versionLabel, boolean removeExisting) throws VersionException, UnsupportedRepositoryOperationException, RepositoryException {
468 this.node.restoreByLabel(versionLabel, removeExisting);
469 throw new UnsupportedRepositoryOperationException("Not implemented in 3.0 Beta");
470 }
471
472 public Version addVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
473 return VersionManager.getInstance().addVersion(this);
474 }
475
476 public Version addVersion(Rule rule) throws UnsupportedRepositoryOperationException, RepositoryException {
477 return VersionManager.getInstance().addVersion(this, rule);
478 }
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494 protected boolean isCheckedOut() throws RepositoryException {
495 return this.node.isCheckedOut();
496 }
497
498 public boolean isModified() {
499 return this.node.isModified();
500 }
501
502 public VersionHistory getVersionHistory() throws UnsupportedRepositoryOperationException, RepositoryException {
503 return VersionManager.getInstance().getVersionHistory(this);
504 }
505
506 public VersionIterator getAllVersions() throws UnsupportedRepositoryOperationException, RepositoryException {
507 return VersionManager.getInstance().getAllVersions(this);
508 }
509
510 public ContentVersion getBaseVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
511 return new ContentVersion(VersionManager.getInstance().getBaseVersion(this), this);
512 }
513
514 public ContentVersion getVersionedContent(Version version) throws RepositoryException {
515 return new ContentVersion(version, this);
516 }
517
518 public ContentVersion getVersionedContent(String versionName) throws RepositoryException {
519 return new ContentVersion(VersionManager.getInstance().getVersion(this, versionName), this);
520 }
521
522 public void removeVersionHistory() throws AccessDeniedException, RepositoryException {
523 Access.isGranted(this.hierarchyManager.getAccessManager(), Path.getAbsolutePath(node.getPath()), Permission.WRITE);
524 VersionManager.getInstance().removeVersionHistory(this.node.getUUID());
525 }
526
527 public void save() throws RepositoryException {
528 this.node.save();
529 }
530
531 public void delete() throws RepositoryException {
532 Access.isGranted(this.hierarchyManager.getAccessManager(), Path.getAbsolutePath(this.node.getPath()), Permission.REMOVE);
533 String nodePath = Path.getAbsolutePath(this.node.getPath());
534 ItemType nodeType = this.getItemType();
535 this.node.remove();
536 AuditLoggingUtil.log( AuditLoggingUtil.ACTION_DELETE, hierarchyManager.getName(), nodeType, nodePath);
537 }
538
539
540 public void refresh(boolean keepChanges) throws RepositoryException {
541 this.node.refresh(keepChanges);
542 }
543
544 public String getUUID() {
545 try {
546 return this.node.getUUID();
547 }
548 catch (UnsupportedOperationException e) {
549 log.error(e.getMessage());
550 }
551 catch (RepositoryException re) {
552 log.error("Exception caught", re);
553 }
554 return StringUtils.EMPTY;
555 }
556
557 public void addMixin(String type) throws RepositoryException {
558 Access.isGranted(this.hierarchyManager.getAccessManager(), Path.getAbsolutePath(this.node.getPath()), Permission.SET);
559 if (this.node.canAddMixin(type)) {
560 this.node.addMixin(type);
561 }
562 else {
563 log.error("Node - " + this.node.getPath() + " does not allow mixin type - " + type);
564 }
565 }
566
567 public void removeMixin(String type) throws RepositoryException {
568 Access.isGranted(this.hierarchyManager.getAccessManager(), Path.getAbsolutePath(this.node.getPath()), Permission.SET);
569 this.node.removeMixin(type);
570 }
571
572 public NodeType[] getMixinNodeTypes() throws RepositoryException {
573 return this.node.getMixinNodeTypes();
574 }
575
576 public Lock lock(boolean isDeep, boolean isSessionScoped) throws LockException, RepositoryException {
577 return this.node.lock(isDeep, isSessionScoped);
578 }
579
580 public Lock lock(boolean isDeep, boolean isSessionScoped, long yieldFor) throws LockException, RepositoryException {
581 long finalTime = System.currentTimeMillis() + yieldFor;
582 LockException lockException = null;
583 while (System.currentTimeMillis() <= finalTime) {
584 try {
585 return this.node.lock(isDeep, isSessionScoped);
586 }
587 catch (LockException e) {
588
589 lockException = e;
590 }
591 Thread.yield();
592 }
593
594 throw lockException;
595 }
596
597 public Lock getLock() throws LockException, RepositoryException {
598 return this.node.getLock();
599 }
600
601 public void unlock() throws LockException, RepositoryException {
602 this.node.unlock();
603 }
604
605 public boolean holdsLock() throws RepositoryException {
606 return this.node.holdsLock();
607 }
608
609 public boolean isLocked() throws RepositoryException {
610 return this.node.isLocked();
611 }
612
613 public boolean hasMetaData() {
614 try {
615 return this.node.hasNode("MetaData");
616 }
617 catch (RepositoryException re) {
618 log.debug(re.getMessage(), re);
619 }
620 return false;
621 }
622
623 }