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.util.Rule;
38 import info.magnolia.context.Context;
39 import info.magnolia.jcr.predicate.NodeTypePredicate;
40 import info.magnolia.jcr.predicate.RuleBasedNodePredicate;
41 import info.magnolia.jcr.util.NodeTypes;
42 import info.magnolia.jcr.util.NodeUtil;
43
44 import javax.inject.Inject;
45 import javax.jcr.Node;
46 import javax.jcr.RepositoryException;
47 import javax.jcr.lock.Lock;
48 import javax.jcr.lock.LockManager;
49 import javax.jcr.version.Version;
50 import javax.jcr.version.VersionIterator;
51
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55
56
57
58 public class RestorePreviousVersionCommand extends RuleBasedCommand {
59
60 private static final Logger log = LoggerFactory.getLogger(RestorePreviousVersionCommand.class);
61
62 public static final String ATTRIBUTE_PARENT_NODE_TYPE_ONLY = "parentNodeTypeOnly";
63 public static final String ATTRIBUTE_INCLUDING_CHILDREN = "includingChildren";
64 public static final int HOLD_LOCK_IN_SECONDS = 30;
65
66 private VersionManager versionManager;
67
68 private boolean parentNodeTypeOnly = false;
69
70 private boolean includingChildren = true;
71
72 @Inject
73 public RestorePreviousVersionCommand(VersionManager versionManager) {
74 this.versionManager = versionManager;
75 }
76
77 @Override
78 public boolean execute(Context context) throws Exception {
79 final Node node = getJCRNode(context);
80 final LockManager manager = node.getSession().getWorkspace().getLockManager();
81
82 parentNodeTypeOnly = (Boolean) (context.containsKey(ATTRIBUTE_PARENT_NODE_TYPE_ONLY) ? context.get(ATTRIBUTE_PARENT_NODE_TYPE_ONLY) : parentNodeTypeOnly);
83
84 includingChildren = (Boolean) (context.containsKey(ATTRIBUTE_INCLUDING_CHILDREN) ? context.get(ATTRIBUTE_INCLUDING_CHILDREN) : includingChildren);
85
86 if (context.containsKey(ATTRIBUTE_RULE)) {
87 setRule(context.getAttribute(ATTRIBUTE_RULE));
88 }
89
90 try {
91 Lock lock = manager.lock(node.getPath(), true, false, HOLD_LOCK_IN_SECONDS, null);
92 restore(node, lock);
93
94 return true;
95 } finally {
96 if (manager.isLocked(node.getPath())) {
97 manager.unlock(node.getPath());
98 }
99 }
100 }
101
102 @Override
103 protected Rule getDefaultRule() {
104 final Rule rule = super.getDefaultRule();
105 rule.removeAllowType(NodeTypes.Resource.NAME);
106 return rule;
107 }
108
109 private void restore(Node node, Lock lock) throws RepositoryException {
110 String nodeType = node.getPrimaryNodeType().getName();
111
112 log.debug("Restoring previous version of node at {} of type {}", node.getPath(), nodeType);
113
114
115 Version version = getPreviousVersion(node);
116
117 if (version == null) {
118 throw new RepositoryException("No previous version found for node at " + node.getPath());
119 }
120
121
122 versionManager.restore(node, version, true);
123
124 if (includingChildren) {
125 lock.refresh();
126 restoreAllChildren(node, nodeType);
127 }
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141 protected void restoreAllChildren(Node node, String parentNodeType) throws RepositoryException {
142
143 Iterable<Node> children;
144
145 if (isParentNodeTypeOnly()) {
146 children = NodeUtil.collectAllChildren(node, new NodeTypePredicate(parentNodeType));
147 } else {
148 children = NodeUtil.collectAllChildren(node, new RuleBasedNodePredicate(this.getRule()));
149 }
150
151 for (Node child : children) {
152 Version childVersion = getPreviousVersion(child);
153 if (childVersion == null) {
154 log.debug("No previous version found for subnode {}. Skipping restore...", child.getPath());
155 continue;
156 }
157 versionManager.restore(child, childVersion, true);
158 }
159 }
160
161
162
163
164 private Version getPreviousVersion(Node node) throws RepositoryException {
165 Version previousVersion = null;
166 VersionIterator versionIterator = versionManager.getAllVersions(node);
167
168 while (versionIterator.hasNext()) {
169 previousVersion = versionIterator.nextVersion();
170 }
171
172 return previousVersion;
173 }
174
175
176
177
178 public boolean isParentNodeTypeOnly() {
179 return parentNodeTypeOnly;
180 }
181
182 }