au.com.permeance.liferay.portlet.patchingtoolinfo.cli.PatchingToolCommandRunner.java Source code

Java tutorial

Introduction

Here is the source code for au.com.permeance.liferay.portlet.patchingtoolinfo.cli.PatchingToolCommandRunner.java

Source

/**
* Copyright (C) 2015-present by Permeance Technologies
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If
* not, see <http://www.gnu.org/licenses/>.
*/

package au.com.permeance.liferay.portlet.patchingtoolinfo.cli;

import au.com.permeance.liferay.portlet.patchingtoolinfo.util.StringHelper;

import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.OSDetector;
import com.liferay.portal.kernel.util.StringPool;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.IOUtils;

/**
 * Patching Tool Command Runner.
 * 
 * @author Tim Telcik <tim.telcik@permeance.com.au>
 * 
 * @see PatchingToolResults
 */
public class PatchingToolCommandRunner {

    private static final Log LOG = LogFactoryUtil.getLog(PatchingToolCommandRunner.class);

    private static final String MS_WINDOWS_SHELL_FILE_EXT = ".bat";

    private static final String UNIX_LINUX_SHELL_FILE_EXT = ".sh";

    private static final String MS_WINDOWS_SHELL_NAME = "cmd";

    private static final String MS_WINDOWS_SHELL_OPTION = "/c";

    private static final String UNIX_LINUX_SHELL_NAME = "/bin/sh";

    private static final String PATCHING_TOOL_HOME_FOLDER_NAME = "patching-tool";

    private static final String PATCHING_TOOL_SCRIPT_BASE_NAME = "patching-tool";

    private static final String SYS_PROP_KEY_LIFERAY_HOME = "liferay.home";

    private List<String> patchingToolOptions = new ArrayList<String>();

    private PatchingToolResults patchingToolResults = new PatchingToolResults();

    public PatchingToolCommandRunner() {
    }

    public void setPatchingToolOptions(List<String> options) {
        if (options == null) {
            options = new ArrayList<String>();
        }
        this.patchingToolOptions = options;
    }

    public List<String> getPatchingToolOptions() {
        return patchingToolOptions;
    }

    public PatchingToolResults getPatchingToolResults() {
        return patchingToolResults;
    }

    public void runCommand() throws Exception {

        if (LOG.isDebugEnabled()) {
            LOG.debug("running patching tool command ...");
        }

        try {

            ProcessBuilder processBuilder = configureProcessBuilder();

            // NOTE: ProcessBuilder#environent is initialised with System.getenv()
            // @see http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment%28%29

            if (LOG.isDebugEnabled()) {
                LOG.debug("processBuilder : " + processBuilder);
                List<String> commandList = processBuilder.command();
                LOG.debug("command environment : " + processBuilder.environment());
                LOG.debug("command list : " + commandList);
                LOG.debug("command directory : " + processBuilder.directory());
            }

            if (LOG.isDebugEnabled()) {
                List<String> commandList = processBuilder.command();
                String processCommandStr = StringHelper.flattenStringList(commandList);
                LOG.debug("running patching tool command : " + processCommandStr);
            }

            Process process = processBuilder.start();

            if (LOG.isDebugEnabled()) {
                LOG.debug("process : " + process);
            }

            // NOTE: Java 1.8 supports Process#waitFor with a timeout
            // eg. boolean finished = iostat.waitFor(100, TimeUnit.MILLISECONDS);

            int processExitValue = process.waitFor();

            List<String> processOutputLines = IOUtils.readLines(process.getInputStream());

            List<String> processErrorLines = IOUtils.readLines(process.getErrorStream());

            this.patchingToolResults = new PatchingToolResults(processExitValue, processOutputLines,
                    processErrorLines);

            if (LOG.isDebugEnabled()) {
                LOG.debug("patchingToolResults: " + patchingToolResults);
            }

            if (LOG.isDebugEnabled()) {
                LOG.debug("patching tool returned exit code " + this.patchingToolResults.getExitValue());
                LOG.debug("patching tool returned " + this.patchingToolResults.getOutputLines().size()
                        + " output lines");
                LOG.debug("--- COMMAND OUTPUT ---");
                LOG.debug(processOutputLines);
                LOG.debug("patching tool returned " + this.patchingToolResults.getErrorLines().size()
                        + " error lines");
                LOG.debug("--- COMMAND ERROR ---");
                LOG.debug(processErrorLines);
            }

            // NOTE: Command shell may return lines in the error stream that are warning messages, not errors.
            // Hence, we cannot rely upon content in the error stream as a valid error.

            if (this.patchingToolResults.getExitValue() != 0) {
                StringBuilder sb = new StringBuilder();
                String errorLine1 = null;
                if (this.patchingToolResults.hasErrorLines()) {
                    errorLine1 = this.patchingToolResults.getErrorLines().get(0);
                }
                if (errorLine1 == null) {
                    sb.append("Error running patching tool command.");
                    sb.append(" See portal logs for more details.");
                } else {
                    sb.append("Error running patching tool command : ");
                    sb.append(errorLine1);
                }
                String errMsg = sb.toString();
                throw new Exception(errMsg);
            }

        } catch (Exception e) {

            String msg = "Error executing patching tool command : " + e.getMessage();
            LOG.error(msg, e);
            throw new Exception(msg, e);
        }
    }

