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.search.QueryManager;
37 import info.magnolia.cms.security.AccessDeniedException;
38 import info.magnolia.cms.security.AccessManager;
39 import info.magnolia.cms.security.Permission;
40 import info.magnolia.cms.util.WorkspaceAccessUtil;
41 import info.magnolia.cms.beans.config.ContentRepository;
42 import info.magnolia.logging.AuditLoggingUtil;
43
44 import java.util.Collection;
45 import java.io.ObjectStreamField;
46 import java.io.Serializable;
47
48 import javax.jcr.PathNotFoundException;
49 import javax.jcr.RepositoryException;
50 import javax.jcr.Node;
51 import javax.jcr.Session;
52 import javax.jcr.Workspace;
53 import javax.jcr.ItemNotFoundException;
54
55 import org.apache.commons.lang.StringUtils;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59
60
61
62
63
64
65
66 public class DefaultHierarchyManager implements HierarchyManager, Serializable {
67
68 private static final long serialVersionUID = 223L;
69
70
71
72
73
74 private static final ObjectStreamField[] serialPersistentFields = {
75 new ObjectStreamField("userId", String.class),
76 new ObjectStreamField("repositoryName", String.class),
77 new ObjectStreamField("workspaceName", String.class),
78 new ObjectStreamField("accessManager", AccessManager.class)
79 };
80
81 private static final Logger log = LoggerFactory.getLogger(DefaultHierarchyManager.class);
82
83 private Node rootNode;
84
85 private Workspace workspace;
86
87 private Session jcrSession;
88
89 private QueryManager queryManager;
90
91
92
93
94 private String userId;
95
96 private String repositoryName;
97
98 private String workspaceName;
99
100 private AccessManager accessManager;
101
102 protected DefaultHierarchyManager() {}
103
104 public DefaultHierarchyManager(String userId, Session jcrSession, AccessManager aManager) throws RepositoryException {
105 this.userId = userId;
106 this.jcrSession = jcrSession;
107 this.rootNode = jcrSession.getRootNode();
108 this.workspace = jcrSession.getWorkspace();
109 this.workspaceName = this.workspace.getName();
110 this.repositoryName = ContentRepository.getParentRepositoryName(this.workspaceName);
111 this.accessManager = aManager;
112 }
113
114
115
116
117 private void reInitialize() {
118 WorkspaceAccessUtil util = WorkspaceAccessUtil.getInstance();
119 try {
120 this.jcrSession = util.createRepositorySession(util.getDefaultCredentials(), this.repositoryName, this.workspaceName);
121 this.queryManager = util.createQueryManager(this.jcrSession, this);
122 this.rootNode = this.jcrSession.getRootNode();
123 this.workspace = this.jcrSession.getWorkspace();
124 } catch (RepositoryException re) {
125 log.error("Failed to load HierarchyManager from persistent storage", re);
126 }
127 }
128
129
130
131
132
133 protected void setAccessManager(AccessManager accessManager) {
134 this.accessManager = accessManager;
135 }
136
137
138
139
140
141 public AccessManager getAccessManager() {
142 return this.accessManager;
143 }
144
145
146
147
148
149 protected void setQueryManager(QueryManager queryManager) {
150 this.queryManager = queryManager;
151 }
152
153 public QueryManager getQueryManager() {
154 if (null == this.queryManager) {
155 WorkspaceAccessUtil util = WorkspaceAccessUtil.getInstance();
156 try {
157 this.queryManager = util.createQueryManager(this.jcrSession, this);
158 } catch (RepositoryException e) {
159 reInitialize();
160 }
161 }
162 return this.queryManager;
163 }
164
165 private Node getRootNode() {
166 if (null == this.rootNode) {
167 reInitialize();
168 }
169 return this.rootNode;
170 }
171
172 private Session getJcrSession() {
173 log.debug("Accessing JCR session from {}", Thread.currentThread().getName());
174 if (null == this.jcrSession) {
175 reInitialize();
176 }
177 return this.jcrSession;
178 }
179
180
181
182
183
184
185
186
187
188
189
190 public Content createContent(String path, String label, String contentType) throws PathNotFoundException, RepositoryException, AccessDeniedException {
191 Content content = new DefaultContent(this.getRootNode(), this.getNodePath(path, label), contentType, this);
192 setMetaData(content.getMetaData());
193 AuditLoggingUtil.log( AuditLoggingUtil.ACTION_CREATE, workspaceName, content.getItemType(), content.getHandle());
194 return content;
195 }
196
197 private String getNodePath(String parent, String label) {
198 if (StringUtils.isEmpty(parent) || (parent.equals("/"))) {
199 return label;
200 }
201 if (!parent.endsWith("/")) {
202 parent = parent + "/";
203 }
204 return getNodePath(parent + label);
205 }
206
207 private String getNodePath(String path) {
208 if (path != null && path.startsWith("/")) {
209 return path.replaceFirst("/", StringUtils.EMPTY);
210 }
211 return path;
212 }
213
214
215
216
217
218 protected void setMetaData(MetaData md) throws RepositoryException, AccessDeniedException {
219 md.setCreationDate();
220 md.setModificationDate();
221 md.setAuthorId(this.userId);
222 md.setTitle(StringUtils.EMPTY);
223 }
224
225
226
227
228
229
230
231
232 public Content getContent(String path) throws PathNotFoundException, RepositoryException, AccessDeniedException {
233 if (path.equals("/")) {
234 return this.getRoot();
235 }
236 return (new DefaultContent(this.getRootNode(), getNodePath(path), this));
237 }
238
239
240
241
242
243
244
245
246
247
248 public Content getContent(String path, boolean create, ItemType type) throws AccessDeniedException, RepositoryException {
249 Content node;
250 try {
251 node = getContent(path);
252 }
253 catch (PathNotFoundException e) {
254 if (create) {
255 node = this.createContent(StringUtils.substringBeforeLast(path, "/"), StringUtils.substringAfterLast( path, "/"), type.toString());
256 AuditLoggingUtil.log( AuditLoggingUtil.ACTION_CREATE, workspaceName, node.getItemType(), node.getHandle());
257 }
258 else {
259 throw e;
260 }
261 }
262 return node;
263 }
264
265
266
267
268
269
270
271
272
273 public NodeData getNodeData(String path) throws PathNotFoundException, RepositoryException, AccessDeniedException {
274 if (StringUtils.isEmpty(path)) {
275 return null;
276 }
277 final String nodePath = StringUtils.substringBeforeLast(path, "/");
278 final String nodeDataName = StringUtils.substringAfterLast(path, "/");
279 return getContent(nodePath).getNodeData(nodeDataName);
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293 @Deprecated
294 public Content getPage(String path, String templateName) throws PathNotFoundException, RepositoryException, AccessDeniedException {
295 Content page = getContent(path);
296 if (page.getTemplate().equals(templateName)) {
297 return page;
298 }
299 Content pageToBeFound = null;
300 try {
301 if (page.hasChildren()) {
302 Collection<Content> children = page.getChildren(ItemType.CONTENT.getSystemName());
303 for (Content child : children) {
304 if (child.getTemplate().equals(templateName)) {
305 return child;
306 }
307 if (child.hasChildren()) {
308 pageToBeFound = getPage(child.getHandle(), templateName);
309 }
310 if (pageToBeFound != null) {
311 return pageToBeFound;
312 }
313 }
314 }
315 }
316 catch (Exception e) {
317 log.error("Failed to get - " + path + " : " + e.getMessage(), e);
318 }
319 return pageToBeFound;
320 }
321
322
323
324
325
326
327
328
329 public void delete(String path) throws PathNotFoundException, RepositoryException, AccessDeniedException {
330 Access.isGranted(this.accessManager, path, Permission.REMOVE);
331 ItemType type = null;
332 if (this.isNodeData(path)) {
333 this.getNodeData(makeRelative(path)).delete();
334 }
335 else {
336 Node aNode = this.getRootNode().getNode(makeRelative(path));
337 if (aNode.hasProperty(ItemType.JCR_FROZEN_PRIMARY_TYPE)) {
338 type = new ItemType(aNode.getProperty(ItemType.JCR_FROZEN_PRIMARY_TYPE).getString());
339 }
340 type = new ItemType(aNode.getProperty(ItemType.JCR_PRIMARY_TYPE).getString());
341 aNode.remove();
342 }
343 AuditLoggingUtil.log( AuditLoggingUtil.ACTION_DELETE, workspaceName, type, path);
344 }
345
346 private String makeRelative(String path) {
347 return StringUtils.stripStart(path, "/");
348 }
349
350
351
352
353 public Content getRoot() throws RepositoryException, AccessDeniedException {
354 return (new DefaultContent(this.getRootNode(), this));
355 }
356
357
358
359
360
361
362
363
364 @Deprecated
365 public boolean isPage(String path) throws AccessDeniedException {
366 Access.isGranted(this.accessManager, path, Permission.READ);
367
368 String nodePath = getNodePath(path);
369 if (StringUtils.isEmpty(nodePath)) {
370 return false;
371 }
372
373 try {
374 Node n = this.getRootNode().getNode(nodePath);
375 return (n.isNodeType(ItemType.CONTENT.getSystemName()));
376 }
377 catch (RepositoryException re) {
378
379 }
380 return false;
381 }
382
383
384
385
386
387
388 public boolean isExist(String path) {
389 try {
390 Access.isGranted(this.accessManager, path, Permission.READ);
391 } catch (AccessDeniedException e) {
392 log.error(e.getMessage());
393 return false;
394 }
395 try {
396 return this.getJcrSession().itemExists(path);
397 }
398 catch (RepositoryException re) {
399 log.error("Exception caught", re);
400 return false;
401 }
402 }
403
404 public boolean isGranted(String path, long permissions) {
405 try {
406 Access.isGranted(this.accessManager, path, permissions);
407 } catch (AccessDeniedException e) {
408 return false;
409 }
410 return true;
411 }
412
413
414
415
416
417 @Deprecated
418 public boolean isNodeType(String path, String type) {
419 try {
420 Node n = this.getRootNode().getNode(getNodePath(path));
421 return n.isNodeType(type);
422 }
423 catch (RepositoryException re) {
424 log.error(re.getMessage());
425 log.debug(re.getMessage(), re);
426 }
427 return false;
428 }
429
430
431
432
433
434 @Deprecated
435 public boolean isNodeType(String path, ItemType type) {
436 return isNodeType(path, type.getSystemName());
437 }
438
439
440
441
442
443
444 public boolean isNodeData(String path) throws AccessDeniedException {
445 Access.isGranted(this.accessManager, path, Permission.READ);
446 boolean result = false;
447 String nodePath = getNodePath(path);
448 if (StringUtils.isEmpty(nodePath)) {
449 return false;
450 }
451 try {
452 result = this.getRootNode().hasProperty(nodePath);
453 if (!result) {
454
455 result = this.getRootNode().hasProperty(nodePath + "/" + ItemType.JCR_DATA);
456 }
457 }
458 catch (RepositoryException e) {
459
460 }
461 return result;
462 }
463
464
465
466
467
468
469 public Content getContentByUUID(String uuid) throws ItemNotFoundException, RepositoryException, AccessDeniedException {
470 return new DefaultContent(this.getJcrSession().getNodeByUUID(uuid), this);
471 }
472
473
474
475
476 public Workspace getWorkspace() {
477 if (null == this.workspace) {
478 reInitialize();
479 }
480 return this.workspace;
481 }
482
483
484
485
486
487
488
489
490 public void moveTo(String source, String destination) throws PathNotFoundException, RepositoryException, AccessDeniedException {
491 Access.isGranted(this.accessManager, source, Permission.REMOVE);
492 Access.isGranted(this.accessManager, destination, Permission.WRITE);
493 this.getWorkspace().move(source, destination);
494 AuditLoggingUtil.log( AuditLoggingUtil.ACTION_MOVE, workspaceName, source, destination);
495 }
496
497
498
499
500
501
502
503
504 public void copyTo(String source, String destination) throws PathNotFoundException, RepositoryException, AccessDeniedException {
505 Access.isGranted(this.accessManager, source, Permission.READ);
506 Access.isGranted(this.accessManager, destination, Permission.WRITE);
507 this.getWorkspace().copy(source, destination);
508 AuditLoggingUtil.log( AuditLoggingUtil.ACTION_COPY, workspaceName, source, destination);
509 }
510
511
512
513
514
515 public void save() throws RepositoryException {
516 try {
517 this.getJcrSession().save();
518 }
519 catch (RepositoryException re) {
520 log.error(re.getMessage(), re);
521 throw re;
522 }
523 }
524
525
526
527
528 public boolean hasPendingChanges() throws RepositoryException {
529 return this.getJcrSession().hasPendingChanges();
530 }
531
532
533
534
535
536
537
538 public void refresh(boolean keepChanges) throws RepositoryException {
539 this.getJcrSession().refresh(keepChanges);
540 }
541
542 public String getName() {
543 return this.workspaceName;
544 }
545
546 }