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.module.admininterface.commands;
35
36 import info.magnolia.cms.core.MetaData;
37 import info.magnolia.cms.core.MgnlNodeType;
38 import info.magnolia.cms.core.version.VersionManager;
39 import info.magnolia.cms.exchange.ActivationManagerFactory;
40 import info.magnolia.cms.exchange.Subscriber;
41 import info.magnolia.cms.i18n.MessagesManager;
42 import info.magnolia.cms.security.AccessDeniedException;
43 import info.magnolia.cms.util.ExclusiveWrite;
44 import info.magnolia.context.Context;
45 import info.magnolia.context.MgnlContext;
46 import info.magnolia.jcr.iterator.FilteringNodeIterator;
47 import info.magnolia.jcr.iterator.FilteringPropertyIterator;
48 import info.magnolia.jcr.predicate.JCRPropertyHidingPredicate;
49 import info.magnolia.jcr.predicate.NodeTypePredicate;
50 import info.magnolia.jcr.util.MetaDataUtil;
51 import info.magnolia.objectfactory.Components;
52
53 import java.util.Calendar;
54 import java.util.Iterator;
55
56 import javax.jcr.Node;
57 import javax.jcr.PathNotFoundException;
58 import javax.jcr.Property;
59 import javax.jcr.RepositoryException;
60 import javax.jcr.UnsupportedRepositoryOperationException;
61
62 public class MarkNodeAsDeletedCommand extends BaseRepositoryCommand {
63
64 public static final String DELETED_NODE_TEMPLATE = "adminInterface:mgnlDeleted";
65
66 public static final String DELETED_NODE_DELETED_BY = "mgnl:deletedBy";
67 public static final String DELETED_NODE_DELETED_ON = "mgnl:deletedOn";
68
69 public static final String DELETED_NODE_PROP_NAME = "deleteNode";
70
71 private boolean versionManually = true;
72
73 private boolean forcePreDelete;
74
75 protected VersionManager versionManager;
76
77 @Override
78 public boolean execute(Context context) throws Exception {
79 versionManager = Components.getSingleton(VersionManager.class);
80
81 final Node parentNode = getJCRNode(context);
82 final Node node = parentNode.getNode((String) context.get(DELETED_NODE_PROP_NAME));
83 boolean hasActiveSubscriber = false;
84 for (Subscriber subscriber : ActivationManagerFactory.getActivationManager().getSubscribers()) {
85 if (subscriber.isActive()) {
86 hasActiveSubscriber = true;
87 break;
88 }
89 }
90 if (hasActiveSubscriber || isForcePreDelete()) {
91 preDeleteNode(node, context);
92 } else {
93 node.remove();
94 parentNode.getSession().save();
95 }
96
97 return true;
98 }
99
100 protected void preDeleteNode(Node node, Context context) throws RepositoryException, AccessDeniedException {
101
102 version(node, context);
103 synchronized (ExclusiveWrite.getInstance()) {
104 markAsDeleted(node);
105 purgeContent(node);
106 storeDeletionInfo(node, context);
107
108 node.getSession().save();
109 }
110 for (Iterator<Node> iter = new FilteringNodeIterator(node.getNodes(), new NodeTypePredicate(MgnlNodeType.NT_CONTENT, true)); iter.hasNext();) {
111 preDeleteNode(iter.next(), context);
112 }
113 }
114
115 protected void storeDeletionInfo(Node node, Context context) throws AccessDeniedException, PathNotFoundException, RepositoryException {
116 node.setProperty(DELETED_NODE_DELETED_BY, MgnlContext.getUser().getName());
117 node.setProperty(DELETED_NODE_DELETED_ON, Calendar.getInstance());
118 String comment = (String) context.get("comment");
119 if (comment == null) {
120 comment = MessagesManager.get("versions.comment.restore");
121 }
122 MetaDataUtil.getMetaData(node).setProperty(Context.ATTRIBUTE_COMMENT, comment);
123 }
124
125 protected void version(Node node, Context context) throws UnsupportedRepositoryOperationException, RepositoryException {
126 if (isVersionManually()) {
127 synchronized (ExclusiveWrite.getInstance()) {
128 String comment = (String) context.get("comment");
129 if (comment == null) {
130 comment = MessagesManager.get("versions.comment.deleted");
131 }
132 MetaDataUtil.getMetaData(node).setProperty(Context.ATTRIBUTE_COMMENT, comment);
133 node.getSession().save();
134 }
135 versionManager.addVersion(node);
136 }
137 }
138
139 protected void markAsDeleted(Node node) throws RepositoryException, AccessDeniedException {
140
141 node.addMixin(MgnlNodeType.MIX_DELETED);
142
143 MetaData metadata = MetaDataUtil.getMetaData(node);
144 metadata.setTemplate(DELETED_NODE_TEMPLATE);
145 if (metadata.getActivationStatus() != MetaData.ACTIVATION_STATUS_NOT_ACTIVATED) {
146 metadata.setModificationDate();
147 }
148 MetaDataUtil.updateMetaData(node);
149 }
150
151 protected void purgeContent(Node node) throws RepositoryException {
152
153 for (Iterator<Node> iter = new FilteringNodeIterator(node.getNodes(), new NodeTypePredicate(MgnlNodeType.NT_CONTENTNODE)); iter.hasNext();) {
154 iter.next().remove();
155 }
156
157 for (Iterator<Property> iter = new FilteringPropertyIterator(node.getProperties(), new JCRPropertyHidingPredicate()); iter.hasNext();) {
158 Property property = iter.next();
159 property.remove();
160 }
161 }
162
163 public boolean isVersionManually() {
164 return versionManually;
165 }
166
167 public void setVersionManually(boolean versionManually) {
168 this.versionManually = versionManually;
169 }
170
171 public boolean isForcePreDelete() {
172 return forcePreDelete;
173 }
174
175 public void setForcePreDelete(boolean forcePreDelete) {
176 this.forcePreDelete = forcePreDelete;
177 }
178 }