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.for5_0;
35
36 import info.magnolia.module.InstallContext;
37 import info.magnolia.module.delta.AbstractRepositoryTask;
38 import info.magnolia.module.delta.TaskExecutionException;
39
40 import java.util.ArrayList;
41 import java.util.Collection;
42 import java.util.HashMap;
43 import java.util.Iterator;
44 import java.util.LinkedHashMap;
45 import java.util.List;
46 import java.util.Set;
47
48 import javax.jcr.NamespaceException;
49 import javax.jcr.RepositoryException;
50 import javax.jcr.nodetype.NodeTypeDefinition;
51 import javax.jcr.nodetype.NodeTypeManager;
52 import javax.jcr.nodetype.NodeTypeTemplate;
53
54 import org.apache.commons.lang3.StringUtils;
55 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
56 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
57 import org.apache.jackrabbit.spi.Name;
58 import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
59 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 import com.google.common.collect.Lists;
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 public abstract class AbstractNodeTypeRegistrationTask extends AbstractRepositoryTask {
99
100 private final Logger log = LoggerFactory.getLogger(AbstractNodeTypeRegistrationTask.class);
101
102 private String workspaceName;
103
104 public AbstractNodeTypeRegistrationTask(String name, String description, String workspaceName) {
105 super(name, description);
106 this.workspaceName = workspaceName;
107 }
108
109 @Override
110 protected void doExecute(InstallContext installContext) throws RepositoryException, TaskExecutionException {
111 if (StringUtils.isBlank(workspaceName)) {
112 log.warn("No workspace defined. This task will resume");
113 return;
114 }
115
116 NodeTypeManager nodeTypeManager = installContext.getJCRSession(workspaceName).getWorkspace().getNodeTypeManager();
117
118
119 List<NodeTypeDefinition> nodeTypeToRegister = getNodeTypesToRegister(nodeTypeManager);
120 if (nodeTypeToRegister == null || nodeTypeToRegister.isEmpty()) {
121 log.info("No NodeType defined to register for the following workspace '{}'", workspaceName);
122 } else {
123
124 registerNodeTypes(nodeTypeManager, nodeTypeToRegister, installContext);
125 }
126
127 List<String> nodeTypeToUnregister = getNodeTypesToUnregister(nodeTypeManager);
128 if (nodeTypeToUnregister == null || nodeTypeToUnregister.isEmpty()) {
129 log.info("No NodeType defined to unregister for the following workspace '{}'", workspaceName);
130 } else {
131 try {
132 unregisterNodeTypes(nodeTypeManager, nodeTypeToUnregister);
133 } catch (RepositoryException e) {
134 installContext.warn("Un-registration of NodeTypes generated exceptions. NodeType will not be Unregistered. Please check the NodeType dependency.");
135 log.warn("Not able to un-register the following node type {}. The original definition is kept.", nodeTypeToUnregister, e);
136 }
137 }
138 }
139
140
141
142
143 public abstract List<NodeTypeDefinition> getNodeTypesToRegister(NodeTypeManager nodeTypeManager) throws RepositoryException;
144
145
146
147
148 public abstract List<String> getNodeTypesToUnregister(NodeTypeManager nodeTypeManager) throws RepositoryException;
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 private void registerNodeTypes(NodeTypeManager nodeTypeManager, List<NodeTypeDefinition> nodeTypesToRegister, InstallContext installContext) throws RepositoryException {
165 NamePathResolver namePathResolver = ((NodeTypeManagerImpl) nodeTypeManager).getNamePathResolver();
166
167 for (NodeTypeDefinition nodeType : nodeTypesToRegister) {
168
169 String nodeTypeName = nodeType.getName();
170
171 if (nodeTypeManager.hasNodeType(nodeTypeName)) {
172
173
174 NodeTypeDefinition originalNodeType = nodeTypeManager.getNodeType(nodeTypeName);
175
176
177 List<NodeTypeDefinition> dependentNodeTypeDefinitions = Lists.newArrayList();
178 getDependencies(nodeTypeManager, nodeTypeName, dependentNodeTypeDefinitions);
179 dependentNodeTypeDefinitions.add(nodeType);
180 List<String> nodeTypeNames = getNodeTypeNames(namePathResolver, dependentNodeTypeDefinitions);
181 unregisterNodeTypes(nodeTypeManager, nodeTypeNames);
182 log.info("In order to unregister '{}', the following depending node types have been unregistered first: {}.", nodeTypeName, nodeTypeNames);
183 dependentNodeTypeDefinitions.remove(nodeType);
184
185
186 log.info("Registering {} and the following depending nodeTypes: {}", nodeTypeName, dependentNodeTypeDefinitions);
187 try {
188 registerNodeType(nodeTypeManager, nodeType);
189 } catch (RepositoryException e) {
190
191 registerNodeType(nodeTypeManager, originalNodeType);
192 String error = String.format("Registration (update of an existing NodeType) of the following NodeType generated exceptions '%s'. " +
193 "The original version of the definition is kept. Please check the NodeType dependency and the input list order.", nodeTypeName);
194 installContext.warn(error);
195 log.warn("Not able to register the following node type {}. The original definition is kept.", nodeTypeName, e);
196 }
197
198 for (NodeTypeDefinition nodeTypeDefinition : dependentNodeTypeDefinitions) {
199 try {
200 registerNodeType(nodeTypeManager, nodeTypeDefinition);
201 } catch (RepositoryException e) {
202 String error = String.format("Re-registration of the NodeType '%s' as a dependent nodeType of '%s' failed.", nodeTypeDefinition.getName(), nodeTypeName);
203 installContext.warn(error);
204 log.error(error, e);
205 }
206 }
207 } else {
208
209 nodeTypeManager.registerNodeType(nodeType, false);
210 log.info("Registering new '{}' node type.", nodeTypeName);
211 }
212 }
213 }
214
215
216
217
218
219
220 private void getDependencies(NodeTypeManager nodeTypeManager, String nodeTypeName, List<NodeTypeDefinition> dependentNodeTypeDefinitions) throws RepositoryException {
221 NodeTypeRegistry registry = ((NodeTypeManagerImpl) nodeTypeManager).getNodeTypeRegistry();
222 NamePathResolver namePathResolver = ((NodeTypeManagerImpl) nodeTypeManager).getNamePathResolver();
223 Set<Name> directChildNodeTypeQNames = registry.getDependentNodeTypes(namePathResolver.getQName(nodeTypeName));
224
225 if (directChildNodeTypeQNames.size() == 0) {
226 return;
227 }
228
229 for (Name directChildNodeTypeQName : directChildNodeTypeQNames) {
230 dependentNodeTypeDefinitions.add(((NodeTypeManagerImpl) nodeTypeManager).getNodeType(directChildNodeTypeQName));
231 getDependencies(nodeTypeManager, namePathResolver.getJCRName(directChildNodeTypeQName), dependentNodeTypeDefinitions);
232 }
233 }
234
235
236
237
238 private void registerNodeType(NodeTypeManager nodeTypeManager, NodeTypeDefinition nodeTypeDefinition) throws RepositoryException {
239
240 final NodeTypeTemplate nodeTypeTemplate = nodeTypeManager.createNodeTypeTemplate(nodeTypeDefinition);
241 log.debug("Registering the following '{}' node type.", nodeTypeTemplate.getName());
242 nodeTypeManager.registerNodeType(nodeTypeTemplate, true);
243 }
244
245
246
247
248
249 private void unregisterNodeTypes(final NodeTypeManager nodeTypeManager, List<String> nodeTypeNames) throws RepositoryException {
250 Iterator<String> it = nodeTypeNames.iterator();
251 while (it.hasNext()) {
252 String nodeTypeName = it.next();
253 if (!nodeTypeManager.hasNodeType(nodeTypeName)) {
254 log.warn("Node type '{}' is not registered . No un-registration will be performed for this nodeType.", nodeTypeName);
255 it.remove();
256 }
257 }
258
259 NodeTypeRegistry.disableCheckForReferencesInContentException = true;
260 nodeTypeManager.unregisterNodeTypes(nodeTypeNames.toArray(new String[nodeTypeNames.size()]));
261 log.info("Unregistered the following NodeTypes '{}'.", nodeTypeNames);
262 NodeTypeRegistry.disableCheckForReferencesInContentException = false;
263 }
264
265 private List<NodeTypeDefinition> getNodeTypeDefinitions(NodeTypeManager nodeTypeManager, List<String> nodeTypeNames) throws RepositoryException {
266 List<NodeTypeDefinition> nodeTypeDefinitions = new ArrayList<>();
267 for (String ntn : nodeTypeNames) {
268 nodeTypeDefinitions.add(nodeTypeManager.getNodeType(ntn));
269 }
270 return nodeTypeDefinitions;
271 }
272
273
274
275
276 private List<String> getNodeTypeNames(NamePathResolver namePathResolver, Collection<NodeTypeDefinition> nodeTypeDefinitions) throws NamespaceException, IllegalNameException {
277 List<String> names = new ArrayList<String>();
278
279 for (NodeTypeDefinition nodeTypeDefinition : nodeTypeDefinitions) {
280 Name qName = namePathResolver.getQName(nodeTypeDefinition.getName());
281 names.add(namePathResolver.getJCRName(qName));
282 }
283 return names;
284 }
285
286
287
288
289
290
291
292
293
294
295
296 @Deprecated
297 protected HashMap<String, NodeTypeDefinition> getDependentNodeTypes(NodeTypeDefinition nodeType, NodeTypeRegistry registry, NamePathResolver namePathResolver, NodeTypeManager nodeTypeManager) throws RepositoryException {
298
299 HashMap<String, NodeTypeDefinition> dependentNodeType = new LinkedHashMap<String, NodeTypeDefinition>();
300
301 Name qName = namePathResolver.getQName(nodeType.getName());
302 Set<Name> dependentNodesName = registry.getDependentNodeTypes(qName);
303
304 if (dependentNodesName != null && !dependentNodesName.isEmpty()) {
305 for (Name name : dependentNodesName) {
306 dependentNodeType.putAll(getDependentNodeTypes(nodeTypeManager.getNodeType(namePathResolver.getJCRName(name)), registry, namePathResolver, nodeTypeManager));
307 }
308 }
309
310 dependentNodeType.put(nodeType.getName(), nodeType);
311 return dependentNodeType;
312 }
313 }