Cq60MSMContentUpgrade.java
9.62 KB
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/*
* Decompiled with CFR 0_118.
*
* Could not load the following classes:
* com.day.text.Text
* javax.jcr.ItemNotFoundException
* javax.jcr.Node
* javax.jcr.NodeIterator
* javax.jcr.Property
* javax.jcr.RepositoryException
* javax.jcr.Session
* javax.jcr.Value
* javax.jcr.ValueFactory
* javax.jcr.Workspace
* javax.jcr.query.Query
* javax.jcr.query.QueryManager
* javax.jcr.query.QueryResult
* javax.jcr.version.Version
* javax.jcr.version.VersionHistory
* javax.jcr.version.VersionIterator
* org.slf4j.Logger
* org.slf4j.LoggerFactory
*/
package com.day.cq.compat.codeupgrade.impl.cq60;
import com.day.cq.compat.codeupgrade.internal.api.ProgressInfoProvider;
import com.day.text.Text;
import java.util.Calendar;
import java.util.HashSet;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.Workspace;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Cq60MSMContentUpgrade
implements ProgressInfoProvider {
private static final String NT_LIVE_RELATIONSHIP = "cq:LiveRelationship";
private static final String STATEMENT = String.format("/jcr:root/jcr:system/jcr:versionStorage//*[%s/@%s='%s']", "jcr:frozenNode", "jcr:frozenMixinTypes", "cq:LiveRelationship");
private static final String PN_CQ_PARENT_PATH = "cq:parentPath";
private static final String PN_CQ_NAME = "cq:name";
private static final Logger log = LoggerFactory.getLogger(Cq60MSMContentUpgrade.class);
private static final int COMMIT_SIZE = 1024;
private static final int HEART_BEAT_FREQUENCY = 1000;
private String progressInfo = "No info yet";
@Override
public String getProgressInfo() {
return this.progressInfo;
}
void setProgressInfo(String info) {
this.progressInfo = info;
log.info(this.progressInfo);
}
public void doUpgrade(Session session) throws Exception {
QueryManager qm = session.getWorkspace().getQueryManager();
int changed = this.changeDeletedLiveRelationships(qm);
this.setProgressInfo(String.format("Changed %s LiveCopies to ", changed));
if (session.hasPendingChanges()) {
session.save();
}
}
int changeDeletedLiveRelationships(QueryManager queryManager) throws RepositoryException {
int total = 0;
int commitCnt = 0;
Query query = queryManager.createQuery(STATEMENT, "xpath");
NodeIterator res = query.execute().getNodes();
int heartbeat = 0;
while (res.hasNext()) {
Node versionNode = res.nextNode();
Version v = (Version)versionNode;
if (Cq60MSMContentUpgrade.filterVersion(v)) {
Session session = v.getSession();
String path = Cq60MSMContentUpgrade.buildPath(v);
if (path != null && !session.nodeExists(path)) {
log.debug("Found deleted LiveRelationship at {}", (Object)path);
Node parent = Cq60MSMContentUpgrade.getClosestParentRelation(session, path);
if (parent != null) {
log.debug("Parent of deleted liveRelation found at {}", (Object)parent);
LiveCopy lc = Cq60MSMContentUpgrade.getClosestLiveCopy(parent);
if (lc != null && lc.addExclusion(path)) {
++total;
this.setProgressInfo(String.format("Add exclusion to LiveCopy at %s for %s", lc.path, path));
if (commitCnt == 1024) {
session.save();
commitCnt = 0;
} else {
++commitCnt;
}
} else {
log.debug("LiveCopy of deleted LiveRelation at {} missing: no updated", (Object)parent);
}
}
}
}
if (heartbeat++ <= 1000) continue;
this.setProgressInfo(String.format("...inspected %s Versions for deleted LiveRelationship", 1000));
heartbeat = 0;
}
return total;
}
private static boolean filterVersion(Version v) throws RepositoryException {
VersionHistory vh = v.getContainingHistory();
String vI = vh.getVersionableIdentifier();
try {
v.getSession().getNodeByIdentifier(vI);
return false;
}
catch (ItemNotFoundException e) {
VersionIterator itr = vh.getAllVersions();
Version last = null;
while (itr.hasNext()) {
Version next = itr.nextVersion();
if (last != null && !next.getCreated().after(last.getCreated())) continue;
last = next;
}
if (last != null) {
Property mixin = last.getFrozenNode().getProperty("jcr:frozenMixinTypes");
for (Value value : mixin.getValues()) {
if (!"cq:LiveRelationship".equals(value.getString())) continue;
return true;
}
}
return false;
}
}
private static LiveCopy getClosestLiveCopy(Node parent) throws RepositoryException {
LiveCopy lc = LiveCopy.create(parent);
if (lc == null) {
if (parent.getParent() != null && Cq60MSMContentUpgrade.isLiveRelationship(parent.getParent())) {
return Cq60MSMContentUpgrade.getClosestLiveCopy(parent.getParent());
}
} else if (lc.isDeep()) {
return lc;
}
return null;
}
private static Node getClosestParentRelation(Session session, String path) throws RepositoryException {
String parent = Text.getRelativeParent((String)path, (int)1);
while (parent != null) {
if (session.nodeExists(parent)) {
Node parentNode = session.getNode(parent);
if (!Cq60MSMContentUpgrade.isLiveRelationship(parentNode)) break;
return parentNode;
}
parent = Text.getRelativeParent((String)parent, (int)1);
}
return null;
}
private static String buildPath(Version version) throws RepositoryException {
Node frozenNode = version.getFrozenNode();
if (frozenNode.hasProperty("cq:name") && frozenNode.hasProperty("cq:parentPath")) {
return frozenNode.getProperty("cq:parentPath").getString() + "/" + frozenNode.getProperty("cq:name").getString();
}
return null;
}
private static boolean isLiveRelationship(Node node) throws RepositoryException {
return node.hasNode("jcr:content") && node.getNode("jcr:content").isNodeType("cq:LiveRelationship");
}
private static class LiveCopy {
private static final String NT_LIVE_SYNC_CONFIG = "cq:LiveSyncConfig";
private static final String PATH_CONFIG = "jcr:content/cq:LiveSyncConfig";
private static final String PN_EXCLUDES = "cq:excludedPaths";
private static final String PN_IS_DEEP = "cq:isDeep";
private static final String NT_LC_PATH_FILTER = "cq:LcPathFilter";
private final Node node;
private final String path;
public LiveCopy(Node node) throws RepositoryException {
this.node = node.getNode("jcr:content/cq:LiveSyncConfig");
this.path = node.getPath();
}
public boolean isDeep() throws RepositoryException {
return this.node.hasProperty("cq:isDeep") && this.node.getProperty("cq:isDeep").getBoolean();
}
private static LiveCopy create(Node node) throws RepositoryException {
if (node.hasProperty("jcr:content/cq:LiveSyncConfig/cq:master")) {
return new LiveCopy(node);
}
return null;
}
public boolean addExclusion(String absPath) throws RepositoryException {
String relPath = this.makeRelative(absPath);
if (relPath == null) {
log.error("Attempt to set non descendant {} to LiveCopy {}", (Object)this.path, (Object)this.path);
return false;
}
HashSet<Value> values = new HashSet<Value>();
if (this.node.hasProperty("cq:excludedPaths")) {
for (Value value : this.node.getProperty("cq:excludedPaths").getValues()) {
String saved = value.getString();
if (saved.equals(relPath) || relPath.startsWith(saved + "/")) {
return false;
}
if (saved.startsWith(relPath + "/")) continue;
values.add(value);
}
}
ValueFactory factory = this.node.getSession().getValueFactory();
values.add(factory.createValue(relPath));
if (!this.node.isNodeType("cq:LcPathFilter")) {
this.node.addMixin("cq:LcPathFilter");
}
this.node.setProperty("cq:excludedPaths", values.toArray((T[])new Value[values.size()]));
return true;
}
private String makeRelative(String descendant) {
if (this.path.length() < descendant.length() + 1) {
return descendant.substring(this.path.length() + 1);
}
return null;
}
}
}