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.setup;
35
36 import info.magnolia.cms.core.version.VersionManager;
37 import info.magnolia.jcr.util.NodeTypes;
38 import info.magnolia.jcr.util.NodeUtil;
39 import info.magnolia.module.InstallContext;
40 import info.magnolia.module.delta.AbstractRepositoryTask;
41 import info.magnolia.module.delta.TaskExecutionException;
42 import info.magnolia.repository.RepositoryConstants;
43 import info.magnolia.repository.RepositoryManager;
44
45 import java.util.Collections;
46 import java.util.HashMap;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.stream.Collectors;
50
51 import javax.jcr.ItemNotFoundException;
52 import javax.jcr.Node;
53 import javax.jcr.RepositoryException;
54 import javax.jcr.Session;
55
56 import org.apache.commons.lang3.RandomStringUtils;
57 import org.apache.commons.lang3.StringUtils;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61
62
63
64
65
66
67 public class MigrateVersionWorkspacesToNewStructureTask extends AbstractRepositoryTask {
68
69 private static final Logger log = LoggerFactory.getLogger(MigrateVersionWorkspacesToNewStructureTask.class);
70
71 private static final String FOUND_IN_MULTIPLE_WORKSPACES_MESSAGE = "Node [%s:%s:%s] found in multiple workspaces [%s]. This means that versions for both nodes are most likely broken and versions needs to be removed.";
72 private static final String ORIGINAL_NODE_NOT_FOUND_MESSAGE = "Version found for node [%s:%s:%s], but original node no longer exists";
73 public static final String INCONSISTENT_VERSIONS = "inconsistentVersions";
74
75 private final RepositoryManager repositoryManager;
76
77 private Map<String, Session> sessions = new HashMap<>();
78
79 public MigrateVersionWorkspacesToNewStructureTask(RepositoryManager repositoryManager) {
80 super("Migrate version workspace", "Migrate version workspace to new structure");
81 this.repositoryManager = repositoryManager;
82 }
83
84 @Override
85 protected void doExecute(InstallContext installContext) throws RepositoryException, TaskExecutionException {
86 List<String> versionWorkspaces = repositoryManager.getWorkspaceNames().stream().filter(input -> StringUtils.endsWith(input, RepositoryConstants.VERSION_STORE)).collect(Collectors.toList());
87
88 List<String> workspacesToSearchIn = repositoryManager.getWorkspaceNames().stream().filter(input -> !(StringUtils.endsWith(input, RepositoryConstants.VERSION_STORE) || StringUtils.endsWith(input, RepositoryConstants.SYSTEM))).collect(Collectors.toList());
89
90 Collections.swap(workspacesToSearchIn, workspacesToSearchIn.indexOf(RepositoryConstants.WEBSITE), 0);
91 if (workspacesToSearchIn.contains("dam")) {
92 Collections.swap(workspacesToSearchIn, workspacesToSearchIn.indexOf("dam"), 1);
93 }
94 if (workspacesToSearchIn.contains("contacts")) {
95 Collections.swap(workspacesToSearchIn, workspacesToSearchIn.indexOf("contacts"), 2);
96 }
97 if (workspacesToSearchIn.contains("segments")) {
98 Collections.swap(workspacesToSearchIn, workspacesToSearchIn.indexOf("segments"), 3);
99 }
100 if (workspacesToSearchIn.contains("personas")) {
101 Collections.swap(workspacesToSearchIn, workspacesToSearchIn.indexOf("personas"), 4);
102 }
103
104 for (String versionWorkspace : versionWorkspaces) {
105 Session versionSession = installContext.getJCRSession(versionWorkspace);
106 final String tempNodeName = RandomStringUtils.randomAlphanumeric(10);
107
108
109 final Node tempNode = versionSession.getRootNode().addNode(tempNodeName, NodeTypes.Folder.NAME);
110
111 final Node inconsistentVersionsNode = versionSession.getRootNode().addNode(INCONSISTENT_VERSIONS, NodeTypes.Folder.NAME);
112
113 for (Node versionNode : NodeUtil.getNodes(versionSession.getRootNode())) {
114 if (versionNode.getName().equals(VersionManager.TMP_REFERENCED_NODES)
115 || StringUtils.startsWith(versionNode.getName(), NodeTypes.REP_PREFIX)
116 || StringUtils.equals(versionNode.getName(), tempNodeName)
117 || StringUtils.equals(versionNode.getName(), INCONSISTENT_VERSIONS)) {
118 continue;
119 }
120
121 log.debug("Processing version node [{}] with uuid [{}]", versionNode.getPath(), versionNode.getIdentifier());
122 String uuid = versionNode.getIdentifier();
123 log.debug("Renaming version node [{}] to [{}]", versionNode.getName(), uuid);
124 NodeUtil.renameNode(versionNode, uuid);
125
126 Map<String, Node> found = new HashMap<>();
127 Node originalNode = null;
128 for (String workspace : workspacesToSearchIn) {
129 if (!sessions.containsKey(workspace)) {
130 sessions.put(workspace, installContext.getJCRSession(workspace));
131 }
132 try {
133 Node node = sessions.get(workspace).getNodeByIdentifier(uuid);
134 if (node.getPrimaryNodeType().getName().equals(versionNode.getPrimaryNodeType().getName())) {
135 originalNode = node;
136 }
137 found.put(workspace, node);
138 } catch (ItemNotFoundException e) {
139
140 }
141 }
142
143 if (found.size() == 0 || originalNode == null) {
144
145 log.debug(String.format(ORIGINAL_NODE_NOT_FOUND_MESSAGE, versionNode.getName(), versionNode.getIdentifier(), versionNode.getPrimaryNodeType().getName()));
146 Node newParent = NodeUtil.createPath(inconsistentVersionsNode, getSavePath(versionNode), NodeTypes.Folder.NAME, false);
147 NodeUtil.moveNode(versionNode, newParent);
148 continue;
149 } else if (found.size() > 1) {
150
151 log.debug(String.format(FOUND_IN_MULTIPLE_WORKSPACES_MESSAGE, versionNode.getName(), versionNode.getIdentifier(), versionNode.getPrimaryNodeType().getName(), StringUtils.join(found, ":")));
152 }
153 Node newParent = NodeUtil.createPath(tempNode, getSavePath(originalNode), NodeTypes.Folder.NAME, false);
154
155 NodeUtil.moveNode(versionNode, newParent);
156
157 originalNode.addMixin(NodeTypes.HasVersion.NAME);
158 log.debug("Moved [{}] to the new location [{}]", versionNode.getPath(), newParent.getPath() + "/" + versionNode.getName());
159 }
160
161 for (Node node : NodeUtil.getNodes(tempNode)) {
162 NodeUtil.moveNode(node, versionSession.getRootNode());
163 }
164 tempNode.remove();
165 }
166 }
167
168 String getSavePath(Node node) throws RepositoryException {
169 String uuid = node.getIdentifier();
170 return String.format("%s/%s/%s", StringUtils.substring(uuid, 0, 2), StringUtils.substring(uuid, 9, 11), StringUtils.substring(uuid, 14, 16));
171 }
172 }