View Javadoc

1   /**
2    * This file Copyright (c) 2003-2013 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.commands;
35  
36  import info.magnolia.cms.beans.config.ObservedManager;
37  import info.magnolia.cms.core.Content;
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.jcr.node2bean.Node2BeanException;
43  import info.magnolia.jcr.node2bean.Node2BeanProcessor;
44  import info.magnolia.jcr.util.NodeTypes;
45  import info.magnolia.objectfactory.Components;
46  
47  import java.util.HashMap;
48  import java.util.Iterator;
49  import java.util.Map;
50  
51  import javax.inject.Inject;
52  import javax.inject.Singleton;
53  import javax.jcr.RepositoryException;
54  
55  import org.apache.commons.lang.StringUtils;
56  
57  
58  /**
59   * Manages the Commands and Catalogs.
60   *
61   */
62  @Singleton
63  public class CommandsManager extends ObservedManager {
64  
65      public static final String DEFAULT_CATALOG = "default";
66  
67      public static final String COMMAND_DELIM = "-";
68  
69      private final CommandTransformer commandTransformer;
70  
71      private final Node2BeanProcessor nodeToBean;
72  
73      private Map<String, MgnlCatalog> catalogs;
74  
75      @Inject
76      public CommandsManager(Node2BeanProcessor nodeToBean) {
77          this.nodeToBean = nodeToBean;
78          this.commandTransformer = new CommandTransformer();
79          this.catalogs = new HashMap<String, MgnlCatalog>();
80      }
81  
82      /**
83       * Register observation for command catalogs.
84       */
85      @Override
86      protected void onRegister(Content node) {
87          // is this a catalog or a collection of catalogs?
88          if (node.getChildren(NodeTypes.Content.NAME).size() == 0) {
89              registerCatalog(node);
90          }
91          else{
92              for (Iterator iter = node.getChildren(NodeTypes.Content.NAME).iterator(); iter.hasNext();) {
93                  onRegister((Content) iter.next());
94              }
95          }
96      }
97  
98  
99      protected void registerCatalog(Content node) {
100         log.debug("Registering commands at {}...", node.getHandle());
101         try {
102             MgnlCatalog catalog = (MgnlCatalog) nodeToBean.toBean(node.getJCRNode(), true, commandTransformer, Components.getComponentProvider());
103             MgnlCatalog current = catalogs.get(catalog.getName());
104             if (current == null) {
105                 catalogs.put(catalog.getName(), catalog);
106                 log.info("Catalog [{}] registered: {}", catalog.getName(), catalog);
107             } else {
108                 for (String commandName : catalog.getNames()) {
109                     Command command = current.getCommand(commandName);
110                     if (command != null) {
111                         log.warn(String.format("Command [%s] found at [%s] already exists in the catalog [%s], skipping...", commandName, node.getHandle(), current.getName()));
112                     } else {
113                         log.info("Adding new command [{}] to already registered catalog [{}]...", commandName, current.getName());
114                         current.addCommand(commandName, catalog.getCommand(commandName));
115                     }
116                 }
117             }
118         }
119         catch (RepositoryException e) {
120             log.error("Can't read catalog [" + node + "]", e);
121         }
122         catch (Node2BeanException e) {
123             log.error("Can't create catalog [" + node  + "]", e);
124         }
125     }
126 
127     /**
128      * Clear all catalogs.
129      */
130     @Override
131     protected void onClear() {
132         catalogs.clear();
133     }
134 
135     /**
136      * Get the command.
137      * @param catalogName the catalog containing the command
138      * @param commandName the name of the command
139      * @return the command to execute
140      */
141     public Command getCommand(String catalogName, String commandName) {
142         // if empty catalog name, use default catalog
143         MgnlCatalog catalog = catalogs.get(StringUtils.isNotEmpty(catalogName) ? catalogName : DEFAULT_CATALOG);
144         if (catalog != null) {
145             Command command = catalog.getCommand(commandName);
146             if (command != null) {
147                 Command copy = command.copy(command);
148                 if (copy != null) {
149                     return copy;
150                 }
151                 log.warn("Cannot create copy of command [" + commandName + "] from catalog [" + catalogName + "].");
152             }
153         }
154 
155         return null;
156     }
157 
158     /**
159      * Use a delimiter to separate the catalog and command name.
160      */
161     public Command getCommand(String commandName) {
162         String catalogName = DEFAULT_CATALOG;
163         if (StringUtils.contains(commandName, COMMAND_DELIM)) {
164             catalogName = StringUtils.substringBefore(commandName, COMMAND_DELIM);
165             commandName = StringUtils.substringAfter(commandName, COMMAND_DELIM);
166         }
167 
168         Command command = getCommand(catalogName, commandName);
169         if (command == null) {
170             command = getCommand(DEFAULT_CATALOG, commandName);
171         }
172         return command;
173     }
174 
175     /**
176      * @return Returns the instance.
177      * @deprecated since 4.5, use IoC !
178      */
179     @Deprecated
180     public static CommandsManager getInstance() {
181         return Components.getComponent(CommandsManager.class);
182     }
183 
184     /**
185      * Executes the given command at the given catalog with the given
186      * parameters.
187      * 
188      * @throws Exception
189      * if an error occurs during command execution or if the command
190      * could not be found in any catalog.
191      */
192     public boolean executeCommand(final String catalogName, final String commandName, final Map<String, Object> params) throws Exception {
193         final Command command = getCommand(catalogName, commandName);
194         if (command == null) {
195             throw new Exception(String.format("Command [%s] could not be found in catalog [%s]", commandName, catalogName));
196         }
197         log.debug("Executing command [{}] from catalog [{}] and params [{}]...", new Object[] { commandName, catalogName, params });
198         return executeCommand(command, params);
199     }
200 
201     /**
202      * Executes the given command by first looking in the default catalog.
203      * Should the command not be found, it will try to look in all other
204      * catalogs.
205      * 
206      * @see CommandsManager#executeCommand(String, String, Map)
207      */
208     public boolean executeCommand(final String commandName, final Map<String, Object> params) throws Exception {
209         return executeCommand(DEFAULT_CATALOG, commandName, params);
210     }
211 
212     /**
213      * Executes the given command.
214      * 
215      * @see CommandsManager#executeCommand(String, Map)
216      */
217     public boolean executeCommand(final Command command, final Map<String, Object> params) throws Exception {
218         return executeCommand(command, params, new SimpleContext());
219     }
220 
221     /**
222      * Executes the given command with given context.
223      *
224      * @see CommandsManager#executeCommand(String, Map)
225      */
226     public boolean executeCommand(final Command command, final Map<String, Object> params, Context context) throws Exception {
227         if (params != null) {
228             context.putAll(params);
229         }
230         return command.execute(context);
231     }
232 
233     Catalog getCatalogByName(String name) {
234         return catalogs.get(name);
235     }
236 
237 }