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.commands;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.util.DeprecationUtil;
38 import info.magnolia.cms.util.ModuleConfigurationObservingManager;
39 import info.magnolia.commands.chain.Catalog;
40 import info.magnolia.commands.chain.Command;
41 import info.magnolia.commands.chain.Context;
42 import info.magnolia.context.SimpleContext;
43 import info.magnolia.event.EventBus;
44 import info.magnolia.event.SystemEventBus;
45 import info.magnolia.jcr.node2bean.Node2BeanException;
46 import info.magnolia.jcr.node2bean.Node2BeanProcessor;
47 import info.magnolia.jcr.util.NodeTypes;
48 import info.magnolia.jcr.util.NodeUtil;
49 import info.magnolia.module.ModuleRegistry;
50 import info.magnolia.module.ModulesStartedEvent;
51 import info.magnolia.objectfactory.Components;
52
53 import java.util.HashMap;
54 import java.util.Iterator;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.concurrent.atomic.AtomicReference;
58
59 import javax.inject.Inject;
60 import javax.inject.Named;
61 import javax.inject.Singleton;
62 import javax.jcr.Node;
63 import javax.jcr.RepositoryException;
64
65 import org.apache.commons.lang3.StringUtils;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
68
69
70
71
72
73
74
75
76
77 @Singleton
78 public class CommandsManager extends ModuleConfigurationObservingManager {
79
80 private static final Logger log = LoggerFactory.getLogger(CommandsManager.class);
81
82 public static final String DEFAULT_CATALOG = "default";
83
84 public static final String COMMAND_DELIM = "-";
85
86 private final CommandTransformer commandTransformer;
87
88 private final Node2BeanProcessor nodeToBean;
89
90
91
92
93
94 private final AtomicReference<Map<String, MgnlCatalog>> catalogs = new AtomicReference<Map<String, MgnlCatalog>>(new HashMap<String, MgnlCatalog>());
95
96 @Inject
97 public CommandsManager(ModuleRegistry moduleRegistry, Node2BeanProcessor nodeToBean, @Named(SystemEventBus.NAME) EventBus systemEventBus) {
98 super("commands", moduleRegistry);
99 this.nodeToBean = nodeToBean;
100 this.commandTransformer = new CommandTransformer();
101 systemEventBus.addHandler(ModulesStartedEvent.class, new ModulesStartedEvent.Handler() {
102 @Override
103 public void onModuleStartupCompleted(ModulesStartedEvent event) {
104 CommandsManager.this.start();
105 }
106 });
107 }
108
109
110
111
112 @Deprecated
113 public CommandsManager(Node2BeanProcessor nodeToBean) {
114 this(Components.getComponent(ModuleRegistry.class), nodeToBean, Components.getComponentWithAnnotation(EventBus.class, Components.named(SystemEventBus.NAME)));
115 }
116
117 @Override
118 protected void reload(List<Node> nodes) throws RepositoryException {
119 Map<String, MgnlCatalog> foundCatalogs = new HashMap<>();
120 for (Node node : nodes) {
121 registerCatalogs(node, foundCatalogs);
122 }
123 this.catalogs.set(foundCatalogs);
124 }
125
126 protected void registerCatalogs(Node node, Map<String, MgnlCatalog> catalogs) throws RepositoryException {
127
128 Iterator<Node> children = NodeUtil.getNodes(node, NodeTypes.Content.NAME).iterator();
129 if (!children.hasNext()) {
130 registerCatalog(node, catalogs);
131 } else {
132 while (children.hasNext()) {
133 registerCatalogs(children.next(), catalogs);
134 }
135 }
136 }
137
138 protected void registerCatalog(Node node, Map<String, MgnlCatalog> catalogs) {
139 try {
140 log.debug("Registering commands at {}...", node.getPath());
141 MgnlCatalog catalog = (MgnlCatalog) nodeToBean.toBean(node, true, commandTransformer, Components.getComponentProvider());
142 MgnlCatalog current = catalogs.get(catalog.getName());
143 if (current == null) {
144 catalogs.put(catalog.getName(), catalog);
145 log.info("Catalog [{}] registered: {}", catalog.getName(), catalog);
146 } else {
147 for (String commandName : catalog.getNames()) {
148 Command command = current.getCommand(commandName);
149 if (command != null) {
150 log.warn(String.format("Command [%s] found at [%s] already exists in the catalog [%s], skipping...", commandName, node.getPath(), current.getName()));
151 } else {
152 log.info("Adding new command [{}] to already registered catalog [{}]...", commandName, current.getName());
153 current.addCommand(commandName, catalog.getCommand(commandName));
154 }
155 }
156 }
157 } catch (RepositoryException e) {
158 log.error("Can't read catalog [{}]", node, e);
159 } catch (Node2BeanException e) {
160 log.error("Can't create catalog [{}]", node, e);
161 }
162 }
163
164
165
166
167
168
169
170
171 public Command getCommand(String catalogName, String commandName) {
172
173 MgnlCatalog catalog = catalogs.get().get(StringUtils.isNotEmpty(catalogName) ? catalogName : DEFAULT_CATALOG);
174 if (catalog != null) {
175 Command command = catalog.getCommand(commandName);
176 if (command != null) {
177 try {
178 return command.clone();
179 } catch (CloneNotSupportedException e) {
180 log.warn("Cannot create clone of command [{}] from catalog [{}], because command doesn't support the Cloneable interface", commandName, catalogName);
181 }
182 }
183 }
184
185 return null;
186 }
187
188
189
190
191 public Command getCommand(String commandName) {
192 String catalogName = DEFAULT_CATALOG;
193 if (StringUtils.contains(commandName, COMMAND_DELIM)) {
194 catalogName = StringUtils.substringBefore(commandName, COMMAND_DELIM);
195 commandName = StringUtils.substringAfter(commandName, COMMAND_DELIM);
196 }
197
198 Command command = getCommand(catalogName, commandName);
199 if (command == null) {
200 command = getCommand(DEFAULT_CATALOG, commandName);
201 }
202 return command;
203 }
204
205
206
207
208
209 @Deprecated
210 public static CommandsManager getInstance() {
211 return Components.getComponent(CommandsManager.class);
212 }
213
214
215
216
217
218
219 public boolean executeCommand(final String catalogName, final String commandName, final Map<String, Object> params) throws Exception {
220 final Command command = getCommand(catalogName, commandName);
221 if (command == null) {
222 throw new Exception(String.format("Command [%s] could not be found in catalog [%s]", commandName, catalogName));
223 }
224 log.debug("Executing command [{}] from catalog [{}] and params [{}]...", commandName, catalogName, params);
225 return executeCommand(command, params);
226 }
227
228
229
230
231
232
233
234 public boolean executeCommand(final String commandName, final Map<String, Object> params) throws Exception {
235 return executeCommand(DEFAULT_CATALOG, commandName, params);
236 }
237
238
239
240
241
242
243
244 public boolean executeCommand(final Command command, final Map<String, Object> params) throws Exception {
245 return executeCommand(command, params, new SimpleContext());
246 }
247
248
249
250
251
252
253 public boolean executeCommand(final Command command, final Map<String, Object> params, Context context) throws Exception {
254 if (params != null) {
255 context.putAll(params);
256 }
257 return command.execute(context);
258 }
259
260 Catalog getCatalogByName(String name) {
261 return catalogs.get().get(name);
262 }
263
264
265
266
267 @Deprecated
268 protected void onRegister(Content node) {
269 this.register(node);
270 }
271
272
273
274
275 @Deprecated
276 public synchronized void register(Content content) {
277 DeprecationUtil.isDeprecated("Use reload(java.util.List) instead");
278 try {
279 List<Node> observedNodes = getObservedNodes();
280 observedNodes.add(content.getJCRNode());
281 reload(observedNodes);
282 } catch (RepositoryException e) {
283 log.error(e.getMessage(), e);
284 }
285 }
286
287
288
289
290 @Deprecated
291 protected void registerCatalog(Content node) {
292 this.register(node);
293 }
294
295
296
297
298 @Deprecated
299 @Override
300 public synchronized void reload() {
301 DeprecationUtil.isDeprecated("Use reload() instead");
302 super.reload();
303 }
304
305
306
307
308 @Deprecated
309 public void clear() {
310 DeprecationUtil.isDeprecated("Use onClear() instead.");
311 try {
312 this.onClear();
313 } catch (RepositoryException e) {
314 log.error(e.getMessage(), e);
315 }
316 }
317 }