001/*
002 * (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *     tdelprat, jcarsique
017 *
018 */
019
020package org.nuxeo.ecm.platform.commandline.executor.service.executors;
021
022import java.io.File;
023import java.io.IOException;
024import java.util.ArrayList;
025import java.util.Collections;
026import java.util.List;
027
028import org.apache.commons.lang.ArrayUtils;
029import org.apache.commons.lang.StringUtils;
030import org.apache.commons.lang3.SystemUtils;
031import org.apache.commons.logging.Log;
032import org.apache.commons.logging.LogFactory;
033import org.apache.commons.logging.impl.SimpleLog;
034
035import org.nuxeo.ecm.platform.commandline.executor.api.CmdParameters;
036import org.nuxeo.ecm.platform.commandline.executor.api.ExecResult;
037import org.nuxeo.ecm.platform.commandline.executor.service.CommandLineDescriptor;
038import org.nuxeo.ecm.platform.commandline.executor.service.EnvironmentDescriptor;
039import org.nuxeo.log4j.ThreadedStreamGobbler;
040
041/**
042 * Default implementation of the {@link Executor} interface. Use simple shell exec.
043 *
044 * @author tiry
045 */
046public class ShellExecutor extends AbstractExecutor {
047
048    private static final Log log = LogFactory.getLog(ShellExecutor.class);
049
050    @Deprecated
051    @Override
052    public ExecResult exec(CommandLineDescriptor cmdDesc, CmdParameters params) {
053        return exec(cmdDesc, params, new EnvironmentDescriptor());
054    }
055
056    @Override
057    public ExecResult exec(CommandLineDescriptor cmdDesc, CmdParameters params, EnvironmentDescriptor env) {
058        long t0 = System.currentTimeMillis();
059        List<String> output = Collections.synchronizedList(new ArrayList<String>());
060
061        String[] cmd;
062        try {
063            if (SystemUtils.IS_OS_WINDOWS) {
064                String[] paramsArray = getParametersArray(cmdDesc, params);
065                cmd = new String[] { "cmd", "/C", cmdDesc.getCommand() };
066                cmd = (String[]) ArrayUtils.addAll(cmd, paramsArray);
067            } else {
068                String paramsString = getParametersString(cmdDesc, params);
069                cmd = new String[] { "/bin/sh", "-c", cmdDesc.getCommand() + " " + paramsString };
070            }
071        } catch (IllegalArgumentException e) {
072            return new ExecResult(cmdDesc.getCommand(), e);
073        }
074        String commandLine = StringUtils.join(cmd, " ");
075
076        Process p1;
077        try {
078            if (log.isDebugEnabled()) {
079                log.debug("Running system command: " + commandLine);
080            }
081            ProcessBuilder processBuilder = new ProcessBuilder(cmd).directory(new File(env.getWorkingDirectory()));
082            processBuilder.environment().putAll(env.getParameters());
083            p1 = processBuilder.start();
084        } catch (IOException e) {
085            return new ExecResult(commandLine, e);
086        }
087
088        ThreadedStreamGobbler out, err;
089        if (cmdDesc.getReadOutput()) {
090            out = new ThreadedStreamGobbler(p1.getInputStream(), output);
091            err = new ThreadedStreamGobbler(p1.getErrorStream(), output);
092        } else {
093            out = new ThreadedStreamGobbler(p1.getInputStream(), SimpleLog.LOG_LEVEL_DEBUG);
094            err = new ThreadedStreamGobbler(p1.getErrorStream(), SimpleLog.LOG_LEVEL_ERROR);
095        }
096
097        err.start();
098        out.start();
099
100        int exitCode = 0;
101        try {
102            exitCode = p1.waitFor();
103            out.join();
104            err.join();
105        } catch (InterruptedException e) {
106            return new ExecResult(commandLine, e);
107        }
108
109        long t1 = System.currentTimeMillis();
110        return new ExecResult(commandLine, output, t1 - t0, exitCode);
111    }
112}