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.commands.impl;
35
36 import info.magnolia.cms.core.version.VersionManager;
37 import info.magnolia.cms.exchange.ActivationManagerFactory;
38 import info.magnolia.cms.exchange.Subscriber;
39 import info.magnolia.cms.i18n.MessagesManager;
40 import info.magnolia.cms.security.AccessDeniedException;
41 import info.magnolia.cms.security.Permission;
42 import info.magnolia.cms.security.PermissionUtil;
43 import info.magnolia.cms.security.User;
44 import info.magnolia.cms.util.ExclusiveWrite;
45 import info.magnolia.cms.util.Rule;
46 import info.magnolia.context.Context;
47 import info.magnolia.context.MgnlContext;
48 import info.magnolia.jcr.iterator.FilteringNodeIterator;
49 import info.magnolia.jcr.iterator.FilteringPropertyIterator;
50 import info.magnolia.jcr.predicate.JCRMgnlPropertyHidingPredicate;
51 import info.magnolia.jcr.predicate.RuleBasedNodePredicate;
52 import info.magnolia.jcr.util.NodeTypes;
53 import info.magnolia.objectfactory.Components;
54
55 import java.util.Iterator;
56
57 import javax.jcr.Node;
58 import javax.jcr.Property;
59 import javax.jcr.RepositoryException;
60
61 import org.apache.commons.lang.StringUtils;
62
63
64
65
66
67
68
69
70
71
72 public class MarkNodeAsDeletedCommand extends RuleBasedCommand {
73
74 public static final String DELETED_NODE_TEMPLATE = "ui-admincentral:deleted";
75
76 public static final String DELETED_NODE_PROP_NAME = "deleteNode";
77
78 private boolean versionManually = true;
79
80 private boolean forcePreDelete;
81
82 private VersionManager versionManager;
83
84 @Override
85 public boolean execute(Context context) throws Exception {
86 versionManager = Components.getComponent(VersionManager.class);
87
88 final Node parentNode = getJCRNode(context);
89 final Node node = parentNode.getNode((String) context.get(DELETED_NODE_PROP_NAME));
90
91
92 User currentUser = MgnlContext.getUser();
93 if (currentUser == null) {
94 throw new AccessDeniedException(String.format("Current user in context %s was null, denying execution of command %s", context, this));
95 } else if (!PermissionUtil.isGranted(node, Permission.WRITE)) {
96 throw new AccessDeniedException(String.format("%s: not allowed to delete item", node.getPath()));
97 }
98
99 boolean hasActiveSubscriber = false;
100 for (Subscriber subscriber : ActivationManagerFactory.getActivationManager().getSubscribers()) {
101 if (subscriber.isActive()) {
102 hasActiveSubscriber = true;
103 break;
104 }
105 }
106 if (hasActiveSubscriber || isForcePreDelete()) {
107 preDeleteNode(node, context);
108 } else {
109 node.remove();
110 parentNode.getSession().save();
111 }
112
113 return true;
114 }
115
116 protected void preDeleteNode(Node node, Context context) throws RepositoryException {
117
118 version(node, context);
119 synchronized (ExclusiveWrite.getInstance()) {
120 markAsDeleted(node);
121 purgeContent(node);
122 storeDeletionInfo(node, context);
123
124 node.getSession().save();
125 }
126
127 Rule rule = new Rule(StringUtils.split(getItemTypes() + "," + NodeTypes.MetaData.NAME + "," + NodeTypes.Resource.NAME, ", "));
128 rule.reverse();
129 for (Iterator<Node> iter = new FilteringNodeIterator(node.getNodes(), new RuleBasedNodePredicate(rule)); iter.hasNext();) {
130 preDeleteNode(iter.next(), context);
131 }
132 }
133
134 protected void storeDeletionInfo(Node node, Context context) throws RepositoryException {
135 String comment = (String) context.get("comment");
136 if (comment == null) {
137 comment = MessagesManager.get("versions.comment.restore");
138 }
139 NodeTypes.Deleted.set(node, comment);
140 }
141
142 protected void version(Node node, Context context) throws RepositoryException {
143 if (isVersionManually()) {
144 synchronized (ExclusiveWrite.getInstance()) {
145 String comment = (String) context.get("comment");
146 if (comment == null) {
147 comment = MessagesManager.get("versions.comment.deleted");
148 }
149 node.setProperty(NodeTypes.Deleted.COMMENT, comment);
150 node.getSession().save();
151 }
152 versionManager.addVersion(node, getRule());
153 }
154 }
155
156 protected void markAsDeleted(Node node) throws RepositoryException {
157
158 node.addMixin(NodeTypes.Deleted.NAME);
159
160 if (node.isNodeType(NodeTypes.Renderable.NAME)) {
161 NodeTypes.Renderable.set(node, DELETED_NODE_TEMPLATE);
162 }
163 }
164
165 protected void purgeContent(Node node) throws RepositoryException {
166
167 for (Iterator<Node> iter = new FilteringNodeIterator(node.getNodes(), new RuleBasedNodePredicate(getRule())); iter.hasNext();) {
168 iter.next().remove();
169 }
170
171 for (Iterator<Property> iter = new FilteringPropertyIterator(node.getProperties(), new JCRMgnlPropertyHidingPredicate()); iter.hasNext();) {
172 Property property = iter.next();
173 property.remove();
174 }
175 }
176
177 public boolean isVersionManually() {
178 return versionManually;
179 }
180
181 public void setVersionManually(boolean versionManually) {
182 this.versionManually = versionManually;
183 }
184
185 public boolean isForcePreDelete() {
186 return forcePreDelete;
187 }
188
189 public void setForcePreDelete(boolean forcePreDelete) {
190 this.forcePreDelete = forcePreDelete;
191 }
192 }