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.HashMap;
41 import java.util.LinkedHashMap;
42 import java.util.LinkedList;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Set;
46
47 import javax.jcr.RepositoryException;
48 import javax.jcr.nodetype.NodeTypeDefinition;
49 import javax.jcr.nodetype.NodeTypeManager;
50 import javax.jcr.nodetype.NodeTypeTemplate;
51
52 import org.apache.commons.lang3.StringUtils;
53 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
54 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
55 import org.apache.jackrabbit.spi.Name;
56 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public abstract class AbstractNodeTypeRegistrationTask extends AbstractRepositoryTask {
79
80 private final Logger log = LoggerFactory.getLogger(AbstractNodeTypeRegistrationTask.class);
81
82 private String workspaceName;
83
84 public AbstractNodeTypeRegistrationTask(String name, String description, String workspaceName) {
85 super(name, description);
86 this.workspaceName = workspaceName;
87 }
88
89 @Override
90 protected void doExecute(InstallContext installContext) throws RepositoryException, TaskExecutionException {
91 if (StringUtils.isBlank(workspaceName)) {
92 log.warn("No workspace defined. This task will resume");
93 return;
94 }
95
96 NodeTypeManager nodeTypeManager = installContext.getJCRSession(workspaceName).getWorkspace().getNodeTypeManager();
97
98
99 List<NodeTypeDefinition> nodeTypeToRegister = getNodeTypesToRegister(nodeTypeManager);
100 if (nodeTypeToRegister == null || nodeTypeToRegister.isEmpty()) {
101 log.info("No NodeType defined to register for the following workspace '{}'", workspaceName);
102 } else {
103 registerNodeTypes(nodeTypeManager, nodeTypeToRegister, installContext);
104 }
105
106 List<String> nodeTypeToUnregister = getNodeTypesToUnregister(nodeTypeManager);
107 if (nodeTypeToUnregister == null || nodeTypeToUnregister.isEmpty()) {
108 log.info("No NodeType defined to unregister for the following workspace '{}'", workspaceName);
109 } else {
110 unregisterNodeTypes(nodeTypeManager, nodeTypeToUnregister, installContext);
111 }
112
113 }
114
115
116
117
118 public abstract List<NodeTypeDefinition> getNodeTypesToRegister(NodeTypeManager nodeTypeManager) throws RepositoryException;
119
120
121
122
123 public abstract List<String> getNodeTypesToUnregister(NodeTypeManager nodeTypeManager) throws RepositoryException;
124
125
126
127
128
129
130
131
132
133
134
135 private void registerNodeTypes(NodeTypeManager nodeTypeManager, List<NodeTypeDefinition> nodeTypesToRegister, InstallContext installContext) throws RepositoryException {
136 NodeTypeRegistry registry = ((NodeTypeManagerImpl) nodeTypeManager).getNodeTypeRegistry();
137 NamePathResolver namePathResolver = ((NodeTypeManagerImpl) nodeTypeManager).getNamePathResolver();
138
139 for (NodeTypeDefinition nodeType : nodeTypesToRegister) {
140
141 if (nodeTypeManager.hasNodeType(nodeType.getName())) {
142
143 NodeTypeDefinition originalNodeType = nodeTypeManager.getNodeType(nodeType.getName());
144
145 HashMap<String, NodeTypeDefinition> nodeTypeToUnregister = getDependentNodeTypes(nodeType, registry, namePathResolver, nodeTypeManager);
146
147 NodeTypeRegistry.disableCheckForReferencesInContentException = true;
148 log.info("In order to register '{}', the following depending node types have to be unregistered first: {}.", nodeType.getName(), nodeTypeToUnregister.keySet());
149 final String[] nodeTypesToUnregisterNames = nodeTypeToUnregister.keySet().toArray(new String[nodeTypeToUnregister.keySet().size()]);
150 nodeTypeManager.unregisterNodeTypes(nodeTypesToUnregisterNames);
151 NodeTypeRegistry.disableCheckForReferencesInContentException = false;
152
153
154 final Map<String, NodeTypeTemplate> templates = new LinkedHashMap<String, NodeTypeTemplate>();
155 try {
156 for (NodeTypeDefinition nodeTypeDefinition : nodeTypeToUnregister.values()) {
157
158 templates.put(nodeTypeDefinition.getName(), nodeTypeManager.createNodeTypeTemplate(nodeTypeDefinition));
159 }
160
161 log.info("Registering the following '{}' node type. Reregistered the following dependency: {}", nodeType.getName(), nodeTypeToUnregister.keySet());
162 nodeTypeManager.registerNodeTypes(templates.values().toArray(new NodeTypeDefinition[nodeTypeToUnregister.values().size()]), true);
163
164 } catch (Exception e) {
165
166 NodeTypeTemplate originalTemplate = nodeTypeManager.createNodeTypeTemplate(originalNodeType);
167 nodeTypeManager.registerNodeType(originalTemplate, false);
168
169 templates.remove(nodeType.getName());
170 nodeTypeManager.registerNodeTypes(templates.values().toArray(new NodeTypeDefinition[templates.values().size()]), true);
171 installContext.warn("Registration (update of an existing NodeType) of the following NodeType generated exceptions '" + nodeType.getName() + "'.The original version of the definition is kept. Please check the NodeType dependency and the input list order");
172 log.warn("Not able to register the following node type {}. The original definition is kept.", nodeType.getName(), e);
173 }
174 } else {
175
176 nodeTypeManager.registerNodeType(nodeType, false);
177 log.info("Registering new '{}' node type.", nodeType.getName());
178 }
179 }
180 }
181
182
183
184
185
186
187 protected HashMap<String, NodeTypeDefinition> getDependentNodeTypes(NodeTypeDefinition nodeType, NodeTypeRegistry registry, NamePathResolver namePathResolver, NodeTypeManager nodeTypeManager) throws RepositoryException {
188
189 HashMap<String, NodeTypeDefinition> dependentNodeType = new LinkedHashMap<String, NodeTypeDefinition>();
190
191 Name qName = namePathResolver.getQName(nodeType.getName());
192 Set<Name> dependentNodesName = registry.getDependentNodeTypes(qName);
193
194 if (dependentNodesName != null && !dependentNodesName.isEmpty()) {
195 for (Name name : dependentNodesName) {
196 dependentNodeType.putAll(getDependentNodeTypes(nodeTypeManager.getNodeType(namePathResolver.getJCRName(name)), registry, namePathResolver, nodeTypeManager));
197 }
198 }
199
200 dependentNodeType.put(nodeType.getName(), nodeType);
201 return dependentNodeType;
202
203 }
204
205
206
207
208 private void unregisterNodeTypes(NodeTypeManager nodeTypeManager, List<String> nodeTypesToUnregister, InstallContext installContext) throws RepositoryException {
209 LinkedList<String> filteredNodeTypeToUnregister = getFilteredNodesToUnregister(nodeTypeManager, nodeTypesToUnregister);
210 try {
211 NodeTypeRegistry.disableCheckForReferencesInContentException = true;
212 nodeTypeManager.unregisterNodeTypes(filteredNodeTypeToUnregister.toArray(new String[filteredNodeTypeToUnregister.size()]));
213 log.info("Unregistered the following NodeTypes '{}'", filteredNodeTypeToUnregister.toArray());
214 NodeTypeRegistry.disableCheckForReferencesInContentException = false;
215 } catch (RepositoryException re) {
216
217 installContext.warn("Unregistration of NodeTypes generated exceptions. NodeType will not be Unregistered. Please check the NodeType dependency");
218 log.warn("Not able to unregister the following node type {}. The original definition is kept.", filteredNodeTypeToUnregister.toArray(), re);
219 }
220 }
221
222
223
224
225
226 private LinkedList<String> getFilteredNodesToUnregister(NodeTypeManager nodeTypeManager, List<String> nodeTypeToUnregister) throws RepositoryException {
227 LinkedList<String> filteredNodeTypes = new LinkedList<String>();
228 for (String nodeTypeName : nodeTypeToUnregister) {
229 if (nodeTypeManager.hasNodeType(nodeTypeName)) {
230 filteredNodeTypes.add(nodeTypeName);
231 } else {
232 log.warn("Node type '{}' is not registered . No unregistration will be performed", nodeTypeName);
233 }
234 }
235 return filteredNodeTypes;
236 }
237 }