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.nodetype;
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 public 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 List<String> dependentNodeTypeNames = new ArrayList<>(nodeTypeNames);
182 dependentNodeTypeNames.remove(nodeTypeName);
183 unregisterNodeTypes(nodeTypeManager, nodeTypeNames);
184 log.info("In order to unregister '{}', the following depending node types have been unregistered first: {}.", nodeTypeName, dependentNodeTypeNames);
185 dependentNodeTypeDefinitions.remove(nodeType);
186
187
188 log.info("Registering '{}' and the following depending nodeTypes: {}", nodeTypeName, dependentNodeTypeNames);
189 try {
190 registerNodeType(nodeTypeManager, nodeType);
191 } catch (RepositoryException e) {
192
193 registerNodeType(nodeTypeManager, originalNodeType);
194 String error = String.format("Registration (update of an existing NodeType) of the following NodeType generated exceptions '%s'. " +
195 "The original version of the definition is kept. Please check the NodeType dependency and the input list order.", nodeTypeName);
196 installContext.warn(error);
197 log.warn("Not able to register the following node type {}. The original definition is kept.", nodeTypeName, e);
198 }
199
200 for (NodeTypeDefinition nodeTypeDefinition : dependentNodeTypeDefinitions) {
201 try {
202 registerNodeType(nodeTypeManager, nodeTypeDefinition);
203 } catch (RepositoryException e) {
204 String error = String.format("Re-registration of the NodeType '%s' as a dependent nodeType of '%s' failed.", nodeTypeDefinition.getName(), nodeTypeName);
205 installContext.warn(error);
206 log.error(error, e);
207 }
208 }
209 } else {
210
211 nodeTypeManager.registerNodeType(nodeType, false);
212 log.info("Registering new '{}' node type.", nodeTypeName);
213 }
214 }
215 }
216
217
218
219
220
221
222 private void getDependencies(NodeTypeManager nodeTypeManager, String nodeTypeName, List<NodeTypeDefinition> dependentNodeTypeDefinitions) throws RepositoryException {
223 NodeTypeRegistry registry = ((NodeTypeManagerImpl) nodeTypeManager).getNodeTypeRegistry();
224 NamePathResolver namePathResolver = ((NodeTypeManagerImpl) nodeTypeManager).getNamePathResolver();
225 Set<Name> directChildNodeTypeQNames = registry.getDependentNodeTypes(namePathResolver.getQName(nodeTypeName));
226
227 if (directChildNodeTypeQNames.size() == 0) {
228 return;
229 }
230
231 for (Name directChildNodeTypeQName : directChildNodeTypeQNames) {
232 dependentNodeTypeDefinitions.add(((NodeTypeManagerImpl) nodeTypeManager).getNodeType(directChildNodeTypeQName));
233 getDependencies(nodeTypeManager, namePathResolver.getJCRName(directChildNodeTypeQName), dependentNodeTypeDefinitions);
234 }
235 }
236
237
238
239
240 private void registerNodeType(NodeTypeManager nodeTypeManager, NodeTypeDefinition nodeTypeDefinition) throws RepositoryException {
241
242 final NodeTypeTemplate nodeTypeTemplate = nodeTypeManager.createNodeTypeTemplate(nodeTypeDefinition);
243 log.debug("Registering the following '{}' node type.", nodeTypeTemplate.getName());
244 nodeTypeManager.registerNodeType(nodeTypeTemplate, true);
245 }
246
247
248
249
250
251 private void unregisterNodeTypes(final NodeTypeManager nodeTypeManager, List<String> nodeTypeNames) throws RepositoryException {
252 Iterator<String> it = nodeTypeNames.iterator();
253 while (it.hasNext()) {
254 String nodeTypeName = it.next();
255 if (!nodeTypeManager.hasNodeType(nodeTypeName)) {
256 log.warn("Node type '{}' is not registered . No un-registration will be performed for this nodeType.", nodeTypeName);
257 it.remove();
258 }
259 }
260
261 NodeTypeRegistry.disableCheckForReferencesInContentException = true;
262 nodeTypeManager.unregisterNodeTypes(nodeTypeNames.toArray(new String[nodeTypeNames.size()]));
263 log.info("Unregistered the following NodeTypes '{}'.", nodeTypeNames);
264 NodeTypeRegistry.disableCheckForReferencesInContentException = false;
265 }
266
267
268
269
270 private List<String> getNodeTypeNames(NamePathResolver namePathResolver, Collection<NodeTypeDefinition> nodeTypeDefinitions) throws NamespaceException, IllegalNameException {
271 List<String> names = new ArrayList<>();
272
273 for (NodeTypeDefinition nodeTypeDefinition : nodeTypeDefinitions) {
274 Name qName = namePathResolver.getQName(nodeTypeDefinition.getName());
275 names.add(namePathResolver.getJCRName(qName));
276 }
277 return names;
278 }
279
280
281
282
283
284
285
286
287
288
289
290 @Deprecated
291 protected HashMap<String, NodeTypeDefinition> getDependentNodeTypes(NodeTypeDefinition nodeType, NodeTypeRegistry registry, NamePathResolver namePathResolver, NodeTypeManager nodeTypeManager) throws RepositoryException {
292
293 HashMap<String, NodeTypeDefinition> dependentNodeType = new LinkedHashMap<>();
294
295 Name qName = namePathResolver.getQName(nodeType.getName());
296 Set<Name> dependentNodesName = registry.getDependentNodeTypes(qName);
297
298 if (dependentNodesName != null && !dependentNodesName.isEmpty()) {
299 for (Name name : dependentNodesName) {
300 dependentNodeType.putAll(getDependentNodeTypes(nodeTypeManager.getNodeType(namePathResolver.getJCRName(name)), registry, namePathResolver, nodeTypeManager));
301 }
302 }
303
304 dependentNodeType.put(nodeType.getName(), nodeType);
305 return dependentNodeType;
306 }
307 }