/**
* This file Copyright (c) 2003-2013 Magnolia International
* Ltd. (http://www.magnolia-cms.com). All rights reserved.
*
*
* This file is dual-licensed under both the Magnolia
* Network Agreement and the GNU General Public License.
* You may elect to use one or the other of these licenses.
*
* This file is distributed in the hope that it will be
* useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
* Redistribution, except as permitted by whichever of the GPL
* or MNA you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or
* modify this file under the terms of the GNU General
* Public License, Version 3, as published by the Free Software
* Foundation. You should have received a copy of the GNU
* General Public License, Version 3 along with this program;
* if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 2. For the Magnolia Network Agreement (MNA), this file
* and the accompanying materials are made available under the
* terms of the MNA which accompanies this distribution, and
* is available at http://www.magnolia-cms.com/mna.html
*
* Any modifications to this file must keep this entire header
* intact.
*
*/
package info.magnolia.commands;
import info.magnolia.cms.beans.config.ObservedManager;
import info.magnolia.cms.core.Content;
import info.magnolia.commands.chain.Catalog;
import info.magnolia.commands.chain.Command;
import info.magnolia.commands.chain.Context;
import info.magnolia.context.MgnlContext;
import info.magnolia.jcr.node2bean.Node2BeanException;
import info.magnolia.jcr.node2bean.Node2BeanProcessor;
import info.magnolia.jcr.util.NodeTypes;
import info.magnolia.objectfactory.Components;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.RepositoryException;
import org.apache.commons.lang.StringUtils;
/**
* Manages the Commands and Catalogs.
*
*/
@Singleton
public class CommandsManager extends ObservedManager {
public static final String DEFAULT_CATALOG = "default";
public static final String COMMAND_DELIM = "-";
private final CommandTransformer commandTransformer;
private final Node2BeanProcessor nodeToBean;
private Map<String, MgnlCatalog> catalogs;
@Inject
public CommandsManager(Node2BeanProcessor nodeToBean) {
this.nodeToBean = nodeToBean;
this.commandTransformer = new CommandTransformer();
this.catalogs = new HashMap<String, MgnlCatalog>();
}
/**
* Register observation for command catalogs.
*/
@Override
protected void onRegister(Content node) {
// is this a catalog or a collection of catalogs?
if (node.getChildren(NodeTypes.Content.NAME).size() == 0) {
registerCatalog(node);
}
else{
for (Iterator iter = node.getChildren(NodeTypes.Content.NAME).iterator(); iter.hasNext();) {
onRegister((Content) iter.next());
}
}
}
protected void registerCatalog(Content node) {
log.info("Registering commands at {}...", node.getHandle());
try {
MgnlCatalog catalog = (MgnlCatalog) nodeToBean.toBean(node.getJCRNode(), true, commandTransformer, Components.getComponentProvider());
MgnlCatalog current = catalogs.get(catalog.getName());
if (current == null) {
catalogs.put(catalog.getName(), catalog);
log.info("Catalog [{}] registered: {}", catalog.getName(), catalog);
} else {
Iterator<String> names = catalog.getNames();
while (names.hasNext()) {
String commandName = names.next();
Command command = current.getCommand(commandName);
if (command != null) {
log.warn(String.format("Command [%s] found at [%s] already exists in the catalog [%s], skipping...", commandName, node.getHandle(), current.getName()));
} else {
log.info("Adding new command [{}] to already registered catalog [{}]...", commandName, current.getName());
current.addCommand(commandName, catalog.getCommand(commandName));
}
}
}
}
catch (RepositoryException e) {
log.error("Can't read catalog [" + node + "]", e);
}
catch (Node2BeanException e) {
log.error("Can't create catalog [" + node + "]", e);
}
}
/**
* Clear all catalogs.
*/
@Override
protected void onClear() {
catalogs.clear();
}
/**
* Get the command.
* @param catalogName the catalog containing the command
* @param commandName the name of the command
* @return the command to execute
*/
public Command getCommand(String catalogName, String commandName) {
// if empty catalog name, use default catalog
MgnlCatalog catalog = catalogs.get(StringUtils.isNotEmpty(catalogName) ? catalogName : DEFAULT_CATALOG);
if (catalog != null) {
Command command = catalog.getCommand(commandName);
try {
if (command != null) {
return command.getClass().newInstance();
}
} catch (IllegalAccessException iae) {
log.warn("Cannot create new instance of command [" + commandName + "] from catalog [" + catalogName + "].", iae);
} catch (InstantiationException ie) {
log.warn("Cannot create new instance of command [" + commandName + "] from catalog [" + catalogName + "].", ie);
}
}
return null;
}
/**
* Use a delimiter to separate the catalog and command name.
*/
public Command getCommand(String commandName) {
String catalogName = DEFAULT_CATALOG;
if (StringUtils.contains(commandName, COMMAND_DELIM)) {
catalogName = StringUtils.substringBefore(commandName, COMMAND_DELIM);
commandName = StringUtils.substringAfter(commandName, COMMAND_DELIM);
}
Command command = getCommand(catalogName, commandName);
if (command == null) {
command = getCommand(DEFAULT_CATALOG, commandName);
}
return command;
}
/**
* @return Returns the instance.
* @deprecated since 4.5, use IoC !
*/
@Deprecated
public static CommandsManager getInstance() {
return Components.getComponent(CommandsManager.class);
}
/**
* Executes the given command at the given catalog with the given parameters.
*
* @throws Exception if an error occurs during command execution or if the command could not be found in any catalog.
*/
public boolean executeCommand(final String catalogName, final String commandName, final Map<String, Object> params) throws Exception {
final Command command = getCommand(catalogName, commandName);
if (command == null) {
throw new Exception(String.format("Command [%s] could not be found in catalog [%s]", commandName, catalogName));
}
log.debug("Executing command [{}] from catalog [{}] and params [{}]...", new Object[] { commandName, catalogName, params });
return executeCommand(command, params);
}
/**
* Executes the given command by first looking in the default catalog.
* Should the command not be found, it will try to look in all other catalogs.
*
* @see CommandsManager#executeCommand(String, String, Map)
*/
public boolean executeCommand(final String commandName, final Map<String, Object> params) throws Exception {
return executeCommand(DEFAULT_CATALOG, commandName, params);
}
/**
* Executes the given command.
*
* @see CommandsManager#executeCommand(String, Map)
*/
public boolean executeCommand(final Command command, final Map<String, Object> params) throws Exception {
Context context = MgnlContext.getInstance();
if (params != null) {
for (Entry<String, Object> param : params.entrySet()) {
context.put(param.getKey(), param.getValue());
}
}
return command.execute(context);
}
Catalog getCatalogByName(String name) {
return catalogs.get(name);
}
}