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.jcr.wrapper;
35
36 import info.magnolia.cms.security.JCRSessionOp;
37 import info.magnolia.context.Context;
38 import info.magnolia.context.MgnlContext;
39 import info.magnolia.context.SystemContext;
40 import info.magnolia.jcr.decoration.ContentDecorator;
41 import info.magnolia.jcr.decoration.ContentDecoratorPropertyWrapper;
42 import info.magnolia.jcr.decoration.ContentDecoratorSessionWrapper;
43 import info.magnolia.jcr.decoration.ContentDecoratorWorkspaceWrapper;
44 import info.magnolia.jcr.util.NodeTypes;
45 import info.magnolia.jcr.util.NodeTypes.LastModified;
46 import info.magnolia.jcr.util.NodeUtil;
47 import info.magnolia.repository.RepositoryConstants;
48
49 import java.io.InputStream;
50 import java.math.BigDecimal;
51 import java.util.ArrayList;
52 import java.util.Calendar;
53 import java.util.LinkedList;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Stack;
57
58 import javax.jcr.AccessDeniedException;
59 import javax.jcr.Binary;
60 import javax.jcr.InvalidItemStateException;
61 import javax.jcr.ItemExistsException;
62 import javax.jcr.NoSuchWorkspaceException;
63 import javax.jcr.Node;
64 import javax.jcr.NodeIterator;
65 import javax.jcr.PathNotFoundException;
66 import javax.jcr.Property;
67 import javax.jcr.ReferentialIntegrityException;
68 import javax.jcr.RepositoryException;
69 import javax.jcr.Session;
70 import javax.jcr.Value;
71 import javax.jcr.ValueFormatException;
72 import javax.jcr.Workspace;
73 import javax.jcr.lock.LockException;
74 import javax.jcr.nodetype.ConstraintViolationException;
75 import javax.jcr.nodetype.NoSuchNodeTypeException;
76 import javax.jcr.version.VersionException;
77
78 import org.apache.commons.lang3.StringUtils;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
81
82 import com.google.common.collect.ImmutableList;
83 import com.google.common.collect.ImmutableMap;
84
85
86
87
88
89
90 public class MgnlPropertySettingContentDecorator extends PropertyAndChildWrappingContentDecorator implements ContentDecorator {
91
92
93
94
95
96 private class DirtyOp {
97
98 private String path;
99 private String userName;
100 private Calendar updateDate;
101
102 public DirtyOp(String path, String userName, Calendar updateDate) {
103 this.path = path;
104 this.userName = userName;
105 this.updateDate = updateDate;
106 }
107
108 public String getPath() {
109 return path;
110 }
111
112 public void setPath(String path) {
113 this.path = path;
114 }
115
116 public String getUserName() {
117 return userName;
118 }
119
120 public Calendar getUpdateDate() {
121 return updateDate;
122 }
123
124 }
125
126 private static final Logger log = LoggerFactory.getLogger(MgnlPropertySettingContentDecorator.class);
127
128
129
130
131 private static final ImmutableList<String> SPECIAL_PROPERTY_NAMES = ImmutableList.of(
132 NodeTypes.MGNL_PREFIX + "variantTitle",
133 NodeTypes.MGNL_PREFIX + "variationOf",
134 NodeTypes.MGNL_PREFIX + "assignedSegments",
135 NodeTypes.Renderable.TEMPLATE
136 );
137
138
139
140
141
142 private static Map<String, String> PARENT_NODE_MAPPINGS = ImmutableMap.of(RepositoryConstants.WEBSITE, NodeTypes.Page.NAME,
143 RepositoryConstants.USERS, NodeTypes.User.NAME);
144
145 protected List<DirtyOp> dirtyOps = new LinkedList<>();
146
147
148
149
150
151 final class ChangeLastUpdateDateOp extends MgnlContext.RepositoryOp {
152 private final String workspaceName;
153 private final String userName;
154 private final String destAbsPath;
155 private final Calendar updateDate;
156 private final boolean recursiveDown;
157
158 ChangeLastUpdateDateOp(String workspaceName, String userName, String destAbsPath, Calendar updateDate, boolean recursiveDown) {
159 this.workspaceName = workspaceName;
160 this.userName = userName;
161 this.destAbsPath = destAbsPath;
162 this.updateDate = updateDate;
163 this.recursiveDown = recursiveDown;
164 }
165
166 @Override
167 public void doExec() throws RepositoryException {
168 Session sysSession = MgnlContext.getJCRSession(workspaceName);
169
170
171 if (!sysSession.itemExists(destAbsPath)) {
172
173 if (log.isDebugEnabled()) {
174 log.warn("Can't update mgnl:lastModified. Path {}:{} doesn't exist anymore.", workspaceName, destAbsPath);
175 }
176 return;
177 }
178 String srcAbsPath = sysSession.getNode(destAbsPath).getPath();
179
180 Stack<Node> nodes = resolveNodesToModify(destAbsPath, sysSession);
181 Node node;
182 if (!nodes.isEmpty()) {
183 node = nodes.pop();
184 } else {
185
186 node = sysSession.getNode(destAbsPath);
187 }
188
189 if (node.isNodeType(NodeTypes.MetaData.NAME)) {
190
191 return;
192 }
193
194
195 if (node.getDepth() == 0) {
196 return;
197 }
198
199
200 if (node instanceof DelegateNodeWrapper) {
201 node = ((DelegateNodeWrapper) node).deepUnwrap(MgnlPropertySettingNodeWrapper.class);
202 }
203
204 log.debug("LUD on {} from {}:{}", node.getPath(), node.getSession().toString(), Thread.currentThread().getName());
205 if (node.isNodeType(LastModified.NAME)) {
206 String resolvedPath = node.getPath();
207 if (!destAbsPath.equals(srcAbsPath)) {
208
209 if (!resolvedPath.equals(srcAbsPath) && !resolvedPath.equals(destAbsPath)) {
210
211 if (srcAbsPath.startsWith(resolvedPath)) {
212 String hunk = StringUtils.substringAfter(srcAbsPath, resolvedPath);
213 if (destAbsPath.endsWith(hunk)) {
214 resolvedPath = StringUtils.substringBefore(destAbsPath, hunk);
215 }
216 } else {
217 resolvedPath = destAbsPath;
218 }
219 }
220 }
221
222 dirtyOps.add(new DirtyOp(resolvedPath, userName, updateDate));
223 }
224
225
226 while (!nodes.isEmpty()) {
227 Node child = nodes.pop();
228 if (child.isNodeType(LastModified.NAME)) {
229 dirtyOps.add(new DirtyOp(child.getPath(), userName, updateDate));
230 }
231 }
232
233 if (recursiveDown) {
234
235 List<NodeIterator> iters = new ArrayList<>();
236 iters.add(node.getNodes());
237 while (!iters.isEmpty()) {
238 List<NodeIterator> tmp = updateChildren(node.getPath(), destAbsPath, iters, updateDate);
239 iters.clear();
240 iters.addAll(tmp);
241 }
242 }
243
244
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259 private Stack<Node> resolveNodesToModify(String destAbsPath, Session sysSession) throws RepositoryException {
260 Stack<Node> nodeStack = new Stack<>();
261
262 String parentNodeType = PARENT_NODE_MAPPINGS.get(workspaceName);
263 Node node = sysSession.getNode(destAbsPath);
264 if (parentNodeType == null) {
265 return nodeStack;
266 }
267 while (node != null && !parentNodeType.equals(node.getPrimaryNodeType().getName()) && node.getDepth() > 0) {
268 nodeStack.add(node);
269 node = node.getParent();
270 }
271 nodeStack.add(node);
272 return nodeStack;
273 }
274
275 private List<NodeIterator> updateChildren(String srcAbsPath, String destAbsPath, List<NodeIterator> iters, Calendar updateDate) {
276 List<NodeIterator> tmp = new ArrayList<>();
277 for (NodeIterator iter : iters) {
278 while (iter.hasNext()) {
279 Node node = iter.nextNode();
280 try {
281 if (skipTypeInWorkspace(workspaceName, node.getPrimaryNodeType().getName())) {
282
283 continue;
284 }
285 if (node.isNodeType(NodeTypes.MetaData.NAME)) {
286
287 continue;
288 }
289 if (node.isNodeType(LastModified.NAME)) {
290 dirtyOps.add(new DirtyOp(destAbsPath + StringUtils.removeStart(node.getPath(), srcAbsPath), userName, updateDate));
291 }
292 tmp.add(node.getNodes());
293 } catch (RepositoryException e) {
294 log.error("Failed to update last modified date of {} with {}", node, e.getMessage(), e);
295 }
296 }
297 }
298 return tmp;
299 }
300
301 private boolean skipTypeInWorkspace(String workspaceName, String name) {
302 if (RepositoryConstants.USER_ROLES.equals(workspaceName)) {
303 return !(NodeTypes.Role.NAME.equals(name) || NodeTypes.Folder.NAME.equals(name));
304 }
305 if (RepositoryConstants.WEBSITE.equals(workspaceName)) {
306 return !NodeTypes.Page.NAME.equals(name);
307 }
308 return false;
309 }
310
311 }
312
313
314
315
316 public class LastUpdatePropertyWrapper extends ContentDecoratorPropertyWrapper<MgnlPropertySettingContentDecorator> implements Property {
317
318 public LastUpdatePropertyWrapper(Property property, MgnlPropertySettingContentDecorator contentDecorator) {
319 super(property, contentDecorator);
320 }
321
322 @Override
323 public void setValue(BigDecimal value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
324 String parentPath = this.getParent().getPath();
325 String propertyName = this.getName();
326 super.setValue(value);
327 updateLastModifiedProperty(propertyName, parentPath);
328 }
329
330 @Override
331 public void setValue(Binary value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
332 String parentPath = this.getParent().getPath();
333 String propertyName = this.getName();
334 super.setValue(value);
335 updateLastModifiedProperty(propertyName, parentPath);
336 }
337
338 @Override
339 public void setValue(boolean value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
340 String parentPath = this.getParent().getPath();
341 String propertyName = this.getName();
342 super.setValue(value);
343 updateLastModifiedProperty(propertyName, parentPath);
344 }
345
346 @Override
347 public void setValue(Calendar value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
348 String parentPath = this.getParent().getPath();
349 String propertyName = this.getName();
350 super.setValue(value);
351 updateLastModifiedProperty(propertyName, parentPath);
352 }
353
354 @Override
355 public void setValue(double value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
356 String parentPath = this.getParent().getPath();
357 String propertyName = this.getName();
358 super.setValue(value);
359 updateLastModifiedProperty(propertyName, parentPath);
360 }
361
362 @Override
363 public void setValue(InputStream value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
364 String parentPath = this.getParent().getPath();
365 String propertyName = this.getName();
366 super.setValue(value);
367 updateLastModifiedProperty(propertyName, parentPath);
368 }
369
370 @Override
371 public void setValue(long value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
372 String parentPath = this.getParent().getPath();
373 String propertyName = this.getName();
374 super.setValue(value);
375 updateLastModifiedProperty(propertyName, parentPath);
376 }
377
378 @Override
379 public void setValue(Node value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
380 String parentPath = this.getParent().getPath();
381 String propertyName = this.getName();
382 super.setValue(value);
383 updateLastModifiedProperty(propertyName, parentPath);
384 }
385
386 @Override
387 public void setValue(String value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
388 String parentPath = this.getParent().getPath();
389 String propertyName = this.getName();
390 super.setValue(value);
391 updateLastModifiedProperty(propertyName, parentPath);
392 }
393
394 @Override
395 public void setValue(String[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
396 String parentPath = this.getParent().getPath();
397 String propertyName = this.getName();
398 super.setValue(values);
399 updateLastModifiedProperty(propertyName, parentPath);
400 }
401
402 @Override
403 public void setValue(Value value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
404 String parentPath = this.getParent().getPath();
405 String propertyName = this.getName();
406 super.setValue(value);
407 updateLastModifiedProperty(propertyName, parentPath);
408 }
409
410 @Override
411 public void setValue(Value[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
412 String parentPath = this.getParent().getPath();
413 String propertyName = this.getName();
414 super.setValue(values);
415 updateLastModifiedProperty(propertyName, parentPath);
416 }
417
418 @Override
419 public void remove() throws VersionException, LockException, ConstraintViolationException, AccessDeniedException, RepositoryException {
420 String parentPath = this.getParent().getPath();
421 String propertyName = this.getName();
422 super.remove();
423
424 updateLastModifiedProperty(propertyName, parentPath);
425 }
426
427 private void updateLastModifiedProperty(String propertyName, String parentPath) throws RepositoryException {
428 getContentDecorator().updateLastModifiedProperty(getSession().getWorkspace().getName(), propertyName, parentPath);
429 }
430 }
431
432
433
434
435
436
437 public class LastUpdateWorkspaceWrapper extends MgnlPropertySettingWorkspaceWrapper {
438
439 protected LastUpdateWorkspaceWrapper(final Workspace workspace, final ContentDecorator contentDecorator) {
440 super(workspace, contentDecorator);
441 }
442 }
443
444
445
446
447 public class MgnlPropertySettingWorkspaceWrapper extends ContentDecoratorWorkspaceWrapper implements Workspace {
448
449 protected MgnlPropertySettingWorkspaceWrapper(final Workspace workspace, final ContentDecorator contentDecorator) {
450 super(workspace, contentDecorator);
451 }
452
453 @Override
454 public void move(String srcAbsPath, String destAbsPath) throws ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
455 super.move(srcAbsPath, destAbsPath);
456 updateLastModified(super.getWrappedWorkspace().getSession(), destAbsPath, true);
457 }
458
459 @Override
460 public void copy(String srcAbsPath, String destAbsPath) throws ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
461 super.copy(srcAbsPath, destAbsPath);
462 final String workspaceName = super.getWrappedWorkspace().getName();
463 setCreatedDate(workspaceName, destAbsPath, true);
464 final String user = getCurrentUserName();
465 NodeUtil.visit(getSession().getNode(destAbsPath), node -> updateActivationStatus(node, user));
466 getSession().save();
467 }
468
469 @Override
470 public void copy(String srcWorkspace, String srcAbsPath, String destAbsPath) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
471 super.copy(srcWorkspace, srcAbsPath, destAbsPath);
472 final String workspaceName = super.getWrappedWorkspace().getName();
473 setCreatedDate(workspaceName, destAbsPath, true);
474 final String user = getCurrentUserName();
475 NodeUtil.visit(getSession().getNode(destAbsPath), node -> updateActivationStatus(node, user));
476 getSession().save();
477 }
478
479 @Override
480 public void clone(String srcWorkspace, String srcAbsPath, String destAbsPath, boolean removeExisting) throws NoSuchWorkspaceException, ConstraintViolationException, VersionException, AccessDeniedException, PathNotFoundException, ItemExistsException, LockException, RepositoryException {
481 super.clone(srcWorkspace, srcAbsPath, destAbsPath, removeExisting);
482
483 }
484
485 }
486
487
488
489
490
491
492 public class LastUpdateSessionWrapper extends MgnlPropertySettingSessionWrapper {
493 public LastUpdateSessionWrapper(final Session session, final MgnlPropertySettingContentDecorator contentDecorator) {
494 super(session, contentDecorator);
495 }
496 }
497
498
499
500
501 public class MgnlPropertySettingSessionWrapper extends ContentDecoratorSessionWrapper<MgnlPropertySettingContentDecorator> implements Session {
502
503 public MgnlPropertySettingSessionWrapper(Session session, MgnlPropertySettingContentDecorator contentDecorator) {
504 super(session, contentDecorator);
505 }
506
507 @Override
508 public void move(final String srcAbsPath, final String destAbsPath) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, RepositoryException {
509 super.move(srcAbsPath, destAbsPath);
510
511 boolean onSourcePath = MgnlContext.doInSystemContext(new JCRSessionOp<Boolean>(super.getWrappedSession().getWorkspace().getName()) {
512 @Override
513 public Boolean exec(Session session) throws RepositoryException {
514 return session.itemExists(srcAbsPath);
515 }
516 });
517 String aPath = onSourcePath ? srcAbsPath : destAbsPath;
518 updateLastModified(super.getWrappedSession(), aPath, true);
519 if (onSourcePath) {
520 for (DirtyOp op : dirtyOps) {
521 if (op.getPath().equals(srcAbsPath) || op.getPath().startsWith(srcAbsPath + "/")) {
522 op.setPath(destAbsPath + StringUtils.substringAfter(op.getPath(), srcAbsPath));
523 }
524 }
525 }
526 }
527
528 @Override
529 public void save() throws AccessDeniedException, ItemExistsException, ReferentialIntegrityException, ConstraintViolationException, InvalidItemStateException, VersionException, LockException, NoSuchNodeTypeException, RepositoryException {
530 String workspaceName = wrapped.getWorkspace().getName();
531 try {
532 log.debug("saving session: {}::{}::sys:{}::{}", wrapped.toString(), workspaceName, MgnlContext.isSystemInstance(), Thread.currentThread().getName());
533 super.save();
534 } catch (InvalidItemStateException e) {
535 log.error("Failed to update LUD for session: {}::{}", wrapped.toString(), workspaceName, e);
536 throw e;
537 }
538 if (!dirtyOps.isEmpty()) {
539 Session sysSession = MgnlContext.getSystemContext().getJCRSession(workspaceName);
540 if (sysSession instanceof DelegateSessionWrapper) {
541 sysSession = ((DelegateSessionWrapper) sysSession).deepUnwrap(MgnlPropertySettingSessionWrapper.class);
542 }
543 applyPendingChanges(sysSession);
544 sysSession.save();
545 }
546 }
547
548 protected void applyPendingChanges(Session session) throws RepositoryException, PathNotFoundException {
549 while (!dirtyOps.isEmpty()) {
550 DirtyOp dirty = dirtyOps.remove(0);
551 if (session.nodeExists(dirty.getPath())) {
552 log.debug("Updating {} with {}", dirty.getPath(), dirty.getUpdateDate());
553 LastModified.update(session.getNode(dirty.getPath()), dirty.getUserName(), dirty.getUpdateDate());
554 } else {
555
556 if (log.isDebugEnabled()) {
557 log.warn("wanted to update {}:{} modified by:{} at {} but it's gone now.", session.getWorkspace().getName(), dirty.getPath(), dirty.getUserName(), dirty.getUpdateDate());
558 }
559 }
560 }
561 }
562
563 }
564
565 @Override
566 public Session wrapSession(Session session) {
567 return new MgnlPropertySettingSessionWrapper(session, this);
568 }
569
570 @Override
571 public Workspace wrapWorkspace(Workspace workspace) {
572 return new MgnlPropertySettingWorkspaceWrapper(workspace, this);
573 }
574
575 @Override
576 public Node wrapNode(Node node) {
577 return new MgnlPropertySettingNodeWrapper(node, this);
578 }
579
580 @Override
581 public Property wrapProperty(Property property) {
582 return new LastUpdatePropertyWrapper(property, this);
583 }
584
585 void updateLastModified(final Session session, final String destAbsPath, final boolean recursiveDown) throws RepositoryException, PathNotFoundException {
586 this.updateLastModified(session.getWorkspace().getName(), destAbsPath, recursiveDown);
587 }
588
589 void updateLastModified(final String workspaceName, final String destAbsPath, final boolean recursiveDown) throws RepositoryException, PathNotFoundException {
590
591 if ("/".equals(destAbsPath) && !recursiveDown) {
592
593 return;
594 }
595
596 final Calendar updateDate = Calendar.getInstance();
597
598
599 MgnlContext.doInSystemContext(new ChangeLastUpdateDateOp(workspaceName, getCurrentUserName(), destAbsPath, updateDate, recursiveDown));
600
601 }
602
603 void updateLastModified(String workspaceName, String destAbsPath) throws RepositoryException, PathNotFoundException {
604 updateLastModified(workspaceName, destAbsPath, false);
605 }
606
607 void updateLastModified(Session session, String destAbsPath) throws RepositoryException, PathNotFoundException {
608 updateLastModified(session, destAbsPath, false);
609 }
610
611 void updateLastModifiedProperty(String workspaceName, String propertyName, String parentPath) throws RepositoryException {
612 if (shouldIgnoreUpdate(propertyName)) {
613 return;
614 }
615 updateLastModified(workspaceName, parentPath);
616 }
617
618 void setCreatedDate(final String workspaceName, final String absPath) throws RepositoryException {
619 setCreatedDate(workspaceName, absPath, false);
620 }
621
622 void setCreatedDate(final String workspaceName, final String absPath, final boolean recursiveDown) throws RepositoryException {
623 final Session session = MgnlContext.getJCRSession(workspaceName);
624
625
626 if (!session.itemExists(absPath)) {
627
628 if (log.isDebugEnabled()) {
629 log.warn("Can't update {}. Path {}:{} does not exist.", NodeTypes.Created.NAME, workspaceName, absPath);
630 }
631 return;
632 }
633 Node node = session.getNode(absPath);
634
635
636 if (node == null) {
637 return;
638 }
639
640
641 if (node.getDepth() == 0) {
642 return;
643 }
644
645
646 if (node instanceof DelegateNodeWrapper) {
647 node = ((DelegateNodeWrapper) node).deepUnwrap(MgnlPropertySettingNodeWrapper.class);
648 }
649
650 final String user = getCurrentUserName();
651
652
653 final Calendar now = Calendar.getInstance();
654
655 if (node.isNodeType(NodeTypes.Created.NAME)) {
656 log.debug("Setting {} on {} from {}:{}", NodeTypes.Created.NAME, node.getPath(), node.getSession().toString(), Thread.currentThread().getName());
657 NodeTypes.Created.set(node, user, now);
658 }
659
660 if (recursiveDown) {
661
662 List<NodeIterator> iters = new ArrayList<>();
663 iters.add(node.getNodes());
664 while (!iters.isEmpty()) {
665 List<NodeIterator> tmp = updateChildren(iters, user, now);
666 iters.clear();
667 iters.addAll(tmp);
668 }
669 }
670 }
671
672 private void updateActivationStatus(Node node, String userName) throws RepositoryException {
673 if (NodeUtil.isNodeType(node, NodeTypes.Activatable.NAME)) {
674 NodeTypes.Activatable.update(node, userName, false);
675 }
676 }
677
678 private List<NodeIterator> updateChildren(final List<NodeIterator> iters, final String user, final Calendar updateDate) {
679 List<NodeIterator> tmp = new ArrayList<>();
680 for (NodeIterator iterator : iters) {
681 while (iterator.hasNext()) {
682 Node node = iterator.nextNode();
683 try {
684 if (node.isNodeType(NodeTypes.Created.NAME)) {
685 NodeTypes.Created.set(node, user, updateDate);
686 }
687 tmp.add(node.getNodes());
688 } catch (RepositoryException e) {
689 log.error("Failed to set created date of {} with {}", node, e.getMessage(), e);
690 }
691 }
692 }
693 return tmp;
694 }
695
696
697
698
699 protected boolean shouldIgnoreUpdate(final String propertyName) {
700
701 return propertyName.startsWith(NodeTypes.JCR_PREFIX) || (propertyName.startsWith(NodeTypes.MGNL_PREFIX) && !SPECIAL_PROPERTY_NAMES.contains(propertyName));
702 }
703
704 protected String getCurrentUserName() {
705 String userName = MgnlContext.getUser().getName();
706 if (MgnlContext.isSystemInstance()) {
707
708 Context ctx = ((SystemContext) MgnlContext.getInstance()).getOriginalContext();
709 if (ctx != null && ctx.getUser() != null && !userName.equals(ctx.getUser().getName())) {
710
711 return "System [" + ctx.getUser().getName() + "]";
712 }
713 }
714 return userName;
715 }
716 }