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.version;
35
36 import info.magnolia.cms.core.AbstractContent;
37 import info.magnolia.cms.core.Content;
38 import info.magnolia.cms.core.HierarchyManager;
39 import info.magnolia.cms.core.ItemType;
40 import info.magnolia.cms.core.NodeData;
41 import info.magnolia.cms.core.DefaultContent;
42 import info.magnolia.cms.security.AccessDeniedException;
43 import info.magnolia.cms.security.AccessManager;
44 import info.magnolia.cms.security.AccessManagerImpl;
45 import info.magnolia.cms.security.Permission;
46 import info.magnolia.cms.security.PermissionImpl;
47 import info.magnolia.cms.util.ContentWrapper;
48 import info.magnolia.cms.util.HierarchyManagerWrapper;
49 import info.magnolia.cms.util.Rule;
50 import info.magnolia.cms.util.SimpleUrlPattern;
51
52 import java.util.ArrayList;
53 import java.util.Calendar;
54 import java.util.Collection;
55 import java.util.List;
56
57 import javax.jcr.PathNotFoundException;
58 import javax.jcr.PropertyType;
59 import javax.jcr.RepositoryException;
60 import javax.jcr.Value;
61 import javax.jcr.Workspace;
62 import javax.jcr.lock.Lock;
63 import javax.jcr.lock.LockException;
64 import javax.jcr.nodetype.NodeType;
65 import javax.jcr.version.Version;
66 import javax.jcr.version.VersionHistory;
67 import javax.jcr.version.VersionIterator;
68
69 import org.apache.commons.lang.StringUtils;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
72
73
74
75
76
77
78
79 public class ContentVersion extends DefaultContent {
80
81 private final class FixParentContentWrapper extends ContentWrapper {
82 private final Content parent;
83
84 private FixParentContentWrapper(Content wrappedContent, Content parent) {
85 super(wrappedContent);
86 this.parent = parent;
87 }
88
89 @Override
90 public Content getParent() throws RepositoryException {
91 return parent;
92 }
93
94 @Override
95 protected Content wrap(Content node) {
96 return new FixParentContentWrapper(node, this);
97 }
98 }
99
100 private static Logger log = LoggerFactory.getLogger(ContentVersion.class);
101
102
103
104
105 public static final String VERSION_USER = "versionUser";
106
107
108
109
110 public static final String NAME = "name";
111
112
113
114
115 private Version state;
116
117
118
119
120 private AbstractContent base;
121
122
123
124
125 private Rule rule;
126
127 public ContentVersion(Version thisVersion, AbstractContent base) throws RepositoryException {
128 if (thisVersion == null) {
129 throw new RepositoryException("Failed to get ContentVersion, version does not exist");
130 }
131 this.state = thisVersion;
132 this.base = base;
133
134 this.hierarchyManager = new HierarchyManagerWrapper(base.getHierarchyManager()) {
135 private AccessManagerImpl accessManager;
136
137 {
138
139 List<Permission> permissions = new ArrayList<Permission>(getWrappedHierarchyManager().getAccessManager().getPermissionList());
140 PermissionImpl p = new PermissionImpl();
141 p.setPattern(new SimpleUrlPattern("/jcr:system/jcr:versionStorage/*"));
142
143 p.setPermissions(8);
144 permissions.add(p);
145
146 accessManager = new AccessManagerImpl();
147 accessManager.setPermissionList(permissions);
148 }
149
150 @Override
151 public AccessManager getAccessManager() {
152 return accessManager;
153 }
154 };
155 this.init();
156 }
157
158
159
160
161
162 private void init() throws RepositoryException {
163 this.setNode(this.state.getNode(ItemType.JCR_FROZENNODE));
164 try {
165 if (!StringUtils.equalsIgnoreCase(this.state.getName(), VersionManager.ROOT_VERSION)) {
166 this.rule = VersionManager.getInstance().getUsedFilter(this);
167 }
168 }
169 catch (Exception e) {
170 log.error(e.getMessage(), e);
171 }
172 if (this.rule == null) {
173 log.info("failed to get filter used for creating this version, use open filter");
174 this.rule = new Rule();
175 }
176 }
177
178
179
180
181
182
183 public Calendar getCreated() throws RepositoryException {
184 return this.state.getCreated();
185 }
186
187
188
189
190
191
192 public String getVersionLabel() throws RepositoryException {
193 return this.state.getName();
194 }
195
196
197
198
199
200
201 public VersionHistory getContainingHistory() throws RepositoryException {
202 return this.state.getContainingHistory();
203 }
204
205
206
207
208 public String getName() {
209 try {
210 return VersionManager.getInstance().getSystemNode(this).getNodeData(NAME).getString();
211 }
212 catch (RepositoryException re) {
213 log.error("Failed to retrieve name from version system node", re);
214 return "";
215 }
216 }
217
218
219
220
221 public String getUserName() {
222 try {
223 return VersionManager.getInstance().getSystemNode(this).getNodeData(VERSION_USER).getString();
224 }
225 catch (RepositoryException re) {
226 log.error("Failed to retrieve user from version system node", re);
227 return "";
228 }
229 }
230
231
232
233
234 public String getHandle() {
235 return this.base.getHandle();
236 }
237
238 public Content getContent(String name) throws PathNotFoundException, RepositoryException, AccessDeniedException {
239 return new FixParentContentWrapper(super.getContent(name), this);
240 }
241
242
243
244
245 public Content createContent(String name) throws AccessDeniedException {
246 throw new AccessDeniedException("Not allowed to write on version preview");
247 }
248
249
250
251
252 public Content createContent(String name, String contentType) throws AccessDeniedException {
253 throw new AccessDeniedException("Not allowed to write on version preview");
254 }
255
256
257
258
259 public Content createContent(String name, ItemType contentType) throws AccessDeniedException {
260 throw new AccessDeniedException("Not allowed to write on version preview");
261 }
262
263
264
265
266 public NodeData createNodeData(String name) throws AccessDeniedException {
267 throw new AccessDeniedException("Not allowed to write on version preview");
268 }
269
270
271
272
273 public NodeData createNodeData(String name, Value value, int type) throws AccessDeniedException {
274 throw new AccessDeniedException("Not allowed to write on version preview");
275 }
276
277
278
279
280 public NodeData createNodeData(String name, Value value) throws AccessDeniedException {
281 throw new AccessDeniedException("Not allowed to write on version preview");
282 }
283
284
285
286
287 public NodeData createNodeData(String name, int type) throws AccessDeniedException {
288 throw new AccessDeniedException("Not allowed to write on version preview");
289 }
290
291
292
293
294 public void deleteNodeData(String name) throws RepositoryException {
295 throw new AccessDeniedException("Not allowed to write on version preview");
296 }
297
298
299
300
301 public void updateMetaData() throws AccessDeniedException {
302 throw new AccessDeniedException("Not allowed to write on version preview");
303 }
304
305
306
307
308
309 public Collection<Content> getChildren() {
310 try {
311 if (this.rule.isAllowed(this.base.getNodeTypeName())) {
312 return wrap(super.getChildren());
313 }
314 }
315 catch (RepositoryException re) {
316 log.error(re.getMessage(), re);
317 }
318 return this.base.getChildren();
319 }
320
321
322
323
324
325
326 public Collection<Content> getChildren(String contentType) {
327 if (this.rule.isAllowed(contentType)) {
328 return wrap(super.getChildren(contentType));
329 }
330 return this.base.getChildren(contentType);
331 }
332
333
334
335
336
337
338 public Collection<Content> getChildren(ItemType contentType) {
339 return this.getChildren(contentType.getSystemName());
340 }
341
342
343
344
345
346
347
348 public Collection<Content> getChildren(String contentType, String namePattern) {
349 if (this.rule.isAllowed(contentType)) {
350 return wrap(super.getChildren(contentType, namePattern));
351 }
352 return this.base.getChildren(contentType, namePattern);
353 }
354
355 private Collection<Content> wrap(Collection<Content> children) {
356 List<Content> transformed = new ArrayList<Content>();
357 for (Content child : children) {
358 transformed.add(new FixParentContentWrapper(child, this));
359 }
360 return transformed;
361 }
362
363
364
365
366 public boolean hasChildren() {
367 return (this.getChildren().size() > 0);
368 }
369
370
371
372
373
374 public boolean hasChildren(String contentType) {
375 return (this.getChildren(contentType).size() > 0);
376 }
377
378
379
380
381 public Content getParent() throws PathNotFoundException, RepositoryException, AccessDeniedException {
382 return this.base.getParent();
383 }
384
385 public Content getAncestor(int level) throws PathNotFoundException, RepositoryException, AccessDeniedException {
386 return this.base.getAncestor(level);
387 }
388
389
390
391
392
393
394 public Collection<Content> getAncestors() throws PathNotFoundException, RepositoryException {
395 return this.base.getAncestors();
396 }
397
398
399
400
401
402
403
404 public int getLevel() throws PathNotFoundException, RepositoryException {
405 return this.base.getLevel();
406 }
407
408
409
410
411 public void orderBefore(String srcName, String beforeName) throws RepositoryException {
412 throw new AccessDeniedException("Not allowed to write on version preview");
413 }
414
415
416
417
418
419
420
421
422
423 public int getIndex() throws RepositoryException {
424 return this.base.getIndex();
425 }
426
427
428
429
430
431 public NodeType getNodeType() throws RepositoryException {
432 log.warn("This is a Version node, it will always return NT_FROZEN as node type.");
433 log.warn("Use getNodeTypeName to retrieve base node primary type");
434 return super.getNodeType();
435 }
436
437
438
439
440 public void restore(String versionName, boolean removeExisting) throws RepositoryException {
441 throw new AccessDeniedException("Not allowed to write on version preview");
442 }
443
444
445
446
447 public void restore(Version version, boolean removeExisting) throws RepositoryException {
448 throw new AccessDeniedException("Not allowed to write on version preview");
449 }
450
451
452
453
454 public void restore(Version version, String relPath, boolean removeExisting) throws RepositoryException {
455 throw new AccessDeniedException("Not allowed to write on version preview");
456 }
457
458
459
460
461 public void restoreByLabel(String versionLabel, boolean removeExisting) throws RepositoryException {
462 throw new AccessDeniedException("Not allowed to write on version preview");
463 }
464
465
466
467
468 public Version addVersion() throws RepositoryException {
469 throw new AccessDeniedException("Not allowed to add version on version preview");
470 }
471
472
473
474
475 public Version addVersion(Rule rule) throws RepositoryException {
476 throw new AccessDeniedException("Not allowed to add version on version preview");
477 }
478
479
480
481
482 public boolean isModified() {
483 log.error("Not valid for version");
484 return false;
485 }
486
487
488
489
490 public VersionHistory getVersionHistory() throws RepositoryException {
491 throw new AccessDeniedException("Not allowed to read VersionHistory of Version");
492 }
493
494
495
496
497 public VersionIterator getAllVersions() throws RepositoryException {
498 throw new AccessDeniedException("Not allowed to get VersionIterator of Version");
499 }
500
501
502
503
504 public ContentVersion getBaseVersion() throws RepositoryException {
505 throw new AccessDeniedException("Not allowed to get base version of Version");
506 }
507
508
509
510
511 public ContentVersion getVersionedContent(Version version) throws RepositoryException {
512 throw new AccessDeniedException("Not allowed to get preview of Version itself");
513 }
514
515
516
517
518 public ContentVersion getVersionedContent(String versionName) throws RepositoryException {
519 throw new AccessDeniedException("Not allowed to get preview of Version itself");
520 }
521
522
523
524
525 public void save() throws RepositoryException {
526 throw new AccessDeniedException("Not allowed to write on version preview");
527 }
528
529
530
531
532
533
534 public boolean isGranted(long permissions) {
535 return (permissions & Permission.READ) == permissions;
536 }
537
538
539
540
541 public void delete() throws RepositoryException {
542 throw new AccessDeniedException("Not allowed to write on version preview");
543 }
544
545
546
547
548 public void delete(String path) throws RepositoryException {
549 throw new AccessDeniedException("Not allowed to write on version preview");
550 }
551
552
553
554
555
556 public String getUUID() {
557 return this.base.getUUID();
558 }
559
560
561
562
563 public void addMixin(String type) throws RepositoryException {
564 throw new AccessDeniedException("Not allowed to write on version preview");
565 }
566
567
568
569
570 public void removeMixin(String type) throws RepositoryException {
571 throw new AccessDeniedException("Not allowed to write on version preview");
572 }
573
574
575
576
577 public Lock lock(boolean isDeep, boolean isSessionScoped) throws LockException, RepositoryException {
578 throw new AccessDeniedException("Lock not supported on version preview");
579 }
580
581
582
583
584 public Lock lock(boolean isDeep, boolean isSessionScoped, long yieldFor) throws LockException, RepositoryException {
585 throw new AccessDeniedException("Lock not supported on version preview");
586 }
587
588
589
590
591 public Lock getLock() throws LockException, RepositoryException {
592 throw new AccessDeniedException("Lock not supported on version preview");
593 }
594
595
596
597
598 public void unlock() throws LockException, RepositoryException {
599 throw new AccessDeniedException("Lock not supported on version preview");
600 }
601
602
603
604
605 public boolean holdsLock() throws RepositoryException {
606 throw new AccessDeniedException("Lock not supported on version preview");
607 }
608
609
610
611
612 public boolean isLocked() throws RepositoryException {
613 throw new AccessDeniedException("Lock not supported on version preview");
614 }
615
616
617
618
619
620 public HierarchyManager getHierarchyManager() {
621 return this.base.getHierarchyManager();
622 }
623
624
625
626
627
628
629 public AccessManager getAccessManager() {
630 return this.base.getAccessManager();
631 }
632
633 @Override
634 public Workspace getWorkspace() throws RepositoryException {
635 return this.base.getWorkspace();
636 }
637
638 @Override
639 public boolean hasNodeData(String name) throws RepositoryException {
640 if (this.node.hasProperty(name)) {
641 return true;
642 }
643 else {
644 if (this.node.hasNode(name) && this.node.getNode(name).getProperty("jcr:frozenPrimaryType").getValue().getString().equals(ItemType.NT_RESOURCE)) {
645 return true;
646 }
647 }
648 return false;
649 }
650
651 @Override
652 protected int determineNodeDataType(String name) {
653
654 try {
655 if (this.node.hasProperty(name)) {
656 return this.node.getProperty(name).getType();
657 }
658 else {
659 if (this.node.hasNode(name) && this.node.getNode(name).getProperty("jcr:frozenPrimaryType").getValue().getString().equals(ItemType.NT_RESOURCE)) {
660 return PropertyType.BINARY;
661 }
662 }
663 }
664 catch (RepositoryException e) {
665 throw new IllegalStateException("Can't determine property type of [" + getHandle() + "/" + name + "]", e);
666 }
667 return PropertyType.UNDEFINED;
668 }
669
670
671 }