    private ProcessBuilder configureProcessBuilder() throws Exception {

        String liferayHomePath = System.getProperty(SYS_PROP_KEY_LIFERAY_HOME);

        if (LOG.isDebugEnabled()) {
            LOG.debug(SYS_PROP_KEY_LIFERAY_HOME + " : " + liferayHomePath);
        }

        if (liferayHomePath == null) {
            String msg = "Liferay Home property is undefined";
            LOG.error(msg);
            throw new Exception(msg);
        }

        String patchingToolHomePath = liferayHomePath + File.separator + PATCHING_TOOL_HOME_FOLDER_NAME;

        File patchingToolHomeDir = new File(patchingToolHomePath);

        if (LOG.isDebugEnabled()) {
            LOG.debug("patchingToolHomeDir : " + patchingToolHomeDir);
        }

        if (!patchingToolHomeDir.exists()) {
            String msg = "Patching tool home folder does not exist : " + patchingToolHomeDir.getAbsolutePath();
            LOG.error(msg);
            throw new Exception(msg);
        }

        String patchingToolScriptName = buildPatchingToolScriptName();

        if (LOG.isDebugEnabled()) {
            LOG.debug("patchingToolScriptName : " + patchingToolScriptName);
        }

        String patchingToolScriptPath = patchingToolHomePath + File.separator + buildPatchingToolScriptName();

        if (LOG.isDebugEnabled()) {
            LOG.debug("patchingToolScriptPath : " + patchingToolScriptPath);
        }

        File patchingToolScriptFile = new File(patchingToolScriptPath);

        if (LOG.isDebugEnabled()) {
            LOG.debug("patchingToolScriptFile : " + patchingToolScriptFile);
        }

        if (!patchingToolScriptFile.exists()) {
            String msg = "Patching tool script does not exist : " + patchingToolScriptFile.getAbsolutePath();
            LOG.error(msg);
            throw new Exception(msg);
        }

        List<String> commandList = new ArrayList<String>();

        List<String> shellCommand = buildShellCommand();

        if (LOG.isDebugEnabled()) {
            LOG.debug("shellCommand : " + shellCommand);
        }

        commandList.addAll(shellCommand);

        commandList.add(patchingToolScriptName);

        if (LOG.isDebugEnabled()) {
            LOG.debug("patchingToolOptions : " + getPatchingToolOptions());
        }

        if (!getPatchingToolOptions().isEmpty()) {
            commandList.addAll(getPatchingToolOptions());
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("commandList : " + commandList);
        }

        ProcessBuilder pb = new ProcessBuilder(commandList);

        pb.directory(patchingToolHomeDir);

        return pb;
    }

    private List<String> buildShellCommand() {

        List<String> commandList = new ArrayList<String>();

        if (OSDetector.isWindows()) {
            commandList.add(MS_WINDOWS_SHELL_NAME);
            commandList.add(MS_WINDOWS_SHELL_OPTION);
        } else {
            commandList.add(UNIX_LINUX_SHELL_NAME);
        }

        return commandList;
    }

    private String buildPatchingToolScriptName() throws Exception {

        String shellScriptExt = StringPool.BLANK;

        if (OSDetector.isWindows()) {
            shellScriptExt = MS_WINDOWS_SHELL_FILE_EXT;
        } else {
            shellScriptExt = UNIX_LINUX_SHELL_FILE_EXT;
        }

        String patchingToolScriptName = PATCHING_TOOL_SCRIPT_BASE_NAME + shellScriptExt;

        String command = patchingToolScriptName;

        return command;
    }

}