brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [34/64] incubator-brooklyn git commit: [BROOKLYN-162] Refactor package in ./core/util
Date Tue, 18 Aug 2015 11:00:49 GMT
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/internal/ssh/ShellAbstractTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/ShellAbstractTool.java b/core/src/main/java/brooklyn/util/internal/ssh/ShellAbstractTool.java
deleted file mode 100644
index 5c839a9..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/ShellAbstractTool.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-package brooklyn.util.internal.ssh;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.io.ByteArrayInputStream;
-import java.io.Closeable;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.os.Os;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.text.StringEscapes.BashStringEscapes;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-
-public abstract class ShellAbstractTool implements ShellTool {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ShellAbstractTool.class);
-
-    protected final File localTempDir;
-
-    public ShellAbstractTool(String localTempDir) {
-        this(localTempDir == null ? null : new File(Os.tidyPath(localTempDir)));
-    }
-    
-    public ShellAbstractTool(File localTempDir) {
-        if (localTempDir == null) {
-            localTempDir = new File(Os.tmp(), "tmpssh-"+Os.user());
-            if (!localTempDir.exists()) localTempDir.mkdir();
-            Os.deleteOnExitEmptyParentsUpTo(localTempDir, new File(Os.tmp()));
-        }
-        this.localTempDir = localTempDir;
-    }
-    
-    public ShellAbstractTool() {
-        this((File)null);
-    }
-    
-    protected static void warnOnDeprecated(Map<String, ?> props, String deprecatedKey, String correctKey) {
-        if (props.containsKey(deprecatedKey)) {
-            if (correctKey != null && props.containsKey(correctKey)) {
-                Object dv = props.get(deprecatedKey);
-                Object cv = props.get(correctKey);
-                if (!Objects.equal(cv, dv)) {
-                    LOG.warn("SshTool detected deprecated key '"+deprecatedKey+"' with different value ("+dv+") "+
-                            "than new key '"+correctKey+"' ("+cv+"); ambiguous which will be used");
-                } else {
-                    // ignore, the deprecated key populated for legacy reasons
-                }
-            } else {
-                Object dv = props.get(deprecatedKey);
-                LOG.warn("SshTool detected deprecated key '"+deprecatedKey+"' used, with value ("+dv+")");     
-            }
-        }
-    }
-
-    protected static Boolean hasVal(Map<String,?> map, ConfigKey<?> keyC) {
-        String key = keyC.getName();
-        return map.containsKey(key);
-    }
-    
-    protected static <T> T getMandatoryVal(Map<String,?> map, ConfigKey<T> keyC) {
-        String key = keyC.getName();
-        checkArgument(map.containsKey(key), "must contain key '"+keyC+"'");
-        return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
-    }
-    
-    public static <T> T getOptionalVal(Map<String,?> map, ConfigKey<T> keyC) {
-        if (keyC==null) return null;
-        String key = keyC.getName();
-        if (map!=null && map.containsKey(key) && map.get(key) != null) {
-            return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
-        } else {
-            return keyC.getDefaultValue();
-        }
-    }
-
-    /** returns the value of the key if specified, otherwise defaultValue */
-    protected static <T> T getOptionalVal(Map<String,?> map, ConfigKey<T> keyC, T defaultValue) {
-        String key = keyC.getName();
-        if (map!=null && map.containsKey(key) && map.get(key) != null) {
-            return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
-        } else {
-            return defaultValue;
-        }
-    }
-
-    protected void closeWhispering(Closeable closeable, Object context) {
-        closeWhispering(closeable, this, context);
-    }
-    
-    /**
-     * Similar to Guava's Closeables.closeQuitely, except logs exception at debug with context in message.
-     */
-    protected static void closeWhispering(Closeable closeable, Object context1, Object context2) {
-        if (closeable != null) {
-            try {
-                closeable.close();
-            } catch (IOException e) {
-                if (LOG.isDebugEnabled()) {
-                    String msg = String.format("<< exception during close, for %s -> %s (%s); continuing.", 
-                            context1, context2, closeable);
-                    if (LOG.isTraceEnabled())
-                        LOG.debug(msg + ": " + e);
-                    else
-                        LOG.trace(msg, e);
-                }
-            }
-        }
-    }
-
-    protected File writeTempFile(InputStream contents) {
-        File tempFile = Os.writeToTempFile(contents, localTempDir, "sshcopy", "data");
-        tempFile.setReadable(false, false);
-        tempFile.setReadable(true, true);
-        tempFile.setWritable(false);
-        tempFile.setExecutable(false);
-        return tempFile;
-    }
-
-    protected File writeTempFile(String contents) {
-        return writeTempFile(contents.getBytes());
-    }
-
-    protected File writeTempFile(byte[] contents) {
-        return writeTempFile(new ByteArrayInputStream(contents));
-    }
-
-    protected String toScript(Map<String,?> props, List<String> commands, Map<String,?> env) {
-        List<String> allcmds = toCommandSequence(commands, env);
-        StringBuilder result = new StringBuilder();
-        result.append(getOptionalVal(props, PROP_SCRIPT_HEADER)).append('\n');
-        
-        for (String cmd : allcmds) {
-            result.append(cmd).append('\n');
-        }
-        
-        return result.toString();
-    }
-
-    /**
-     * Merges the commands and env, into a single set of commands. Also escapes the commands as required.
-     * 
-     * Not all ssh servers handle "env", so instead convert env into exported variables
-     */
-    protected List<String> toCommandSequence(List<String> commands, Map<String,?> env) {
-        List<String> result = new ArrayList<String>((env!=null ? env.size() : 0) + commands.size());
-        
-        if (env!=null) {
-            for (Entry<String,?> entry : env.entrySet()) {
-                if (entry.getKey() == null || entry.getValue() == null) {
-                    LOG.warn("env key-values must not be null; ignoring: key="+entry.getKey()+"; value="+entry.getValue());
-                    continue;
-                }
-                String escapedVal = BashStringEscapes.escapeLiteralForDoubleQuotedBash(entry.getValue().toString());
-                result.add("export "+entry.getKey()+"=\""+escapedVal+"\"");
-            }
-        }
-        for (CharSequence cmd : commands) { // objects in commands can be groovy GString so can't treat as String here
-            result.add(cmd.toString());
-        }
-
-        return result;
-    }
-
-    @Override
-    public int execScript(Map<String,?> props, List<String> commands) {
-        return execScript(props, commands, Collections.<String,Object>emptyMap());
-    }
-
-    @Override
-    public int execCommands(Map<String,?> props, List<String> commands) {
-        return execCommands(props, commands, Collections.<String,Object>emptyMap());
-    }
-
-    protected static int asInt(Integer input, int valueIfInputNull) {
-        return input != null ? input : valueIfInputNull;
-    }
-
-    protected abstract class ToolAbstractExecScript {
-        protected final Map<String, ?> props;
-        protected final String separator;
-        protected final OutputStream out;
-        protected final OutputStream err;
-        protected final String scriptDir;
-        protected final Boolean runAsRoot;
-        protected final Boolean noExtraOutput;
-        protected final Boolean noDeleteAfterExec;
-        protected final String scriptNameWithoutExtension;
-        protected final String scriptPath;
-        protected final Duration execTimeout;
-
-        public ToolAbstractExecScript(Map<String,?> props) {
-            this.props = props;
-            this.separator = getOptionalVal(props, PROP_SEPARATOR);
-            this.out = getOptionalVal(props, PROP_OUT_STREAM);
-            this.err = getOptionalVal(props, PROP_ERR_STREAM);
-            
-            this.scriptDir = getOptionalVal(props, PROP_SCRIPT_DIR);
-            this.runAsRoot = getOptionalVal(props, PROP_RUN_AS_ROOT);
-            this.noExtraOutput = getOptionalVal(props, PROP_NO_EXTRA_OUTPUT);
-            this.noDeleteAfterExec = getOptionalVal(props, PROP_NO_DELETE_SCRIPT);
-            this.execTimeout = getOptionalVal(props, PROP_EXEC_TIMEOUT);
-            
-            String summary = getOptionalVal(props, PROP_SUMMARY);
-            if (summary!=null) {
-                summary = Strings.makeValidFilename(summary);
-                if (summary.length()>30) 
-                    summary = summary.substring(0,30);
-            }
-            this.scriptNameWithoutExtension = "brooklyn-"+
-                    Time.makeDateStampString()+"-"+Identifiers.makeRandomId(4)+
-                    (Strings.isBlank(summary) ? "" : "-"+summary);
-            this.scriptPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension+".sh");
-        }
-
-        /** builds the command to run the given script;
-         * note that some modes require \$RESULT passed in order to access a variable, whereas most just need $ */
-        protected List<String> buildRunScriptCommand() {
-            MutableList.Builder<String> cmds = MutableList.<String>builder()
-                    .add((runAsRoot ? BashCommands.sudo(scriptPath) : scriptPath) + " < /dev/null")
-                    .add("RESULT=$?");
-            if (noExtraOutput==null || !noExtraOutput)
-                cmds.add("echo Executed "+scriptPath+", result $RESULT"); 
-            if (noDeleteAfterExec!=Boolean.TRUE) {
-                // use "-f" because some systems have "rm" aliased to "rm -i"
-                // use "< /dev/null" to guarantee doesn't hang
-                cmds.add("rm -f "+scriptPath+" < /dev/null");
-            }
-            cmds.add("exit $RESULT");
-            return cmds.build();
-        }
-
-        protected String getSummary() {
-            String summary = getOptionalVal(props, PROP_SUMMARY);
-            return (summary != null) ? summary : scriptPath; 
-        }
-
-        public abstract int run();
-    }
-    
-    protected abstract class ToolAbstractAsyncExecScript extends ToolAbstractExecScript {
-        protected final String stdoutPath;
-        protected final String stderrPath;
-        protected final String exitStatusPath;
-        protected final String pidPath;
-
-        public ToolAbstractAsyncExecScript(Map<String,?> props) {
-            super(props);
-
-            stdoutPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".stdout");
-            stderrPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".stderr");
-            exitStatusPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".exitstatus");
-            pidPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".pid");
-        }
-
-        /**
-         * Builds the command to run the given script, asynchronously.
-         * The executed command will return immediately, but the output from the script
-         * will continue to be written 
-         * note that some modes require \$RESULT passed in order to access a variable, whereas most just need $ */
-        @Override
-        protected List<String> buildRunScriptCommand() {
-            String touchCmd = String.format("touch %s %s %s %s", stdoutPath, stderrPath, exitStatusPath, pidPath);
-            String cmd = String.format("nohup sh -c \"( %s > %s 2> %s < /dev/null ) ; echo \\$? > %s \" > /dev/null 2>&1 < /dev/null &", scriptPath, stdoutPath, stderrPath, exitStatusPath);
-            MutableList.Builder<String> cmds = MutableList.<String>builder()
-                    .add(runAsRoot ? BashCommands.sudo(touchCmd) : touchCmd)
-                    .add(runAsRoot ? BashCommands.sudo(cmd) : cmd)
-                    .add("echo $! > "+pidPath)
-                    .add("RESULT=$?");
-            if (noExtraOutput==null || !noExtraOutput) {
-                cmds.add("echo Executing async "+scriptPath);
-            }
-            cmds.add("exit $RESULT");
-            return cmds.build();
-        }
-
-        /**
-         * Builds the command to retrieve the exit status of the command, written to stdout.
-         */
-        protected List<String> buildRetrieveStatusCommand() {
-            // Retrieve exit status from file (writtent to stdout), if populated;
-            // if not found and pid still running, then return empty string; else exit code 1.
-            List<String> cmdParts = ImmutableList.of(
-                    "# Retrieve status", // comment is to aid testing - see SshjToolAsyncStubIntegrationTest
-                    "if test -s "+exitStatusPath+"; then",
-                    "    cat "+exitStatusPath,
-                    "elif test -s "+pidPath+"; then",
-                    "    pid=`cat "+pidPath+"`",
-                    "    if ! ps -p $pid > /dev/null < /dev/null; then",
-                    "        # no exit status, and not executing; give a few seconds grace in case just about to write exit status",
-                    "        sleep 3",
-                    "        if test -s "+exitStatusPath+"; then",
-                    "            cat "+exitStatusPath+"",
-                    "        else",
-                    "            echo \"No exit status in "+exitStatusPath+", and pid in "+pidPath+" ($pid) not executing\"",
-                    "            exit 1",
-                    "        fi",
-                    "    fi",
-                    "else",
-                    "    echo \"No exit status in "+exitStatusPath+", and "+pidPath+" is empty\"",
-                    "    exit 1",
-                    "fi"+"\n");
-            String cmd = Joiner.on("\n").join(cmdParts);
-
-            MutableList.Builder<String> cmds = MutableList.<String>builder()
-                    .add((runAsRoot ? BashCommands.sudo(cmd) : cmd))
-                    .add("RESULT=$?");
-            cmds.add("exit $RESULT");
-            return cmds.build();
-        }
-
-        /**
-         * Builds the command to retrieve the stdout and stderr of the async command.
-         * An offset can be given, to only retrieve data starting at a particular character (indexed from 0).
-         */
-        protected List<String> buildRetrieveStdoutAndStderrCommand(int stdoutPosition, int stderrPosition) {
-            // Note that `tail -c +1` means start at the *first* character (i.e. start counting from 1, not 0)
-            String catStdoutCmd = "tail -c +"+(stdoutPosition+1)+" "+stdoutPath+" 2> /dev/null";
-            String catStderrCmd = "tail -c +"+(stderrPosition+1)+" "+stderrPath+" 2>&1 > /dev/null";
-            MutableList.Builder<String> cmds = MutableList.<String>builder()
-                    .add((runAsRoot ? BashCommands.sudo(catStdoutCmd) : catStdoutCmd))
-                    .add((runAsRoot ? BashCommands.sudo(catStderrCmd) : catStderrCmd))
-                    .add("RESULT=$?");
-            cmds.add("exit $RESULT");
-            return cmds.build();
-        }
-
-        /**
-         * Builds the command to retrieve the stdout and stderr of the async command.
-         * An offset can be given, to only retrieve data starting at a particular character (indexed from 0).
-         */
-        protected List<String> buildLongPollCommand(int stdoutPosition, int stderrPosition, Duration timeout) {
-            long maxTime = Math.max(1, timeout.toSeconds());
-            
-            // Note that `tail -c +1` means start at the *first* character (i.e. start counting from 1, not 0)
-            List<String> waitForExitStatusParts = ImmutableList.of(
-                    //Should be careful here because any output will be part of the stdout/stderr streams
-                    "# Long poll", // comment is to aid testing - see SshjToolAsyncStubIntegrationTest
-                    // disown to avoid Terminated message after killing the process
-                    // redirect error output to avoid "file truncated" messages
-                    "tail -c +"+(stdoutPosition+1)+" -f "+stdoutPath+" 2> /dev/null & export TAIL_STDOUT_PID=$!; disown",
-                    "tail -c +"+(stderrPosition+1)+" -f "+stderrPath+" 1>&2 2> /dev/null & export TAIL_STDERR_PID=$!; disown",
-                    "EXIT_STATUS_PATH="+exitStatusPath,
-                    "PID_PATH="+pidPath,
-                    "MAX_TIME="+maxTime,
-                    "COUNTER=0",
-                    "while [ \"$COUNTER\" -lt $MAX_TIME ]; do",
-                    "    if test -s $EXIT_STATUS_PATH; then",
-                    "        EXIT_STATUS=`cat $EXIT_STATUS_PATH`",
-                    "        kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
-                    "        exit $EXIT_STATUS",
-                    "    elif test -s $PID_PATH; then",
-                    "        PID=`cat $PID_PATH`",
-                    "        if ! ps -p $PID > /dev/null 2>&1 < /dev/null; then",
-                    "            # no exit status, and not executing; give a few seconds grace in case just about to write exit status",
-                    "            sleep 3",
-                    "            if test -s $EXIT_STATUS_PATH; then",
-                    "                EXIT_STATUS=`cat $EXIT_STATUS_PATH`",
-                    "                kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
-                    "                exit $EXIT_STATUS",
-                    "            else",
-                    "                echo \"No exit status in $EXIT_STATUS_PATH, and pid in $PID_PATH ($PID) not executing\"",
-                    "                kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
-                    "                exit 126",
-                    "            fi",
-                    "        fi",
-                    "    fi",
-                    "    # No exit status in $EXIT_STATUS_PATH; keep waiting",
-                    "    sleep 1",
-                    "    COUNTER+=1",
-                    "done",
-                    "kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
-                    "exit 125"+"\n");
-            String waitForExitStatus = Joiner.on("\n").join(waitForExitStatusParts);
-
-            return ImmutableList.of(runAsRoot ? BashCommands.sudo(waitForExitStatus) : waitForExitStatus);
-        }
-
-        protected List<String> deleteTemporaryFilesCommand() {
-            ImmutableList.Builder<String> cmdParts = ImmutableList.builder();
-            
-            if (!Boolean.TRUE.equals(noDeleteAfterExec)) {
-                // use "-f" because some systems have "rm" aliased to "rm -i"
-                // use "< /dev/null" to guarantee doesn't hang
-                cmdParts.add(
-                        "rm -f "+scriptPath+" "+stdoutPath+" "+stderrPath+" "+exitStatusPath+" "+pidPath+" < /dev/null");
-            }
-            
-            // If the buildLongPollCommand didn't complete properly then it might have left tail command running;
-            // ensure they are killed.
-            cmdParts.add(
-                    //ignore error output for the case where there are no running processes and kill is called without arguments
-                    "ps aux | grep \"tail -c\" | grep \""+stdoutPath+"\" | grep -v grep | awk '{ printf $2 }' | xargs kill 2> /dev/null",
-                    "ps aux | grep \"tail -c\" | grep \""+stderrPath+"\" | grep -v grep | awk '{ printf $2 }' | xargs kill 2> /dev/null");
-
-            String cmd = Joiner.on("\n").join(cmdParts.build());
-            
-            return ImmutableList.of(runAsRoot ? BashCommands.sudo(cmd) : cmd);
-        }
-
-        @Override
-        public abstract int run();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/internal/ssh/ShellTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/ShellTool.java b/core/src/main/java/brooklyn/util/internal/ssh/ShellTool.java
deleted file mode 100644
index 0555039..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/ShellTool.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-package brooklyn.util.internal.ssh;
-
-import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
-import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
-
-import java.io.OutputStream;
-import java.util.List;
-import java.util.Map;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.os.Os;
-import brooklyn.util.time.Duration;
-
-/** Methods for executing things in an environment (localhost process, or ssh) */
-public interface ShellTool {
-
-    // config which applies to sessions
-    
-    public static final ConfigKey<String> PROP_LOCAL_TEMP_DIR = newStringConfigKey(
-            "localTempDir", 
-            "The directory on the local machine (i.e. running brooklyn) for writing temp files", 
-            Os.mergePaths(Os.tmp(), "brooklyn-"+Os.user()+"-ssh-tmp"));
-    
-    // config which applies to calls:
-    
-    public static final ConfigKey<Boolean> PROP_RUN_AS_ROOT = newConfigKey("runAsRoot", "When running a script, whether to run as root", Boolean.FALSE);
-    
-    public static final ConfigKey<OutputStream> PROP_OUT_STREAM = newConfigKey(OutputStream.class, "out", "Stream to which to capture stdout");
-    public static final ConfigKey<OutputStream> PROP_ERR_STREAM = newConfigKey(OutputStream.class, "err", "Stream to which to capture stderr");
-    
-    public static final ConfigKey<Boolean> PROP_NO_EXTRA_OUTPUT = newConfigKey("noExtraOutput", "Suppresses any decorative output such as result code which some tool commands insert", false);
-    
-    public static final ConfigKey<String> PROP_SEPARATOR = newConfigKey("separator", "string to insert between caller-supplied commands being executed as commands", " ; ");
-    
-    public static final ConfigKey<String> PROP_SCRIPT_DIR = newConfigKey("scriptDir", "directory where scripts should be copied", "/tmp");
-    public static final ConfigKey<String> PROP_SCRIPT_HEADER = newConfigKey("scriptHeader", "lines to insert at the start of scripts generated for caller-supplied commands for script execution", "#!/bin/bash -e\n");
-    public static final ConfigKey<String> PROP_DIRECT_HEADER = newConfigKey("directHeader", "commands to run at the target before any caller-supplied commands for direct execution", "exec bash -e");
-
-    ConfigKey<Boolean> PROP_NO_DELETE_SCRIPT = newConfigKey("noDeleteAfterExec", "Retains the generated script file after executing the commands instead of deleting it", false);
-
-    ConfigKey<String> PROP_SUMMARY = ConfigKeys.newStringConfigKey("summary", "Provides a human-readable summary, used in file generation etc");
-    
-    ConfigKey<Duration> PROP_EXEC_TIMEOUT = newConfigKey("execTimeout", "Timeout when executing a script", Duration.PRACTICALLY_FOREVER);
-
-    ConfigKey<Boolean> PROP_EXEC_ASYNC = newConfigKey("execAsync", "Executes the script asynchronously, and then polls for the result (and for stdout/stderr)", false);
-
-    ConfigKey<Duration> PROP_EXEC_ASYNC_POLLING_TIMEOUT = newConfigKey("execAsyncPollTimeout", "Timeout per poll when executing a script asynchronously", Duration.ONE_MINUTE);
-
-    /**
-     * Executes the set of commands in a shell script. Blocks until completion.
-     * <p>
-     * 
-     * Optional properties are the same common ones as for {@link #execCommands(Map, List, Map)} with the addition of:
-     * <ul>
-     * <li>{@link #PROP_RUN_AS_ROOT}
-     * <li>{@link #PROP_SCRIPT_DIR}
-     * </ul>
-     * 
-     * @return exit status of script
-     */
-    public int execScript(Map<String,?> props, List<String> commands, Map<String,?> env);
-
-    /**
-     * @see #execScript(Map, List, Map)
-     */
-    public int execScript(Map<String,?> props, List<String> commands);
-
-    /**
-     * Executes the set of commands using ssh exec.
-     * 
-     * This is generally more efficient than ssh shell mode (cf {@link #execScript(Map, List, Map)}), 
-     * but is not suitable if you need env values which are only set on a fully-fledged shell,
-     * or if you want the entire block executed with root permission.
-     *
-     * Common optional properties (which also apply to {@link #execScript(Map, List, Map)}) are:
-     * <ul>
-     * <li>{@link #PROP_OUT_STREAM}
-     * <li>{@link #PROP_ERR_STREAM}
-     * <li>{@link #PROP_SEPARATOR} (for some modes)
-     * <li>{@link #PROP_NO_EXTRA_OUTPUT} (often there is no extra output here)
-     * </ul>
-     * 
-     * Note that {@link #PROP_RUN_AS_ROOT} is <i>not</i> typically supported here. Prefer {@link #execScript(Map, List, Map)}).
-     * 
-     * @return exit status of commands
-     */
-    public int execCommands(Map<String,?> properties, List<String> commands, Map<String,?> env);
-
-    /**
-     * @see #execCommands(Map, List, Map)
-     */
-    public int execCommands(Map<String,?> properties, List<String> commands);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/internal/ssh/SshAbstractTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/SshAbstractTool.java b/core/src/main/java/brooklyn/util/internal/ssh/SshAbstractTool.java
deleted file mode 100644
index eb0222a..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/SshAbstractTool.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-package brooklyn.util.internal.ssh;
-
-import static brooklyn.util.net.Networking.checkPortValid;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.File;
-import java.util.Map;
-import java.util.Set;
-
-import brooklyn.util.os.Os;
-
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-
-public abstract class SshAbstractTool extends ShellAbstractTool implements SshTool {
-
-    protected final String toString;
-
-    protected final String host;
-    protected final String user;
-    protected final String password;
-    protected final int port;
-    protected String privateKeyPassphrase;
-    protected String privateKeyData;
-    protected File privateKeyFile;
-    protected boolean strictHostKeyChecking;
-    protected boolean allocatePTY;
-
-    public static interface SshAction<T> {
-        void clear() throws Exception;
-        T create() throws Exception;
-    }
-
-    public static abstract class AbstractSshToolBuilder<T extends SshTool, B extends AbstractSshToolBuilder<T,B>> {
-        protected String host;
-        protected int port = 22;
-        protected String user = System.getProperty("user.name");
-        protected String password;
-        protected String privateKeyData;
-        protected String privateKeyPassphrase;
-        protected Set<String> privateKeyFiles = Sets.newLinkedHashSet();
-        protected boolean strictHostKeyChecking = false;
-        protected boolean allocatePTY = false;
-        protected File localTempDir = null;
-
-        @SuppressWarnings("unchecked")
-        protected B self() {
-           return (B) this;
-        }
-
-        public B from(Map<String,?> props) {
-            host = getMandatoryVal(props, PROP_HOST);
-            port = getOptionalVal(props, PROP_PORT);
-            user = getOptionalVal(props, PROP_USER);
-            
-            password = getOptionalVal(props, PROP_PASSWORD);
-            
-            warnOnDeprecated(props, "privateKey", "privateKeyData");
-            privateKeyData = getOptionalVal(props, PROP_PRIVATE_KEY_DATA);
-            privateKeyPassphrase = getOptionalVal(props, PROP_PRIVATE_KEY_PASSPHRASE);
-            
-            // for backwards compatibility accept keyFiles and privateKey
-            // but sshj accepts only a single privateKeyFile; leave blank to use defaults (i.e. ~/.ssh/id_rsa and id_dsa)
-            warnOnDeprecated(props, "keyFiles", null);
-            String privateKeyFile = getOptionalVal(props, PROP_PRIVATE_KEY_FILE);
-            if (privateKeyFile != null) privateKeyFiles.add(privateKeyFile);
-            
-            strictHostKeyChecking = getOptionalVal(props, PROP_STRICT_HOST_KEY_CHECKING);
-            allocatePTY = getOptionalVal(props, PROP_ALLOCATE_PTY);
-            
-            String localTempDirPath = getOptionalVal(props, PROP_LOCAL_TEMP_DIR);
-            localTempDir = (localTempDirPath == null) ? null : new File(Os.tidyPath(localTempDirPath));
-            
-            return self();
-        }
-        public B host(String val) {
-            this.host = val; return self();
-        }
-        public B user(String val) {
-            this.user = val; return self();
-        }
-        public B password(String val) {
-            this.password = val; return self();
-        }
-        public B port(int val) {
-            this.port = val; return self();
-        }
-        public B privateKeyPassphrase(String val) {
-            this.privateKeyPassphrase = val; return self();
-        }
-        /** @deprecated 1.4.0, use privateKeyData */
-        public B privateKey(String val) {
-            this.privateKeyData = val; return self();
-        }
-        public B privateKeyData(String val) {
-            this.privateKeyData = val; return self();
-        }
-        public B privateKeyFile(String val) {
-            this.privateKeyFiles.add(val); return self();
-        }
-        public B localTempDir(File val) {
-            this.localTempDir = val; return self();
-        }
-        public abstract T build();
-    }
-
-    protected SshAbstractTool(AbstractSshToolBuilder<?,?> builder) {
-        super(builder.localTempDir);
-        
-        host = checkNotNull(builder.host, "host");
-        port = builder.port;
-        user = builder.user;
-        password = builder.password;
-        strictHostKeyChecking = builder.strictHostKeyChecking;
-        allocatePTY = builder.allocatePTY;
-        privateKeyPassphrase = builder.privateKeyPassphrase;
-        privateKeyData = builder.privateKeyData;
-        
-        if (builder.privateKeyFiles.size() > 1) {
-            throw new IllegalArgumentException("sshj supports only a single private key-file; " +
-                    "for defaults of ~/.ssh/id_rsa and ~/.ssh/id_dsa leave blank");
-        } else if (builder.privateKeyFiles.size() == 1) {
-            String privateKeyFileStr = Iterables.get(builder.privateKeyFiles, 0);
-            String amendedKeyFile = privateKeyFileStr.startsWith("~") ? (System.getProperty("user.home")+privateKeyFileStr.substring(1)) : privateKeyFileStr;
-            privateKeyFile = new File(amendedKeyFile);
-        } else {
-            privateKeyFile = null;
-        }
-        
-        checkArgument(host.length() > 0, "host value must not be an empty string");
-        checkPortValid(port, "ssh port");
-        
-        toString = String.format("%s@%s:%d", user, host, port);
-    }
-
-    @Override
-    public String toString() {
-        return toString;
-    }
-
-    public String getHostAddress() {
-        return this.host;
-    }
-
-    public String getUsername() {
-        return this.user;
-    }
-
-    protected SshException propagate(Exception e, String message) throws SshException {
-        throw new SshException("(" + toString() + ") " + message + ": " + e.getMessage(), e);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/internal/ssh/SshException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/SshException.java b/core/src/main/java/brooklyn/util/internal/ssh/SshException.java
deleted file mode 100644
index 20653bb..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/SshException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-package brooklyn.util.internal.ssh;
-
-public class SshException extends RuntimeException {
-
-    private static final long serialVersionUID = -5690230838066860965L;
-
-    public SshException(String msg) {
-        super(msg);
-    }
-    
-    public SshException(String msg, Throwable cause) {
-        super(msg, cause);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/internal/ssh/SshTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/SshTool.java b/core/src/main/java/brooklyn/util/internal/ssh/SshTool.java
deleted file mode 100644
index a676599..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/SshTool.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-package brooklyn.util.internal.ssh;
-
-import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
-import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.stream.KnownSizeInputStream;
-import brooklyn.util.time.Duration;
-
-/**
- * Defines the methods available on the various different implementations of SSH,
- * and configuration options which are also generally available.
- * <p>
- * The config keys in this class can be supplied (or their string equivalents, where the flags/props take {@code Map<String,?>})
- * to influence configuration, either for the tool/session itself or for individual commands.
- * <p>
- * To specify some of these properties on a global basis, use the variants of the keys here
- * contained in {@link ConfigKeys}
- * (which are generally {@value #BROOKLYN_CONFIG_KEY_PREFIX} prefixed to the names of keys here).
- */
-public interface SshTool extends ShellTool {
-    
-    /** Public-facing global config keys for Brooklyn are defined in ConfigKeys, 
-     * and have this prefix pre-prended to the config keys in this class. 
-     * These keys are detected from entity/global config and automatically applied to ssh executions. */
-    public static final String BROOKLYN_CONFIG_KEY_PREFIX = "brooklyn.ssh.config.";
-    
-    public static final ConfigKey<String> PROP_TOOL_CLASS = newStringConfigKey("tool.class", "SshTool implementation to use", null);
-    
-    public static final ConfigKey<String> PROP_HOST = newStringConfigKey("host", "Host to connect to (required)", null);
-    public static final ConfigKey<Integer> PROP_PORT = newConfigKey("port", "Port on host to connect to", 22);
-    public static final ConfigKey<String> PROP_USER = newConfigKey("user", "User to connect as", System.getProperty("user.name"));
-    public static final ConfigKey<String> PROP_PASSWORD = newStringConfigKey("password", "Password to use to connect", null);
-    
-    public static final ConfigKey<String> PROP_PRIVATE_KEY_FILE = newStringConfigKey("privateKeyFile", "the path of an ssh private key file; leave blank to use defaults (i.e. ~/.ssh/id_rsa and id_dsa)", null);
-    public static final ConfigKey<String> PROP_PRIVATE_KEY_DATA = newStringConfigKey("privateKeyData", "the private ssh key (e.g. contents of an id_rsa or id_dsa file)", null);
-    public static final ConfigKey<String> PROP_PRIVATE_KEY_PASSPHRASE = newStringConfigKey("privateKeyPassphrase", "the passphrase for the ssh private key", null);
-    public static final ConfigKey<Boolean> PROP_STRICT_HOST_KEY_CHECKING = newConfigKey("strictHostKeyChecking", "whether to check the remote host's identification; defaults to false", false);
-    public static final ConfigKey<Boolean> PROP_ALLOCATE_PTY = newConfigKey("allocatePTY", "whether to allocate PTY (vt100); if true then stderr is sent to stdout, but sometimes required for sudo'ing due to requiretty", false);
-
-    public static final ConfigKey<Long> PROP_CONNECT_TIMEOUT = newConfigKey("connectTimeout", "Timeout in millis when establishing an SSH connection; if 0 then uses default (usually 30s)", 0L);
-    public static final ConfigKey<Long> PROP_SESSION_TIMEOUT = newConfigKey("sessionTimeout", "Timeout in millis for an ssh session; if 0 then uses default", 0L);
-    public static final ConfigKey<Integer> PROP_SSH_TRIES = newConfigKey("sshTries", "Max number of times to attempt ssh operations", 4);
-    public static final ConfigKey<Long> PROP_SSH_TRIES_TIMEOUT = newConfigKey("sshTriesTimeout", "Time limit for attempting retries; will not interrupt tasks, but stops retrying after a total amount of elapsed time", Duration.TWO_MINUTES.toMilliseconds());
-    public static final ConfigKey<Long> PROP_SSH_RETRY_DELAY = newConfigKey("sshRetryDelay", "Time (in milliseconds) before first ssh-retry, after which it will do exponential backoff", 50L);
-
-    // NB -- items above apply for _session_ (a tool), below apply for a _call_
-    // TODO would be nice to track which arguments are used, so we can indicate whether extras are supplied
-
-    public static final ConfigKey<String> PROP_PERMISSIONS = newConfigKey("permissions", "Default permissions for files copied/created on remote machine; must be four-digit octal string, default '0644'", "0644");
-    public static final ConfigKey<Long> PROP_LAST_MODIFICATION_DATE = newConfigKey("lastModificationDate", "Last-modification-date to be set on files copied/created (should be UTC/1000, ie seconds since 1970; default 0 usually means current)", 0L);
-    public static final ConfigKey<Long> PROP_LAST_ACCESS_DATE = newConfigKey("lastAccessDate", "Last-access-date to be set on files copied/created (should be UTC/1000, ie seconds since 1970; default 0 usually means lastModificationDate)", 0L);
-    public static final ConfigKey<Integer> PROP_OWNER_UID = newConfigKey("ownerUid", "Default owner UID (not username) for files created on remote machine; default is unset", -1);
-    
-    // TODO remove unnecessary "public static final" modifiers
-    
-    // TODO Could define the following in SshMachineLocation, or some such?
-    //public static ConfigKey<String> PROP_LOG_PREFIX = newStringKey("logPrefix", "???", ???);
-    //public static ConfigKey<Boolean> PROP_NO_STDOUT_LOGGING = newStringKey("noStdoutLogging", "???", ???);
-    //public static ConfigKey<Boolean> PROP_NO_STDOUT_LOGGING = newStringKey("noStdoutLogging", "???", ???);
-
-    /**
-     * @throws SshException
-     */
-    public void connect();
-
-    /**
-     * @deprecated since 0.7.0; (since much earlier) this ignores the argument in favour of {@link #PROP_SSH_TRIES}
-     * 
-     * @param maxAttempts
-     * @throws SshException
-     */
-    public void connect(int maxAttempts);
-
-    public void disconnect();
-
-    public boolean isConnected();
-
-    /**
-     * @see super{@link #execScript(Map, List, Map)}
-     * @throws SshException If failed to connect
-     */
-    @Override
-    public int execScript(Map<String,?> props, List<String> commands, Map<String,?> env);
-
-    /**
-     * @see #execScript(Map, List, Map)
-     */
-    @Override
-    public int execScript(Map<String,?> props, List<String> commands);
-
-    /**
-     * @see super{@link #execCommands(Map, List, Map)}
-     * @throws SshException If failed to connect
-     */
-    @Override
-    public int execCommands(Map<String,?> properties, List<String> commands, Map<String,?> env);
-
-    /**
-     * @see #execCommands(Map, List, Map)
-     */
-    @Override
-    public int execCommands(Map<String,?> properties, List<String> commands);
-
-    /**
-     * Copies the file to the server at the given path.
-     * If path is null, empty, '.', '..', or ends with '/' then file name is used.
-     * <p>
-     * The file will not preserve the permission of last _access_ date.
-     * 
-     * Optional properties are:
-     * <ul>
-     *   <li>'permissions' (e.g. "0644") - see {@link #PROP_PERMISSIONS}
-     *   <li>'lastModificationDate' see {@link #PROP_LAST_MODIFICATION_DATE}; not supported by all SshTool implementations
-     *   <li>'lastAccessDate' see {@link #PROP_LAST_ACCESS_DATE}; not supported by all SshTool implementations
-     * </ul>
-     * 
-     * @return exit code (not supported by all SshTool implementations, usually throwing on error;
-     * sometimes possibly returning 0 even on error (?) )
-     */
-    public int copyToServer(Map<String,?> props, File localFile, String pathAndFileOnRemoteServer);
-
-    /**
-     * Closes the given input stream before returning.
-     * Consider using {@link KnownSizeInputStream} for efficiency when the size of the stream is known.
-     * 
-     * @see #copyToServer(Map, File, String)
-     */
-    public int copyToServer(Map<String,?> props, InputStream contents, String pathAndFileOnRemoteServer);
-
-    /**
-     * @see #copyToServer(Map, File, String)
-     */
-    public int copyToServer(Map<String,?> props, byte[] contents, String pathAndFileOnRemoteServer);
-
-    /**
-     * Copies the file from the server at the given path.
-     *
-     * @return exit code (not supported by all SshTool implementations, usually throwing on error;
-     * sometimes possibly returning 0 even on error (?) )
-     */
-    public int copyFromServer(Map<String,?> props, String pathAndFileOnRemoteServer, File local);
-
-    // TODO might be more efficicent than copyFrom by way of temp file
-//    /**
-//     * Reads from the file at the given path on the remote server.
-//     */
-//    public InputStream streamFromServer(Map<String,?> props, String pathAndFileOnRemoteServer);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/internal/ssh/cli/SshCliTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/cli/SshCliTool.java b/core/src/main/java/brooklyn/util/internal/ssh/cli/SshCliTool.java
deleted file mode 100644
index 91b5d91..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/cli/SshCliTool.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-package brooklyn.util.internal.ssh.cli;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.internal.ssh.SshAbstractTool;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.process.ProcessTool;
-import brooklyn.util.text.StringEscapes.BashStringEscapes;
-import brooklyn.util.text.Strings;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-
-/**
- * For ssh and scp commands, delegating to system calls.
- */
-public class SshCliTool extends SshAbstractTool implements SshTool {
-
-    // TODO No retry support, with backoffLimitedRetryHandler
-    
-    private static final Logger LOG = LoggerFactory.getLogger(SshCliTool.class);
-
-    public static final ConfigKey<String> PROP_SSH_EXECUTABLE = ConfigKeys.newStringConfigKey("sshExecutable", "command to execute for ssh (defaults to \"ssh\", but could be overridden to sshg3 for Tectia for example)", "ssh");
-    public static final ConfigKey<String> PROP_SSH_FLAGS = ConfigKeys.newStringConfigKey("sshFlags", "flags to pass to ssh, as a space separated list", "");
-    public static final ConfigKey<String> PROP_SCP_EXECUTABLE = ConfigKeys.newStringConfigKey("scpExecutable", "command to execute for scp (defaults to \"scp\", but could be overridden to scpg3 for Tectia for example)", "scp");
-
-    public static Builder<SshCliTool,?> builder() {
-        return new ConcreteBuilder();
-    }
-    
-    private static class ConcreteBuilder extends Builder<SshCliTool, ConcreteBuilder> {
-    }
-    
-    public static class Builder<T extends SshCliTool, B extends Builder<T,B>> extends AbstractSshToolBuilder<T,B> {
-        private String sshExecutable;
-        private String sshFlags;
-        private String scpExecutable;
-
-        @Override
-        public B from(Map<String,?> props) {
-            super.from(props);
-            sshExecutable = getOptionalVal(props, PROP_SSH_EXECUTABLE);
-            sshFlags = getOptionalVal(props, PROP_SSH_FLAGS);
-            scpExecutable = getOptionalVal(props, PROP_SCP_EXECUTABLE);
-            return self();
-        }
-        public B sshExecutable(String val) {
-            this.sshExecutable = val; return self();
-        }
-        public B scpExecutable(String val) {
-            this.scpExecutable = val; return self();
-        }
-        @SuppressWarnings("unchecked")
-        public T build() {
-            return (T) new SshCliTool(this);
-        }
-    }
-
-    private final String sshExecutable;
-    private final String sshFlags;
-    private final String scpExecutable;
-
-    public SshCliTool(Map<String,?> map) {
-        this(builder().from(map));
-    }
-    
-    private SshCliTool(Builder<?,?> builder) {
-        super(builder);
-        sshExecutable = checkNotNull(builder.sshExecutable);
-        sshFlags = checkNotNull(builder.sshFlags);
-        scpExecutable = checkNotNull(builder.scpExecutable);
-        if (LOG.isTraceEnabled()) LOG.trace("Created SshCliTool {} ({})", this, System.identityHashCode(this));
-    }
-    
-    @Override
-    public void connect() {
-        // no-op
-    }
-
-    @Override
-    public void connect(int maxAttempts) {
-        // no-op
-    }
-
-    @Override
-    public void disconnect() {
-        if (LOG.isTraceEnabled()) LOG.trace("Disconnecting SshCliTool {} ({}) - no-op", this, System.identityHashCode(this));
-        // no-op
-    }
-
-    @Override
-    public boolean isConnected() {
-        // TODO Always pretends to be connected
-        return true;
-    }
-
-    @Override
-    public int copyToServer(java.util.Map<String,?> props, byte[] contents, String pathAndFileOnRemoteServer) {
-        return copyTempFileToServer(props, writeTempFile(contents), pathAndFileOnRemoteServer);
-    }
-    
-    @Override
-    public int copyToServer(java.util.Map<String,?> props, InputStream contents, String pathAndFileOnRemoteServer) {
-        return copyTempFileToServer(props, writeTempFile(contents), pathAndFileOnRemoteServer);
-    }
-    
-    @Override
-    public int copyToServer(Map<String,?> props, File f, String pathAndFileOnRemoteServer) {
-        if (hasVal(props, PROP_LAST_MODIFICATION_DATE)) {
-            LOG.warn("Unsupported ssh feature, setting lastModificationDate for {}:{}", this, pathAndFileOnRemoteServer);
-        }
-        if (hasVal(props, PROP_LAST_ACCESS_DATE)) {
-            LOG.warn("Unsupported ssh feature, setting lastAccessDate for {}:{}", this, pathAndFileOnRemoteServer);
-        }
-        String permissions = getOptionalVal(props, PROP_PERMISSIONS);
-        
-        int uid = getOptionalVal(props, PROP_OWNER_UID);
-        
-        int result = scpToServer(props, f, pathAndFileOnRemoteServer);
-        if (result == 0) {
-            result = chmodOnServer(props, permissions, pathAndFileOnRemoteServer);
-            if (result == 0) {
-                if (uid != -1) {
-                    result = chownOnServer(props, uid, pathAndFileOnRemoteServer);
-                    if (result != 0) {
-                        LOG.warn("Error setting file owner to {}, after copying file {} to {}:{}; exit code {}", new Object[] { uid, pathAndFileOnRemoteServer, this, f, result });
-                    }
-                }
-            } else {
-                LOG.warn("Error setting file permissions to {}, after copying file {} to {}:{}; exit code {}", new Object[] { permissions, pathAndFileOnRemoteServer, this, f, result });
-            }
-        } else {
-            LOG.warn("Error copying file {} to {}:{}; exit code {}", new Object[] {pathAndFileOnRemoteServer, this, f, result});
-        }
-        return result;
-    }
-
-    private int chownOnServer(Map<String,?> props, int uid, String remote) {
-        return sshExec(props, "chown "+uid+" "+remote);
-    }
-    
-    private int copyTempFileToServer(Map<String,?> props, File f, String pathAndFileOnRemoteServer) {
-        try {
-            return copyToServer(props, f, pathAndFileOnRemoteServer);
-        } finally {
-            f.delete();
-        }
-    }
-
-    @Override
-    public int copyFromServer(Map<String,?> props, String pathAndFileOnRemoteServer, File localFile) {
-        return scpFromServer(props, pathAndFileOnRemoteServer, localFile);
-    }
-
-    @Override
-    public int execScript(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
-        return new ToolAbstractExecScript(props) {
-            public int run() {
-                String scriptContents = toScript(props, commands, env);
-                if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {} as script: {}", host, scriptContents);
-                copyTempFileToServer(ImmutableMap.of("permissions", "0700"), writeTempFile(scriptContents), scriptPath);
-
-                String cmd = Strings.join(buildRunScriptCommand(), separator);
-                return asInt(sshExec(props, cmd), -1);
-            }
-        }.run();
-    }
-
-    @Override
-    public int execCommands(Map<String,?> props, List<String> commands, Map<String,?> env) {
-        Map<String,Object> props2 = new MutableMap<String,Object>();
-        if (props!=null) props2.putAll(props);
-        props2.put(SshTool.PROP_NO_EXTRA_OUTPUT.getName(), true);
-        return execScript(props2, commands, env);
-    }
-    
-    private int scpToServer(Map<String,?> props, File local, String remote) {
-        String to = (Strings.isEmpty(getUsername()) ? "" : getUsername()+"@")+getHostAddress()+":"+remote;
-        return scpExec(props, local.getAbsolutePath(), to);
-    }
-
-    private int scpFromServer(Map<String,?> props, String remote, File local) {
-        String from = (Strings.isEmpty(getUsername()) ? "" : getUsername()+"@")+getHostAddress()+":"+remote;
-        return scpExec(props, from, local.getAbsolutePath());
-    }
-    
-    private int chmodOnServer(Map<String,?> props, String permissions, String remote) {
-        return sshExec(props, "chmod "+permissions+" "+remote);
-    }
-
-    private int scpExec(Map<String,?> props, String from, String to) {
-        File tempFile = null;
-        try {
-            List<String> cmd = Lists.newArrayList();
-            cmd.add(getOptionalVal(props, PROP_SCP_EXECUTABLE, scpExecutable));
-            if (privateKeyFile != null) {
-                cmd.add("-i");
-                cmd.add(privateKeyFile.getAbsolutePath());
-            } else if (privateKeyData != null) {
-                tempFile = writeTempFile(privateKeyData);
-                cmd.add("-i");
-                cmd.add(tempFile.getAbsolutePath());
-            }
-            if (!strictHostKeyChecking) {
-                cmd.add("-o");
-                cmd.add("StrictHostKeyChecking=no");
-            }
-            if (port != 22) {
-                cmd.add("-P");
-                cmd.add(""+port);
-            }
-            cmd.add(from);
-            cmd.add(to);
-            
-            if (LOG.isTraceEnabled()) LOG.trace("Executing with command: {}", cmd);
-            int result = execProcess(props, cmd);
-            
-            if (LOG.isTraceEnabled()) LOG.trace("Executed command: {}; exit code {}", cmd, result);
-            return result;
-
-        } finally {
-            if (tempFile != null) tempFile.delete();
-        }
-    }
-    
-    private int sshExec(Map<String,?> props, String command) {
-        File tempKeyFile = null;
-        try {
-            List<String> cmd = Lists.newArrayList();
-            cmd.add(getOptionalVal(props, PROP_SSH_EXECUTABLE, sshExecutable));
-            String propsFlags = getOptionalVal(props, PROP_SSH_FLAGS, sshFlags);
-            if (propsFlags!=null && propsFlags.trim().length()>0)
-                cmd.addAll(Arrays.asList(propsFlags.trim().split(" ")));
-            if (privateKeyFile != null) {
-                cmd.add("-i");
-                cmd.add(privateKeyFile.getAbsolutePath());
-            } else if (privateKeyData != null) {
-                tempKeyFile = writeTempFile(privateKeyData);
-                cmd.add("-i");
-                cmd.add(tempKeyFile.getAbsolutePath());
-            }
-            if (!strictHostKeyChecking) {
-                cmd.add("-o");
-                cmd.add("StrictHostKeyChecking=no");
-            }
-            if (port != 22) {
-                cmd.add("-P");
-                cmd.add(""+port);
-            }
-            if (allocatePTY) {
-                // have to be careful with double -tt as it can leave a shell session active
-                // when done from bash (ie  ssh -tt localhost < /tmp/myscript.sh);
-                // hover that doesn't seem to be a problem the way we use it from brooklyn
-                // (and note single -t doesn't work _programmatically_ since the input isn't a terminal)
-                cmd.add("-tt");
-            }
-            cmd.add((Strings.isEmpty(getUsername()) ? "" : getUsername()+"@")+getHostAddress());
-            
-            cmd.add("bash -c "+BashStringEscapes.wrapBash(command));
-            // previously we tried these approaches:
-            //cmd.add("$(<"+tempCmdFile.getAbsolutePath()+")");
-            // only pays attention to the first word; the "; echo Executing ..." get treated as arguments
-            // to the script in the first word, when invoked from java (when invoked from prompt the behaviour is as desired)
-            //cmd.add("\""+command+"\"");
-            // only works if command is a single word
-            //cmd.add(tempCmdFile.getAbsolutePath());
-            // above of course only works if the metafile is copied across
-            
-            if (LOG.isTraceEnabled()) LOG.trace("Executing ssh with command: {} (with {})", command, cmd);
-            int result = execProcess(props, cmd);
-            
-            if (LOG.isTraceEnabled()) LOG.trace("Executed command: {}; exit code {}", cmd, result);
-            return result;
-            
-        } finally {
-            if (tempKeyFile != null) tempKeyFile.delete();
-        }
-    }
-
-    private int execProcess(Map<String,?> props, List<String> cmdWords) {
-        OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
-        OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
-        return ProcessTool.execSingleProcess(cmdWords, null, (File)null, out, err, this);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/internal/ssh/process/ProcessTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/process/ProcessTool.java b/core/src/main/java/brooklyn/util/internal/ssh/process/ProcessTool.java
deleted file mode 100644
index 90de9f2..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/process/ProcessTool.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-package brooklyn.util.internal.ssh.process;
-
-import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
-import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.internal.ssh.ShellAbstractTool;
-import brooklyn.util.internal.ssh.ShellTool;
-import brooklyn.util.internal.ssh.SshException;
-import brooklyn.util.os.Os;
-import brooklyn.util.stream.StreamGobbler;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Throwables;
-import com.google.common.io.ByteSource;
-import com.google.common.io.ByteStreams;
-import com.google.common.io.Files;
-
-/** Implementation of {@link ShellTool} which runs locally. */
-public class ProcessTool extends ShellAbstractTool implements ShellTool {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ProcessTool.class);
-
-    // applies to calls
-    
-    public static final ConfigKey<Boolean> PROP_LOGIN_SHELL = newConfigKey("loginShell", "Causes the commands to be invoked with bash arguments to forcea  login shell", Boolean.FALSE);
-
-    public static final ConfigKey<String> PROP_DIRECTORY = newStringConfigKey("directory", "the working directory, for executing commands", null);
-    
-    public ProcessTool() {
-        this(null);
-    }
-    
-    public ProcessTool(Map<String,?> flags) {
-        super(getOptionalVal(flags, PROP_LOCAL_TEMP_DIR));
-        if (flags!=null) {
-            MutableMap<String, Object> flags2 = MutableMap.copyOf(flags);
-            // TODO should remember other flags here?  (e.g. NO_EXTRA_OUTPUT, RUN_AS_ROOT, etc)
-            flags2.remove(PROP_LOCAL_TEMP_DIR.getName());
-            if (!flags2.isEmpty())
-                LOG.warn(""+this+" ignoring unsupported constructor flags: "+flags);
-        }
-    }
-
-    @Override
-    public int execScript(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
-        return new ToolAbstractExecScript(props) {
-            public int run() {
-                try {
-                    String directory = getOptionalVal(props, PROP_DIRECTORY);
-                    File directoryDir = (directory != null) ? new File(Os.tidyPath(directory)) : null;
-                    
-                    String scriptContents = toScript(props, commands, env);
-
-                    if (LOG.isTraceEnabled()) LOG.trace("Running shell process (process) as script:\n{}", scriptContents);
-                    File to = new File(scriptPath);
-                    Files.createParentDirs(to);
-                    ByteSource.wrap(scriptContents.getBytes()).copyTo(Files.asByteSink(to));
-
-                    List<String> cmds = buildRunScriptCommand();
-                    cmds.add(0, "chmod +x "+scriptPath);
-                    return asInt(execProcesses(cmds, null, directoryDir, out, err, separator, getOptionalVal(props, PROP_LOGIN_SHELL), this), -1);
-                } catch (IOException e) {
-                    throw Throwables.propagate(e);
-                }
-            }
-        }.run();
-    }
-
-    @Override
-    public int execCommands(Map<String,?> props, List<String> commands, Map<String,?> env) {
-        if (Boolean.FALSE.equals(props.get("blocks"))) {
-            throw new IllegalArgumentException("Cannot exec non-blocking: command="+commands);
-        }
-        OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
-        OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
-        String separator = getOptionalVal(props, PROP_SEPARATOR);
-        String directory = getOptionalVal(props, PROP_DIRECTORY);
-        File directoryDir = (directory != null) ? new File(Os.tidyPath(directory)) : null;
-
-        List<String> allcmds = toCommandSequence(commands, null);
-
-        String singlecmd = Joiner.on(separator).join(allcmds);
-        if (Boolean.TRUE.equals(getOptionalVal(props, PROP_RUN_AS_ROOT))) {
-            LOG.warn("Cannot run as root when executing as command; run as a script instead (will run as normal user): "+singlecmd);
-        }
-        if (LOG.isTraceEnabled()) LOG.trace("Running shell command (process): {}", singlecmd);
-        
-        return asInt(execProcesses(allcmds, env, directoryDir, out, err, separator, getOptionalVal(props, PROP_LOGIN_SHELL), this), -1);
-    }
-
-    /**
-     * as {@link #execProcesses(List, Map, OutputStream, OutputStream, String, boolean, Object)} but not using a login shell
-     * @deprecated since 0.7; use {@link #execProcesses(List, Map, File, OutputStream, OutputStream, String, boolean, Object)}
-     */
-    @Deprecated
-    public static int execProcesses(List<String> cmds, Map<String,?> env, OutputStream out, OutputStream err, String separator, Object contextForLogging) {
-        return execProcesses(cmds, env, (File)null, out, err, separator, false, contextForLogging);
-    }
-
-    /**
-     * @deprecated since 0.7; use {@link #execProcesses(List, Map, File, OutputStream, OutputStream, String, boolean, Object)}
-     */
-    @Deprecated
-    public static int execProcesses(List<String> cmds, Map<String,?> env, OutputStream out, OutputStream err, String separator, boolean asLoginShell, Object contextForLogging) {
-        return execProcesses(cmds, env, (File)null, out, err, separator, asLoginShell, contextForLogging);
-    }
-    
-    /** executes a set of commands by sending them as a single process to `bash -c` 
-     * (single command argument of all the commands, joined with separator)
-     * <p>
-     * consequence of this is that you should not normally need to escape things oddly in your commands, 
-     * type them just as you would into a bash shell (if you find exceptions please note them here!)
-     */
-    public static int execProcesses(List<String> cmds, Map<String,?> env, File directory, OutputStream out, OutputStream err, String separator, boolean asLoginShell, Object contextForLogging) {
-        MutableList<String> commands = new MutableList<String>().append("bash");
-        if (asLoginShell) commands.append("-l");
-        commands.append("-c", Strings.join(cmds, Preconditions.checkNotNull(separator, "separator")));
-        return execSingleProcess(commands, env, directory, out, err, contextForLogging);
-    }
-    
-    /**
-     * @deprecated since 0.7; use {@link #execSingleProcess(List, Map, File, OutputStream, OutputStream, Object)}
-     */
-    @Deprecated
-    public static int execSingleProcess(List<String> cmdWords, Map<String,?> env, OutputStream out, OutputStream err, Object contextForLogging) {
-        return execSingleProcess(cmdWords, env, (File)null, out, err, contextForLogging);
-    }
-    
-    /** executes a single process made up of the given command words (*not* bash escaped);
-     * should be portable across OS's */
-    public static int execSingleProcess(List<String> cmdWords, Map<String,?> env, File directory, OutputStream out, OutputStream err, Object contextForLogging) {
-        StreamGobbler errgobbler = null;
-        StreamGobbler outgobbler = null;
-        
-        ProcessBuilder pb = new ProcessBuilder(cmdWords);
-        if (env!=null) {
-            for (Map.Entry<String,?> kv: env.entrySet()) pb.environment().put(kv.getKey(), String.valueOf(kv.getValue())); 
-        }
-        if (directory != null) {
-            pb.directory(directory);
-        }
-        
-        try {
-            Process p = pb.start();
-            
-            if (out != null) {
-                InputStream outstream = p.getInputStream();
-                outgobbler = new StreamGobbler(outstream, out, (Logger) null);
-                outgobbler.start();
-            }
-            if (err != null) {
-                InputStream errstream = p.getErrorStream();
-                errgobbler = new StreamGobbler(errstream, err, (Logger) null);
-                errgobbler.start();
-            }
-            
-            int result = p.waitFor();
-            
-            if (outgobbler != null) outgobbler.blockUntilFinished();
-            if (errgobbler != null) errgobbler.blockUntilFinished();
-            
-            if (result==255)
-                // this is not definitive, but tests (and code?) expects throw exception if can't connect;
-                // only return exit code when it is exit code from underlying process;
-                // we have no way to distinguish 255 from ssh failure from 255 from the command run through ssh ...
-                // but probably 255 is from CLI ssh
-                throw new SshException("exit code 255 from CLI ssh; probably failed to connect");
-            
-            return result;
-        } catch (InterruptedException e) {
-            throw Exceptions.propagate(e);
-        } catch (IOException e) {
-            throw Exceptions.propagate(e);
-        } finally {
-            closeWhispering(outgobbler, contextForLogging, "execProcess");
-            closeWhispering(errgobbler, contextForLogging, "execProcess");
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/699b3f65/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjClientConnection.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjClientConnection.java b/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjClientConnection.java
deleted file mode 100644
index 982022a..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjClientConnection.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-package brooklyn.util.internal.ssh.sshj;
-
-import static com.google.common.base.Objects.equal;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.File;
-import java.io.IOException;
-
-import net.schmizz.sshj.SSHClient;
-import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
-import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;
-import net.schmizz.sshj.userauth.password.PasswordUtils;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.GroovyJavaMethods;
-import brooklyn.util.internal.ssh.SshAbstractTool.SshAction;
-
-import com.google.common.base.Objects;
-import com.google.common.net.HostAndPort;
-
-/** based on code from jclouds */
-public class SshjClientConnection implements SshAction<SSHClient> {
-
-    private static final Logger LOG = LoggerFactory.getLogger(SshjClientConnection.class);
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    public static class Builder {
-
-        protected HostAndPort hostAndPort;
-        protected String username;
-        protected String password;
-        protected String privateKeyPassphrase;
-        protected String privateKeyData;
-        protected File privateKeyFile;
-        protected long connectTimeout;
-        protected long sessionTimeout;
-        protected boolean strictHostKeyChecking;
-
-        public Builder hostAndPort(HostAndPort hostAndPort) {
-            this.hostAndPort = hostAndPort;
-            return this;
-        }
-
-        public Builder username(String username) {
-            this.username = username;
-            return this;
-        }
-
-        public Builder password(String val) {
-            this.password = val;
-            return this;
-        }
-
-        /** @deprecated use privateKeyData */
-        public Builder privateKey(String val) {
-            this.privateKeyData = val;
-            return this;
-        }
-
-        public Builder privateKeyPassphrase(String val) {
-            this.privateKeyPassphrase = val;
-            return this;
-        }
-        
-        public Builder privateKeyData(String val) {
-            this.privateKeyData = val;
-            return this;
-        }
-        
-        public Builder privateKeyFile(File val) {
-            this.privateKeyFile = val;
-            return this;
-        }
-        
-        public Builder strictHostKeyChecking(boolean val) {
-            this.strictHostKeyChecking = val;
-            return this;
-        }
-
-        public Builder connectTimeout(long connectTimeout) {
-            this.connectTimeout = connectTimeout;
-            return this;
-        }
-
-        public Builder sessionTimeout(long sessionTimeout) {
-            this.sessionTimeout = sessionTimeout;
-            return this;
-        }
-
-        public SshjClientConnection build() {
-            return new SshjClientConnection(this);
-        }
-
-        protected static Builder fromSSHClientConnection(SshjClientConnection in) {
-            return new Builder().hostAndPort(in.getHostAndPort()).connectTimeout(in.getConnectTimeout()).sessionTimeout(
-                    in.getSessionTimeout()).username(in.username).password(in.password).privateKey(in.privateKeyData).privateKeyFile(in.privateKeyFile);
-        }
-    }
-
-    private final HostAndPort hostAndPort;
-    private final String username;
-    private final String password;
-    private final String privateKeyPassphrase;
-    private final String privateKeyData;
-    private final File privateKeyFile;
-    private final boolean strictHostKeyChecking;
-    private final int connectTimeout;
-    private final int sessionTimeout;
-    
-    SSHClient ssh;
-
-    private SshjClientConnection(Builder builder) {
-        this.hostAndPort = checkNotNull(builder.hostAndPort);
-        this.username = builder.username;
-        this.password = builder.password;
-        this.privateKeyPassphrase = builder.privateKeyPassphrase;
-        this.privateKeyData = builder.privateKeyData;
-        this.privateKeyFile = builder.privateKeyFile;
-        this.strictHostKeyChecking = builder.strictHostKeyChecking;
-        this.connectTimeout = checkInt("connectTimeout", builder.connectTimeout, Integer.MAX_VALUE);
-        this.sessionTimeout = checkInt("sessionTimeout", builder.sessionTimeout, Integer.MAX_VALUE);
-    }
-
-    static Integer checkInt(String context, long value, Integer ifTooLarge) {
-        if (value > Integer.MAX_VALUE) {
-            LOG.warn("Value '"+value+"' for "+context+" too large in SshjClientConnection; using "+value);
-            return ifTooLarge;
-        }
-        return (int)value;
-    }
-
-    public boolean isConnected() {
-        return ssh != null && ssh.isConnected();
-    }
-
-    public boolean isAuthenticated() {
-        return ssh != null && ssh.isAuthenticated();
-    }
-
-    @Override
-    public void clear() {
-        if (ssh != null && ssh.isConnected()) {
-            try {
-                if (LOG.isTraceEnabled()) LOG.trace("Disconnecting SshjClientConnection {} ({})", this, System.identityHashCode(this));
-                ssh.disconnect();
-            } catch (IOException e) {
-                if (LOG.isDebugEnabled()) LOG.debug("<< exception disconnecting from {}: {}", e, e.getMessage());
-            }
-        }
-        ssh = null;
-    }
-
-    @Override
-    public SSHClient create() throws Exception {
-        if (LOG.isTraceEnabled()) LOG.trace("Connecting SshjClientConnection {} ({})", this, System.identityHashCode(this));
-        ssh = new net.schmizz.sshj.SSHClient();
-        if (!strictHostKeyChecking) {
-            ssh.addHostKeyVerifier(new PromiscuousVerifier());
-        }
-        if (connectTimeout != 0) {
-            ssh.setConnectTimeout(connectTimeout);
-        }
-        if (sessionTimeout != 0) {
-            ssh.setTimeout(sessionTimeout);
-        }
-        ssh.connect(hostAndPort.getHostText(), hostAndPort.getPortOrDefault(22));
-        
-        if (password != null) {
-            ssh.authPassword(username, password);
-        } else if (privateKeyData != null) {
-            OpenSSHKeyFile key = new OpenSSHKeyFile();
-            key.init(privateKeyData, null, 
-                    GroovyJavaMethods.truth(privateKeyPassphrase) ? 
-                            PasswordUtils.createOneOff(privateKeyPassphrase.toCharArray())
-                            : null);
-            ssh.authPublickey(username, key);
-        } else if (privateKeyFile != null) {
-            OpenSSHKeyFile key = new OpenSSHKeyFile();
-            key.init(privateKeyFile, 
-                    GroovyJavaMethods.truth(privateKeyPassphrase) ? 
-                            PasswordUtils.createOneOff(privateKeyPassphrase.toCharArray())
-                            : null);
-            ssh.authPublickey(username, key);
-        } else {
-            // Accept defaults (in ~/.ssh)
-            ssh.authPublickey(username);
-        }
-        
-        return ssh;
-    }
-
-    /**
-     * @return host and port, where port if not present defaults to {@code 22}
-     */
-    public HostAndPort getHostAndPort() {
-        return hostAndPort;
-    }
-
-    /**
-     * @return username used in this ssh
-     */
-    public String getUsername() {
-        return username;
-    }
-
-    /**
-     * 
-     * @return how long to wait for the initial connection to be made
-     */
-    public int getConnectTimeout() {
-        return connectTimeout;
-    }
-
-    /**
-     * 
-     * @return how long to keep the ssh open, or {@code 0} for indefinitely
-     */
-    public int getSessionTimeout() {
-        return sessionTimeout;
-    }
-
-    /**
-     * 
-     * @return the current ssh or {@code null} if not connected
-     */
-    public SSHClient getSSHClient() {
-        return ssh;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o)
-            return true;
-        if (o == null || getClass() != o.getClass())
-            return false;
-        SshjClientConnection that = SshjClientConnection.class.cast(o);
-        return equal(this.hostAndPort, that.hostAndPort) && equal(this.username, that.username) 
-                && equal(this.password, that.password) && equal(this.privateKeyData, that.privateKeyData)
-                && equal(this.privateKeyFile, that.privateKeyFile) && equal(this.ssh, that.ssh);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hashCode(hostAndPort, username, password, privateKeyData, ssh);
-    }
-
-    @Override
-    public String toString() {
-        return Objects.toStringHelper("")
-                .add("hostAndPort", hostAndPort)
-                .add("user", username)
-                .add("ssh", ssh != null ? ssh.hashCode() : null)
-                .add("password", (password != null ? "xxxxxx" : null))
-                .add("privateKeyFile", privateKeyFile)
-                .add("privateKey", (privateKeyData != null ? "xxxxxx" : null))
-                .add("connectTimeout", connectTimeout)
-                .add("sessionTimeout", sessionTimeout).toString();
-    }
-}


Mime
View raw message