/*
* (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Nuxeo - initial API and implementation
*
*/
package org.nuxeo.ecm.platform.commandline.executor.service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.common.Environment;
import org.nuxeo.ecm.platform.commandline.executor.api.CmdParameters;
import org.nuxeo.ecm.platform.commandline.executor.api.CommandAvailability;
import org.nuxeo.ecm.platform.commandline.executor.api.CommandLineExecutorService;
import org.nuxeo.ecm.platform.commandline.executor.api.CommandNotAvailable;
import org.nuxeo.ecm.platform.commandline.executor.api.ExecResult;
import org.nuxeo.ecm.platform.commandline.executor.service.cmdtesters.CommandTestResult;
import org.nuxeo.ecm.platform.commandline.executor.service.cmdtesters.CommandTester;
import org.nuxeo.ecm.platform.commandline.executor.service.executors.Executor;
import org.nuxeo.ecm.platform.commandline.executor.service.executors.ShellExecutor;
import org.nuxeo.runtime.model.ComponentContext;
import org.nuxeo.runtime.model.ComponentInstance;
import org.nuxeo.runtime.model.DefaultComponent;
/**
* POJO implementation of the {@link CommandLineExecutorService} interface. Also handles the Extension Point logic.
*
* @author tiry
*/
public class CommandLineExecutorComponent extends DefaultComponent implements CommandLineExecutorService {
public static final String EP_ENV = "environment";
public static final String EP_CMD = "command";
public static final String EP_CMDTESTER = "commandTester";
public static final String DEFAULT_TESTER = "DefaultCommandTester";
public static final String DEFAULT_EXECUTOR = "ShellExecutor";
protected static Map<String, CommandLineDescriptor> commandDescriptors = new HashMap<>();
protected static EnvironmentDescriptor env = new EnvironmentDescriptor();
protected static Map<String, EnvironmentDescriptor> envDescriptors = new HashMap<>();
protected static Map<String, CommandTester> testers = new HashMap<>();
protected static Map<String, Executor> executors = new HashMap<>();
private static final Log log = LogFactory.getLog(CommandLineExecutorComponent.class);
@Override
public void activate(ComponentContext context) {
commandDescriptors = new HashMap<>();
env = new EnvironmentDescriptor();
testers = new HashMap<>();
executors = new HashMap<>();
executors.put(DEFAULT_EXECUTOR, new ShellExecutor());
}
@Override
public void deactivate(ComponentContext context) {
commandDescriptors = null;
env = null;
testers = null;
executors = null;
}
@Override
public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
if (EP_ENV.equals(extensionPoint)) {
EnvironmentDescriptor desc = (EnvironmentDescriptor) contribution;
String name = desc.getName();
if (name == null) {
env.merge(desc);
} else {
for (String envName : name.split(",")) {
if (envDescriptors.containsKey(envName)) {
envDescriptors.get(envName).merge(desc);
} else {
envDescriptors.put(envName, desc);
}
}
}
} else if (EP_CMD.equals(extensionPoint)) {
CommandLineDescriptor desc = (CommandLineDescriptor) contribution;
String name = desc.getName();
log.debug("Registering command: " + name);
if (!desc.isEnabled()) {
commandDescriptors.remove(name);
log.info("Command configured to not be enabled: " + name);
return;
}
String testerName = desc.getTester();
if (testerName == null) {
testerName = DEFAULT_TESTER;
log.debug("Using default tester for command: " + name);
}
CommandTester tester = testers.get(testerName);
boolean cmdAvailable = false;
if (tester == null) {
log.error("Unable to find tester '" + testerName + "', command will not be available: " + name);
} else {
log.debug("Using tester '" + testerName + "' for command: " + name);
CommandTestResult testResult = tester.test(desc);
cmdAvailable = testResult.succeed();
if (cmdAvailable) {
log.info("Registered command: " + name);
} else {
desc.setInstallErrorMessage(testResult.getErrorMessage());
log.warn("Command not available: " + name + " (" + desc.getInstallErrorMessage() + ". "
+ desc.getInstallationDirective() + ')');
}
}
desc.setAvailable(cmdAvailable);
commandDescriptors.put(name, desc);
} else if (EP_CMDTESTER.equals(extensionPoint)) {
CommandTesterDescriptor desc = (CommandTesterDescriptor) contribution;
CommandTester tester;
try {
tester = (CommandTester) desc.getTesterClass().newInstance();
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
testers.put(desc.getName(), tester);
}
}
@Override
public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
}
/*
* Service interface
*/
@Override
public ExecResult execCommand(String commandName, CmdParameters params) throws CommandNotAvailable {
CommandAvailability availability = getCommandAvailability(commandName);
if (!availability.isAvailable()) {
throw new CommandNotAvailable(availability);
}
CommandLineDescriptor cmdDesc = commandDescriptors.get(commandName);
Executor executor = executors.get(cmdDesc.getExecutor());
EnvironmentDescriptor environment = new EnvironmentDescriptor().merge(env).merge(
envDescriptors.getOrDefault(commandName, envDescriptors.get(cmdDesc.getCommand())));
return executor.exec(cmdDesc, params, environment);
}
@Override
public CommandAvailability getCommandAvailability(String commandName) {
if (!commandDescriptors.containsKey(commandName)) {
return new CommandAvailability(commandName + " is not a registered command");
}
CommandLineDescriptor desc = commandDescriptors.get(commandName);
if (desc.isAvailable()) {
return new CommandAvailability();
} else {
return new CommandAvailability(desc.getInstallationDirective(), desc.getInstallErrorMessage());
}
}
@Override
public List<String> getRegistredCommands() {
List<String> cmds = new ArrayList<>();
cmds.addAll(commandDescriptors.keySet());
return cmds;
}
@Override
public List<String> getAvailableCommands() {
List<String> cmds = new ArrayList<>();
for (String cmdName : commandDescriptors.keySet()) {
CommandLineDescriptor cmd = commandDescriptors.get(cmdName);
if (cmd.isAvailable()) {
cmds.add(cmdName);
}
}
return cmds;
}
// ******************************************
// for testing
public static CommandLineDescriptor getCommandDescriptor(String commandName) {
return commandDescriptors.get(commandName);
}
@Override
public CmdParameters getDefaultCmdParameters() {
CmdParameters params = new CmdParameters();
params.addNamedParameter("java.io.tmpdir", System.getProperty("java.io.tmpdir"));
params.addNamedParameter(Environment.NUXEO_TMP_DIR, Environment.getDefault().getTemp().getPath());
return params;
}
}