<commit_before>/*
 * CODENVY CONFIDENTIAL
 * __________________
 *
 *  [2012] - [2015] Codenvy, S.A.
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Codenvy S.A. and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Codenvy S.A.
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Codenvy S.A..
 */
package com.codenvy.im.agent;

import com.codenvy.im.commands.decorators.PuppetErrorInterrupter;
import com.codenvy.im.console.Console;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author <NAME>
 * @author <NAME>
 */
public class LocalAgent extends AbstractAgent {
    private static final Logger LOG = Logger.getLogger(LocalAgent.class.getSimpleName());

    protected final static String READ_PASSWORD_PROMPT              = String.format("[sudo] password for %s: ", System.getProperty("user.name"));
    protected static final String CHECK_PASSWORD_NECESSITY_COMMAND  = "ERROR=$(sudo -n true 2>&1); if [[ $? != 0 ]] ; then echo $ERROR; fi";
    protected static final String CHECK_IS_PASSWORD_CORRECT_COMMAND = "sudo -S true";
    protected static final String PASSWORD_INCORRECT_STATUS         = "Sorry, try again";
    protected static final String NEED_PASSWORD_MESSAGE             = "sudo: a password is required";

    private static char[] pwdCache = null;

    public LocalAgent() {
    }

    /** {@inheritDoc} */
    @Override
    public String execute(String command) throws AgentException {
        if (isPasswordInputRequired(command)) {
            return executeWithPassword(command);
        } else {
            return executeWithoutPassword(command);
        }
    }

    private String executeWithPassword(String command) throws AgentException {
        // workaround to issue CDEC-460 where there was sudo password prompt thrown from IM in time of installing Codenvy
        if (PuppetErrorInterrupter.isReadPuppetLogCommand(command)) {
            LOG.log(Level.WARNING, "It is impossible to read puppet log: sudo right is required");    // ignore to don't interrupt installation
            return "";
        }

        if (pwdCache == null) {
            pwdCache = obtainPassword();
        }

        try {
            String commandWhichIsReadPasswordFromInput =
                    command.replace("sudo ", "sudo -S ");  // make sudo be able to read password from input stream
            Process process = getProcess(commandWhichIsReadPasswordFromInput);
            passPasswordToProcess(process, pwdCache);
            int exitStatus = process.waitFor();

            InputStream in = process.getInputStream();
            InputStream err = process.getErrorStream();

            return processOutput(exitStatus, in, err);
        } catch (Exception e) {
            String errMessage = String.format("Can't execute command '%s'.", command);
            throw makeAgentException(errMessage, e);
        }
    }

    private String executeWithoutPassword(String command) throws AgentException {
        try {
            Process process = getProcess(command);

            int exitStatus = process.waitFor();
            InputStream in = process.getInputStream();
            InputStream err = process.getErrorStream();

            return processOutput(exitStatus, in, err);
        } catch (Exception e) {
            String errMessage = String.format("Can't execute command '%s'.", command);
            throw makeAgentException(errMessage, e);
        }
    }

    protected void passPasswordToProcess(Process process, char[] pwd) throws UnsupportedEncodingException {
        OutputStreamWriter osw = new OutputStreamWriter(process.getOutputStream(), "UTF-8");
        final PrintWriter stdIn = new PrintWriter(osw);

        for (char ch : pwd) {
            stdIn.append(ch);
        }

        stdIn.append('\n');
        stdIn.flush();
    }

    protected boolean isPasswordInputRequired(String command) {
        if (!command.contains("sudo ")) {
            return false;
        }

        // REST request then
        if (!isConsoleAccessible()) {
            return false;
        }

        try {
            String result = executeWithoutPassword(CHECK_PASSWORD_NECESSITY_COMMAND);

            if ((result != null) && result.contains(NEED_PASSWORD_MESSAGE)) {
                LOG.log(Level.WARNING, "Command '%s' requires sudo password");
                return true;
            }
            
            return false;

        } catch (Exception e) {
            LOG.log(Level.SEVERE, "Can't verify requirement of sudo password", e);
            return false;
        }
    }

