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