    protected char[] obtainPassword() throws AgentException, IllegalStateException {
        Console console = getConsole();
<commit_msg>CDEC-460: fix error message<commit_after>/*
 * CODENVY CONFIDENTIAL
 * __________________
 *
 *  [2012] - [2015] Codenvy, S.A.
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Codenvy S.A. and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Codenvy S.A.
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Codenvy S.A..
 */
package com.codenvy.im.agent;

import com.codenvy.im.commands.decorators.PuppetErrorInterrupter;
import com.codenvy.im.console.Console;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author <NAME>
 * @author <NAME>vnov
 */
public class LocalAgent extends AbstractAgent {
    private static final Logger LOG = Logger.getLogger(LocalAgent.class.getSimpleName());

    protected final static String READ_PASSWORD_PROMPT              = String.format("[sudo] password for %s: ", System.getProperty("user.name"));
    protected static final String CHECK_PASSWORD_NECESSITY_COMMAND  = "ERROR=$(sudo -n true 2>&1); if [[ $? != 0 ]] ; then echo $ERROR; fi";
    protected static final String CHECK_IS_PASSWORD_CORRECT_COMMAND = "sudo -S true";
    protected static final String PASSWORD_INCORRECT_STATUS         = "Sorry, try again";
    protected static final String NEED_PASSWORD_MESSAGE             = "sudo: a password is required";

    private static char[] pwdCache = null;

    public LocalAgent() {
    }

    /** {@inheritDoc} */
    @Override
    public String execute(String command) throws AgentException {
        if (isPasswordInputRequired(command)) {
            return executeWithPassword(command);
        } else {
            return executeWithoutPassword(command);
        }
    }

    private String executeWithPassword(String command) throws AgentException {
        // workaround to issue CDEC-460 where there was sudo password prompt thrown from IM in time of installing Codenvy
        if (PuppetErrorInterrupter.isReadPuppetLogCommand(command)) {
            LOG.log(Level.WARNING, "It is impossible to read puppet log: sudo right is required");    // ignore to don't interrupt installation
            return "";
        }

        if (pwdCache == null) {
            pwdCache = obtainPassword();
        }

        try {
            String commandWhichIsReadPasswordFromInput =
                    command.replace("sudo ", "sudo -S ");  // make sudo be able to read password from input stream
            Process process = getProcess(commandWhichIsReadPasswordFromInput);
            passPasswordToProcess(process, pwdCache);
            int exitStatus = process.waitFor();

            InputStream in = process.getInputStream();
            InputStream err = process.getErrorStream();

            return processOutput(exitStatus, in, err);
        } catch (Exception e) {
            String errMessage = String.format("Can't execute command '%s'.", command);
            throw makeAgentException(errMessage, e);
        }
    }

    private String executeWithoutPassword(String command) throws AgentException {
        try {
            Process process = getProcess(command);

            int exitStatus = process.waitFor();
            InputStream in = process.getInputStream();
            InputStream err = process.getErrorStream();

            return processOutput(exitStatus, in, err);
        } catch (Exception e) {
            String errMessage = String.format("Can't execute command '%s'.", command);
            throw makeAgentException(errMessage, e);
        }
    }

    protected void passPasswordToProcess(Process process, char[] pwd) throws UnsupportedEncodingException {
        OutputStreamWriter osw = new OutputStreamWriter(process.getOutputStream(), "UTF-8");
        final PrintWriter stdIn = new PrintWriter(osw);

        for (char ch : pwd) {
            stdIn.append(ch);
        }

        stdIn.append('\n');
        stdIn.flush();
    }

    protected boolean isPasswordInputRequired(String command) {
        if (!command.contains("sudo ")) {
            return false;
        }

        // REST request then
        if (!isConsoleAccessible()) {
            return false;
        }

        try {
            String result = executeWithoutPassword(CHECK_PASSWORD_NECESSITY_COMMAND);

            if ((result != null) && result.contains(NEED_PASSWORD_MESSAGE)) {
                LOG.log(Level.WARNING, String.format("Command '%s' requires sudo password", command));
                return true;
            }
            
            return false;

        } catch (Exception e) {
            LOG.log(Level.SEVERE, "Can't verify requirement of sudo password", e);
            return false;
        }
    }

    protected char[] obtainPassword() throws AgentException, IllegalStateException {
        Console console = getConsole();

{'fraction_non_alphanumeric': 0.09193883330186899, 'fraction_numerical': 0.0031149707381536718, 'mean_word_length': 2.6597582037996546, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5454188', 'n_tokens_mistral': 2795, 'n_tokens_neox': 2658, 'n_words': 822}