Please revert the change and implement it again without turning the
CommandFactory into a NamedResource.
A CommandFactory is not limited to implement a single command, so having a
named on it does not make much sense to me, and it breaks all existing
implementations for no benefit.

2018-05-15 9:48 GMT+02:00 <lgoldst...@apache.org>:

> [SSHD-819] Standardized the DelegateCommandFactory behavior
>
>
> Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
> Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/f1a8077b
> Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/f1a8077b
> Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/f1a8077b
>
> Branch: refs/heads/master
> Commit: f1a8077be3875184b067095b236793e4801c2ad5
> Parents: 3182ad8
> Author: Goldstein Lyor <l...@c-b4.com>
> Authored: Tue May 15 10:41:24 2018 +0300
> Committer: Goldstein Lyor <l...@c-b4.com>
> Committed: Tue May 15 10:48:02 2018 +0300
>
> ----------------------------------------------------------------------
>  .../sshd/cli/server/SshServerCliSupport.java    |   2 +-
>  .../apache/sshd/cli/server/SshServerMain.java   |   6 +-
>  .../apache/sshd/cli/server/SshFsMounter.java    |   9 +-
>  .../sshd/server/AbstractCommandSupport.java     | 168 ------------------
>  .../org/apache/sshd/server/AsyncCommand.java    |  52 ------
>  .../apache/sshd/server/ChannelSessionAware.java |   1 +
>  .../java/org/apache/sshd/server/Command.java    |  65 -------
>  .../org/apache/sshd/server/CommandFactory.java  |  40 -----
>  .../apache/sshd/server/CommandLifecycle.java    |  48 ------
>  .../sshd/server/ServerFactoryManager.java       |   2 +
>  .../java/org/apache/sshd/server/SshServer.java  |   2 +
>  .../server/channel/ChannelDataReceiver.java     |   4 +-
>  .../sshd/server/channel/ChannelSession.java     |   8 +-
>  .../server/command/AbstractCommandSupport.java  | 170 +++++++++++++++++++
>  .../AbstractDelegatingCommandFactory.java       |  76 +++++++++
>  .../sshd/server/command/AsyncCommand.java       |  52 ++++++
>  .../org/apache/sshd/server/command/Command.java |  67 ++++++++
>  .../sshd/server/command/CommandFactory.java     |  41 +++++
>  .../sshd/server/command/CommandLifecycle.java   |  50 ++++++
>  .../command/DelegatingCommandFactory.java       |  43 +++++
>  .../apache/sshd/server/shell/InvertedShell.java |   2 +-
>  .../sshd/server/shell/InvertedShellWrapper.java |   2 +-
>  .../shell/ProcessShellCommandFactory.java       |  50 ++++++
>  .../sshd/server/shell/ProcessShellFactory.java  |   2 +-
>  .../apache/sshd/server/shell/ShellFactory.java  |   2 +-
>  .../sshd/server/shell/UnknownCommand.java       |   2 +-
>  .../server/shell/UnknownCommandFactory.java     |  11 +-
>  .../sshd/server/subsystem/SubsystemFactory.java |   2 +-
>  .../java/org/apache/sshd/KeepAliveTest.java     |   2 +-
>  .../java/org/apache/sshd/KeyReExchangeTest.java |   2 +-
>  .../java/org/apache/sshd/WindowAdjustTest.java  |   2 +-
>  .../java/org/apache/sshd/agent/AgentTest.java   |   2 +-
>  .../java/org/apache/sshd/client/ClientTest.java |   2 +-
>  .../sshd/client/channel/ChannelExecTest.java    |  24 ++-
>  .../sshd/client/session/ClientSessionTest.java  |  69 +++++---
>  .../apache/sshd/common/channel/WindowTest.java  |   2 +-
>  .../java/org/apache/sshd/server/ServerTest.java | 149 +++++++++-------
>  .../sshd/util/test/AsyncEchoShellFactory.java   |   4 +-
>  .../sshd/util/test/CommandExecutionHelper.java  |   2 +-
>  .../apache/sshd/util/test/EchoShellFactory.java |   2 +-
>  .../org/apache/sshd/git/AbstractGitCommand.java |   2 +-
>  .../sshd/git/AbstractGitCommandFactory.java     |  47 ++---
>  .../sshd/git/pack/GitPackCommandFactory.java    |   7 +-
>  .../sshd/git/pgm/GitPgmCommandFactory.java      |   7 +-
>  .../org/apache/sshd/server/scp/ScpCommand.java  |   2 +-
>  .../sshd/server/scp/ScpCommandFactory.java      |  63 +++----
>  .../org/apache/sshd/client/scp/ScpTest.java     |   2 +-
>  .../sshd/server/scp/ScpCommandFactoryTest.java  |   2 +-
>  .../server/subsystem/sftp/SftpSubsystem.java    |   4 +-
>  .../subsystem/sftp/SftpSubsystemFactory.java    |   2 +-
>  .../sshd/client/subsystem/sftp/ClientTest.java  |   2 +-
>  .../sshd/client/subsystem/sftp/SftpTest.java    |   2 +-
>  .../client/subsystem/sftp/SftpVersionsTest.java |   2 +-
>  .../SpaceAvailableExtensionImplTest.java        |   2 +-
>  .../openssh/helpers/OpenSSHExtensionsTest.java  |   2 +-
>  55 files changed, 815 insertions(+), 574 deletions(-)
> ----------------------------------------------------------------------
>
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-cli/src/main/java/org/apache/sshd/cli/
> server/SshServerCliSupport.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
> b/sshd-cli/src/main/java/org/apache/sshd/cli/server/
> SshServerCliSupport.java
> index 910566f..8b392bc 100644
> --- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/
> SshServerCliSupport.java
> +++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/
> SshServerCliSupport.java
> @@ -49,10 +49,10 @@ import org.apache.sshd.common.util.GenericUtils;
>  import org.apache.sshd.common.util.ValidateUtils;
>  import org.apache.sshd.common.util.security.SecurityUtils;
>  import org.apache.sshd.common.util.threads.ThreadUtils;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.ServerAuthenticationManager;
>  import org.apache.sshd.server.ServerFactoryManager;
>  import org.apache.sshd.server.SshServer;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.server.config.SshServerConfigFileReader;
>  import org.apache.sshd.server.forward.ForwardingFilter;
>  import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvid
> er;
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-cli/src/main/java/org/apache/sshd/cli/
> server/SshServerMain.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
> b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
> index cba6fc2..b9f6d1e 100644
> --- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
> +++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
> @@ -33,13 +33,13 @@ import org.apache.sshd.common.PropertyResolverUtils;
>  import org.apache.sshd.common.config.SshConfigFileReader;
>  import org.apache.sshd.common.keyprovider.KeyPairProvider;
>  import org.apache.sshd.common.util.GenericUtils;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.SshServer;
>  import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticato
> r;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.server.config.keys.ServerIdentity;
>  import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvid
> er;
>  import org.apache.sshd.server.scp.ScpCommandFactory;
> -import org.apache.sshd.server.shell.ProcessShellFactory;
> +import org.apache.sshd.server.shell.ProcessShellCommandFactory;
>  import org.apache.sshd.server.shell.ShellFactory;
>
>  /**
> @@ -181,7 +181,7 @@ public class SshServerMain extends SshServerCliSupport
> {
>          sshd.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticato
> r.INSTANCE);
>          setupServerForwarding(sshd, resolver);
>          sshd.setCommandFactory(new ScpCommandFactory.Builder()
> -            .withDelegate(command -> new 
> ProcessShellFactory(GenericUtils.split(command,
> ' ')).create())
> +            .withDelegate(ProcessShellCommandFactory.INSTANCE)
>              .build());
>
>          List<NamedFactory<Command>> subsystems = 
> resolveServerSubsystems(System.err,
> resolver);
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-cli/src/test/java/org/apache/sshd/cli/
> server/SshFsMounter.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
> b/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
> index 74a5a83..c270be7 100644
> --- a/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
> +++ b/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
> @@ -43,13 +43,13 @@ import org.apache.sshd.common.util.ValidateUtils;
>  import org.apache.sshd.common.util.logging.AbstractLoggingBean;
>  import org.apache.sshd.common.util.security.SecurityUtils;
>  import org.apache.sshd.common.util.threads.ThreadUtils;
> -import org.apache.sshd.server.Command;
> -import org.apache.sshd.server.CommandFactory;
>  import org.apache.sshd.server.Environment;
>  import org.apache.sshd.server.ExitCallback;
>  import org.apache.sshd.server.SessionAware;
>  import org.apache.sshd.server.SshServer;
>  import org.apache.sshd.server.auth.password.
> AcceptAllPasswordAuthenticator;
> +import org.apache.sshd.server.command.Command;
> +import org.apache.sshd.server.command.CommandFactory;
>  import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
>  import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
>  import org.apache.sshd.server.scp.ScpCommandFactory;
> @@ -232,6 +232,11 @@ public final class SshFsMounter extends
> SshServerCliSupport {
>          }
>
>          @Override
> +        public String getName() {
> +            return "mounter";
> +        }
> +
> +        @Override
>          public Command createCommand(String command) {
>              return new MounterCommand(command);
>          }
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> AbstractCommandSupport.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/AbstractCommandSupport.java
> b/sshd-core/src/main/java/org/apache/sshd/server/
> AbstractCommandSupport.java
> deleted file mode 100644
> index 7533157..0000000
> --- a/sshd-core/src/main/java/org/apache/sshd/server/
> AbstractCommandSupport.java
> +++ /dev/null
> @@ -1,168 +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 org.apache.sshd.server;
> -
> -import java.io.IOException;
> -import java.io.InputStream;
> -import java.io.OutputStream;
> -import java.util.Collection;
> -import java.util.concurrent.ExecutorService;
> -import java.util.concurrent.Future;
> -
> -import org.apache.sshd.common.util.GenericUtils;
> -import org.apache.sshd.common.util.logging.AbstractLoggingBean;
> -import org.apache.sshd.common.util.threads.ExecutorServiceCarrier;
> -import org.apache.sshd.common.util.threads.ThreadUtils;
> -
> -/**
> - * Provides a basic useful skeleton for {@link Command} executions
> - *
> - * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
> - */
> -public abstract class AbstractCommandSupport
> -        extends AbstractLoggingBean
> -        implements Command, Runnable, ExitCallback,
> ExecutorServiceCarrier {
> -    private final String command;
> -    private InputStream in;
> -    private OutputStream out;
> -    private OutputStream err;
> -    private ExitCallback callback;
> -    private Environment environment;
> -    private Future<?> cmdFuture;
> -    private ExecutorService executorService;
> -    private boolean shutdownOnExit;
> -    private boolean cbCalled;
> -
> -    protected AbstractCommandSupport(String command, ExecutorService
> executorService, boolean shutdownOnExit) {
> -        this.command = command;
> -
> -        if (executorService == null) {
> -            String poolName = GenericUtils.isEmpty(command) ?
> getClass().getSimpleName() : command.replace(' ', '_').replace('/', ':');
> -            this.executorService = ThreadUtils.newSingleThreadExecutor(
> poolName);
> -            this.shutdownOnExit = true;    // we always close the ad-hoc
> executor service
> -        } else {
> -            this.executorService = executorService;
> -            this.shutdownOnExit = shutdownOnExit;
> -        }
> -    }
> -
> -    public String getCommand() {
> -        return command;
> -    }
> -
> -    @Override
> -    public ExecutorService getExecutorService() {
> -        return executorService;
> -    }
> -
> -    @Override
> -    public boolean isShutdownOnExit() {
> -        return shutdownOnExit;
> -    }
> -
> -    public InputStream getInputStream() {
> -        return in;
> -    }
> -
> -    @Override
> -    public void setInputStream(InputStream in) {
> -        this.in = in;
> -    }
> -
> -    public OutputStream getOutputStream() {
> -        return out;
> -    }
> -
> -    @Override
> -    public void setOutputStream(OutputStream out) {
> -        this.out = out;
> -    }
> -
> -    public OutputStream getErrorStream() {
> -        return err;
> -    }
> -
> -    @Override
> -    public void setErrorStream(OutputStream err) {
> -        this.err = err;
> -    }
> -
> -    public ExitCallback getExitCallback() {
> -        return callback;
> -    }
> -
> -    @Override
> -    public void setExitCallback(ExitCallback callback) {
> -        this.callback = callback;
> -    }
> -
> -    public Environment getEnvironment() {
> -        return environment;
> -    }
> -
> -    protected Future<?> getStartedCommandFuture() {
> -        return cmdFuture;
> -    }
> -
> -    @Override
> -    public void start(Environment env) throws IOException {
> -        environment = env;
> -        ExecutorService executors = getExecutorService();
> -        cmdFuture = executors.submit(this);
> -    }
> -
> -    @Override
> -    public void destroy() {
> -        ExecutorService executors = getExecutorService();
> -        if ((executors != null) && (!executors.isShutdown()) &&
> isShutdownOnExit()) {
> -            Collection<Runnable> runners = executors.shutdownNow();
> -            if (log.isDebugEnabled()) {
> -                log.debug("destroy() - shutdown executor service -
> runners count=" + runners.size());
> -            }
> -        }
> -        this.executorService = null;
> -    }
> -
> -    @Override
> -    public void onExit(int exitValue, String exitMessage) {
> -        if (cbCalled) {
> -            if (log.isTraceEnabled()) {
> -                log.trace("onExit({}) ignore exitValue={}, message={} -
> already called",
> -                        this, exitValue, exitMessage);
> -            }
> -            return;
> -        }
> -
> -        ExitCallback cb = getExitCallback();
> -        try {
> -            if (log.isDebugEnabled()) {
> -                log.debug("onExit({}) exiting - value={}, message={}",
> this, exitValue, exitMessage);
> -            }
> -            cb.onExit(exitValue, exitMessage);
> -        } finally {
> -            cbCalled = true;
> -        }
> -    }
> -
> -    @Override
> -    public String toString() {
> -        return getClass().getSimpleName() + "[" + getCommand() + "]";
> -    }
> -}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/AsyncCommand.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/main/java/org/apache/sshd/server/AsyncCommand.java
> b/sshd-core/src/main/java/org/apache/sshd/server/AsyncCommand.java
> deleted file mode 100644
> index b49af64..0000000
> --- a/sshd-core/src/main/java/org/apache/sshd/server/AsyncCommand.java
> +++ /dev/null
> @@ -1,52 +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 org.apache.sshd.server;
> -
> -import org.apache.sshd.common.io.IoInputStream;
> -import org.apache.sshd.common.io.IoOutputStream;
> -
> -/**
> - * Represents a command capable of doing non-blocking io.
> - * If this interface is implemented by a command, the usual
> - * blocking input / output / error streams won't be set.
> - */
> -public interface AsyncCommand extends Command {
> -
> -    /**
> -     * Set the input stream that can be used by the shell to read input.
> -     *
> -     * @param in The {@link IoInputStream} used by the shell to read input
> -     */
> -    void setIoInputStream(IoInputStream in);
> -
> -    /**
> -     * Set the output stream that can be used by the shell to write its
> output.
> -     *
> -     * @param out The {@link IoOutputStream} used by the shell to write
> its output
> -     */
> -    void setIoOutputStream(IoOutputStream out);
> -
> -    /**
> -     * Set the error stream that can be used by the shell to write its
> errors.
> -     *
> -     * @param err The {@link IoOutputStream} used by the shell to write
> its errors
> -     */
> -    void setIoErrorStream(IoOutputStream err);
> -
> -}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> ChannelSessionAware.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/ChannelSessionAware.java
> b/sshd-core/src/main/java/org/apache/sshd/server/ChannelSessionAware.java
> index 150e719..d6d7c8b 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/
> ChannelSessionAware.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/
> ChannelSessionAware.java
> @@ -19,6 +19,7 @@
>  package org.apache.sshd.server;
>
>  import org.apache.sshd.server.channel.ChannelSession;
> +import org.apache.sshd.server.command.Command;
>
>  /**
>   * {@link Command} can implement this optional interface
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/Command.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/main/java/org/apache/sshd/server/Command.java
> b/sshd-core/src/main/java/org/apache/sshd/server/Command.java
> deleted file mode 100644
> index 4043e48..0000000
> --- a/sshd-core/src/main/java/org/apache/sshd/server/Command.java
> +++ /dev/null
> @@ -1,65 +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 org.apache.sshd.server;
> -
> -import java.io.InputStream;
> -import java.io.OutputStream;
> -
> -/**
> - * <p>
> - * Represents a command, shell or subsystem that can be used to send
> command.
> - * </p>
> - *
> - * <p>
> - * This command have direct streams, meaning those streams will be
> provided by the ssh server
> - * for the shell to use directly. This interface is suitable for
> implementing commands in java,
> - * rather than using external processes.  For wrapping such processes or
> using inverted streams,
> - * </p>
> - * see {@link org.apache.sshd.server.shell.InvertedShellWrapper}.
> - */
> -public interface Command extends CommandLifecycle {
> -
> -    /**
> -     * Set the input stream that can be used by the shell to read input.
> -     *
> -     * @param in The {@link InputStream}  used by the shell to read input.
> -     */
> -    void setInputStream(InputStream in);
> -
> -    /**
> -     * Set the output stream that can be used by the shell to write its
> output.
> -     *
> -     * @param out The {@link OutputStream} used by the shell to write its
> output
> -     */
> -    void setOutputStream(OutputStream out);
> -
> -    /**
> -     * Set the error stream that can be used by the shell to write its
> errors.
> -     *
> -     * @param err The {@link OutputStream} used by the shell to write its
> errors
> -     */
> -    void setErrorStream(OutputStream err);
> -
> -    /**
> -     * Set the callback that the shell has to call when it is closed.
> -     *
> -     * @param callback The {@link ExitCallback} to call when shell is
> closed
> -     */
> -    void setExitCallback(ExitCallback callback);
> -}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> CommandFactory.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/CommandFactory.java
> b/sshd-core/src/main/java/org/apache/sshd/server/CommandFactory.java
> deleted file mode 100644
> index 650abe1..0000000
> --- a/sshd-core/src/main/java/org/apache/sshd/server/CommandFactory.java
> +++ /dev/null
> @@ -1,40 +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 org.apache.sshd.server;
> -
> -/**
> - * A factory of commands.
> - * Commands are executed on the server side when an "exec" channel is
> - * requested by the SSH client.
> - *
> - * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
> - */
> -@FunctionalInterface
> -public interface CommandFactory {
> -
> -    /**
> -     * Create a command with the given name.
> -     * If the command is not known, a dummy command should be returned to
> allow
> -     * the display output to be sent back to the client.
> -     *
> -     * @param command The command that will be run
> -     * @return a non {@code null} {@link Command} instance
> -     */
> -    Command createCommand(String command);
> -}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> CommandLifecycle.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/CommandLifecycle.java
> b/sshd-core/src/main/java/org/apache/sshd/server/CommandLifecycle.java
> deleted file mode 100644
> index cbe3cf0..0000000
> --- a/sshd-core/src/main/java/org/apache/sshd/server/CommandLifecycle.java
> +++ /dev/null
> @@ -1,48 +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 org.apache.sshd.server;
> -
> -import java.io.IOException;
> -
> -/**
> - * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
> - */
> -public interface CommandLifecycle {
> -    /**
> -     * Starts the command execution. All streams must have been set
> <U>before</U>
> -     * calling this method. The command should implement {@link
> java.lang.Runnable},
> -     * and this method should spawn a new thread like:
> -     * <pre>
> -     * {@code Thread(this).start(); }
> -     * </pre>
> -     *
> -     * @param env The {@link Environment}
> -     * @throws IOException If failed to start
> -     */
> -    void start(Environment env) throws IOException;
> -
> -    /**
> -     * This method is called by the SSH server to destroy the command
> because
> -     * the client has disconnected somehow.
> -     *
> -     * @throws Exception if failed to destroy
> -     */
> -    void destroy() throws Exception;
> -}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> ServerFactoryManager.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
> b/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
> index 68531ed..60bd655 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/
> ServerFactoryManager.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/
> ServerFactoryManager.java
> @@ -24,6 +24,8 @@ import java.util.concurrent.TimeUnit;
>  import org.apache.sshd.common.Factory;
>  import org.apache.sshd.common.FactoryManager;
>  import org.apache.sshd.common.NamedFactory;
> +import org.apache.sshd.server.command.Command;
> +import org.apache.sshd.server.command.CommandFactory;
>  import org.apache.sshd.server.session.ServerProxyAcceptorHolder;
>
>  /**
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
> b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
> index f93c5d0..35b72cc 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
> @@ -49,6 +49,8 @@ import org.apache.sshd.server.auth.hostbased.
> HostBasedAuthenticator;
>  import org.apache.sshd.server.auth.keyboard.
> KeyboardInteractiveAuthenticator;
>  import org.apache.sshd.server.auth.password.PasswordAuthenticator;
>  import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
> +import org.apache.sshd.server.command.Command;
> +import org.apache.sshd.server.command.CommandFactory;
>  import org.apache.sshd.server.session.ServerConnectionServiceFactory;
>  import org.apache.sshd.server.session.ServerProxyAcceptor;
>  import org.apache.sshd.server.session.ServerUserAuthServiceFactory;
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> channel/ChannelDataReceiver.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelDataReceiver.java
> b/sshd-core/src/main/java/org/apache/sshd/server/channel/
> ChannelDataReceiver.java
> index f336c89..59ade13 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/
> ChannelDataReceiver.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/
> ChannelDataReceiver.java
> @@ -30,10 +30,10 @@ import java.io.IOException;
>   * Sequence of bytes that SSH client sends to the server is eventually
> sent to this interface
>   * to be passed on to the final consumer.
>   * By default {@link ChannelSession} spools this in a buffer so that you
> can read it from
> - * the input stream you get from {@link org.apache.sshd.server.
> Command#setInputStream(java.io.InputStream)}, but if command
> + * the input stream you get from {@link org.apache.sshd.server.
> command.Command#setInputStream(java.io.InputStream)}, but if command
>   * wants to do a callback-driven I/O for the data it receives from the
> client, it can
>   * call {@link ChannelSession#setDataReceiver(ChannelDataReceiver)} to
> do so.
> - * (And to grab a reference to {@link ChannelSession}, a {@link
> org.apache.sshd.server.Command} should implement
> + * (And to grab a reference to {@link ChannelSession}, a {@link
> org.apache.sshd.server.command.Command} should implement
>   * {@link org.apache.sshd.server.ChannelSessionAware}.)
>   * </p>
>   *
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> channel/ChannelSession.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
> b/sshd-core/src/main/java/org/apache/sshd/server/channel/
> ChannelSession.java
> index b884d80..cfaa499 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/
> ChannelSession.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/
> ChannelSession.java
> @@ -62,15 +62,15 @@ import org.apache.sshd.common.util.
> buffer.ByteArrayBuffer;
>  import org.apache.sshd.common.util.closeable.IoBaseCloseable;
>  import org.apache.sshd.common.util.io.IoUtils;
>  import org.apache.sshd.common.util.io.LoggingFilterOutputStream;
> -import org.apache.sshd.server.AsyncCommand;
>  import org.apache.sshd.server.ChannelSessionAware;
> -import org.apache.sshd.server.Command;
> -import org.apache.sshd.server.CommandFactory;
>  import org.apache.sshd.server.Environment;
>  import org.apache.sshd.server.ServerFactoryManager;
>  import org.apache.sshd.server.SessionAware;
>  import org.apache.sshd.server.Signal;
>  import org.apache.sshd.server.StandardEnvironment;
> +import org.apache.sshd.server.command.AsyncCommand;
> +import org.apache.sshd.server.command.Command;
> +import org.apache.sshd.server.command.CommandFactory;
>  import org.apache.sshd.server.forward.AgentForwardingFilter;
>  import org.apache.sshd.server.forward.X11ForwardingFilter;
>  import org.apache.sshd.server.session.ServerSession;
> @@ -602,7 +602,7 @@ public class ChannelSession extends
> AbstractServerChannel {
>      /**
>       * For {@link Command} to install {@link ChannelDataReceiver}.
>       * When you do this, {@link Command#setInputStream(java.io.InputStream)}
> or
> -     * {@link org.apache.sshd.server.AsyncCommand#setIoInputStream(
> org.apache.sshd.common.io.IoInputStream)}
> +     * {@link org.apache.sshd.server.command.AsyncCommand#
> setIoInputStream(org.apache.sshd.common.io.IoInputStream)}
>       * will no longer be invoked. If you call this method from {@link
> Command#start(Environment)},
>       * the input stream you received in {@link
> Command#setInputStream(java.io.InputStream)} will
>       * not read any data.
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/command/
> AbstractCommandSupport.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/command/AbstractCommandSupport.java
> b/sshd-core/src/main/java/org/apache/sshd/server/command/
> AbstractCommandSupport.java
> new file mode 100644
> index 0000000..58cf034
> --- /dev/null
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/command/
> AbstractCommandSupport.java
> @@ -0,0 +1,170 @@
> +/*
> + * 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 org.apache.sshd.server.command;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.io.OutputStream;
> +import java.util.Collection;
> +import java.util.concurrent.ExecutorService;
> +import java.util.concurrent.Future;
> +
> +import org.apache.sshd.common.util.GenericUtils;
> +import org.apache.sshd.common.util.logging.AbstractLoggingBean;
> +import org.apache.sshd.common.util.threads.ExecutorServiceCarrier;
> +import org.apache.sshd.common.util.threads.ThreadUtils;
> +import org.apache.sshd.server.Environment;
> +import org.apache.sshd.server.ExitCallback;
> +
> +/**
> + * Provides a basic useful skeleton for {@link Command} executions
> + *
> + * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
> + */
> +public abstract class AbstractCommandSupport
> +        extends AbstractLoggingBean
> +        implements Command, Runnable, ExitCallback,
> ExecutorServiceCarrier {
> +    private final String command;
> +    private InputStream in;
> +    private OutputStream out;
> +    private OutputStream err;
> +    private ExitCallback callback;
> +    private Environment environment;
> +    private Future<?> cmdFuture;
> +    private ExecutorService executorService;
> +    private boolean shutdownOnExit;
> +    private boolean cbCalled;
> +
> +    protected AbstractCommandSupport(String command, ExecutorService
> executorService, boolean shutdownOnExit) {
> +        this.command = command;
> +
> +        if (executorService == null) {
> +            String poolName = GenericUtils.isEmpty(command) ?
> getClass().getSimpleName() : command.replace(' ', '_').replace('/', ':');
> +            this.executorService = ThreadUtils.newSingleThreadExecutor(
> poolName);
> +            this.shutdownOnExit = true;    // we always close the ad-hoc
> executor service
> +        } else {
> +            this.executorService = executorService;
> +            this.shutdownOnExit = shutdownOnExit;
> +        }
> +    }
> +
> +    public String getCommand() {
> +        return command;
> +    }
> +
> +    @Override
> +    public ExecutorService getExecutorService() {
> +        return executorService;
> +    }
> +
> +    @Override
> +    public boolean isShutdownOnExit() {
> +        return shutdownOnExit;
> +    }
> +
> +    public InputStream getInputStream() {
> +        return in;
> +    }
> +
> +    @Override
> +    public void setInputStream(InputStream in) {
> +        this.in = in;
> +    }
> +
> +    public OutputStream getOutputStream() {
> +        return out;
> +    }
> +
> +    @Override
> +    public void setOutputStream(OutputStream out) {
> +        this.out = out;
> +    }
> +
> +    public OutputStream getErrorStream() {
> +        return err;
> +    }
> +
> +    @Override
> +    public void setErrorStream(OutputStream err) {
> +        this.err = err;
> +    }
> +
> +    public ExitCallback getExitCallback() {
> +        return callback;
> +    }
> +
> +    @Override
> +    public void setExitCallback(ExitCallback callback) {
> +        this.callback = callback;
> +    }
> +
> +    public Environment getEnvironment() {
> +        return environment;
> +    }
> +
> +    protected Future<?> getStartedCommandFuture() {
> +        return cmdFuture;
> +    }
> +
> +    @Override
> +    public void start(Environment env) throws IOException {
> +        environment = env;
> +        ExecutorService executors = getExecutorService();
> +        cmdFuture = executors.submit(this);
> +    }
> +
> +    @Override
> +    public void destroy() {
> +        ExecutorService executors = getExecutorService();
> +        if ((executors != null) && (!executors.isShutdown()) &&
> isShutdownOnExit()) {
> +            Collection<Runnable> runners = executors.shutdownNow();
> +            if (log.isDebugEnabled()) {
> +                log.debug("destroy() - shutdown executor service -
> runners count=" + runners.size());
> +            }
> +        }
> +        this.executorService = null;
> +    }
> +
> +    @Override
> +    public void onExit(int exitValue, String exitMessage) {
> +        if (cbCalled) {
> +            if (log.isTraceEnabled()) {
> +                log.trace("onExit({}) ignore exitValue={}, message={} -
> already called",
> +                        this, exitValue, exitMessage);
> +            }
> +            return;
> +        }
> +
> +        ExitCallback cb = getExitCallback();
> +        try {
> +            if (log.isDebugEnabled()) {
> +                log.debug("onExit({}) exiting - value={}, message={}",
> this, exitValue, exitMessage);
> +            }
> +            cb.onExit(exitValue, exitMessage);
> +        } finally {
> +            cbCalled = true;
> +        }
> +    }
> +
> +    @Override
> +    public String toString() {
> +        return getClass().getSimpleName() + "[" + getCommand() + "]";
> +    }
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/command/
> AbstractDelegatingCommandFactory.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/main/java/org/apache/sshd/server/command/
> AbstractDelegatingCommandFactory.java b/sshd-core/src/main/java/org/
> apache/sshd/server/command/AbstractDelegatingCommandFactory.java
> new file mode 100644
> index 0000000..3169958
> --- /dev/null
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/command/
> AbstractDelegatingCommandFactory.java
> @@ -0,0 +1,76 @@
> +/*
> + * 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 org.apache.sshd.server.command;
> +
> +import org.apache.sshd.common.util.ValidateUtils;
> +import org.apache.sshd.common.util.logging.AbstractLoggingBean;
> +
> +/**
> + * TODO Add javadoc
> + *
> + * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
> + */
> +public abstract class AbstractDelegatingCommandFactory extends
> AbstractLoggingBean implements DelegatingCommandFactory {
> +    private final String name;
> +    /*
> +     * NOTE: we expose setters since there is no problem to change these
> settings between
> +     * successive invocations of the 'createCommand' method
> +     */
> +    private CommandFactory delegate;
> +
> +    protected AbstractDelegatingCommandFactory(String name) {
> +        this.name = ValidateUtils.checkNotNullAndNotEmpty(name, "No
> delegating command factory name provided");
> +    }
> +
> +    @Override
> +    public String getName() {
> +        return name;
> +    }
> +
> +    @Override
> +    public CommandFactory getDelegateCommandFactory() {
> +        return delegate;
> +    }
> +
> +    @Override
> +    public void setDelegateCommandFactory(CommandFactory factory) {
> +        delegate = factory;
> +    }
> +
> +    @Override
> +    public Command createCommand(String command) {
> +        if (isSupportedCommand(command)) {
> +            return executeSupportedCommand(command);
> +        }
> +
> +        CommandFactory factory = getDelegateCommandFactory();
> +        if (factory != null) {
> +            return factory.createCommand(command);
> +        }
> +
> +        return createUnsupportedCommand(command);
> +    }
> +
> +    protected abstract Command executeSupportedCommand(String command);
> +
> +    protected Command createUnsupportedCommand(String command) {
> +        throw new IllegalArgumentException("Unknown command to execute:
> " + command);
> +    }
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> command/AsyncCommand.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/command/AsyncCommand.java
> b/sshd-core/src/main/java/org/apache/sshd/server/command/AsyncCommand.java
> new file mode 100644
> index 0000000..f3d2173
> --- /dev/null
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/command/
> AsyncCommand.java
> @@ -0,0 +1,52 @@
> +/*
> + * 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 org.apache.sshd.server.command;
> +
> +import org.apache.sshd.common.io.IoInputStream;
> +import org.apache.sshd.common.io.IoOutputStream;
> +
> +/**
> + * Represents a command capable of doing non-blocking io.
> + * If this interface is implemented by a command, the usual
> + * blocking input / output / error streams won't be set.
> + */
> +public interface AsyncCommand extends Command {
> +
> +    /**
> +     * Set the input stream that can be used by the shell to read input.
> +     *
> +     * @param in The {@link IoInputStream} used by the shell to read input
> +     */
> +    void setIoInputStream(IoInputStream in);
> +
> +    /**
> +     * Set the output stream that can be used by the shell to write its
> output.
> +     *
> +     * @param out The {@link IoOutputStream} used by the shell to write
> its output
> +     */
> +    void setIoOutputStream(IoOutputStream out);
> +
> +    /**
> +     * Set the error stream that can be used by the shell to write its
> errors.
> +     *
> +     * @param err The {@link IoOutputStream} used by the shell to write
> its errors
> +     */
> +    void setIoErrorStream(IoOutputStream err);
> +
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> command/Command.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/command/Command.java
> b/sshd-core/src/main/java/org/apache/sshd/server/command/Command.java
> new file mode 100644
> index 0000000..5425d3a
> --- /dev/null
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/command/Command.java
> @@ -0,0 +1,67 @@
> +/*
> + * 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 org.apache.sshd.server.command;
> +
> +import java.io.InputStream;
> +import java.io.OutputStream;
> +
> +import org.apache.sshd.server.ExitCallback;
> +
> +/**
> + * <p>
> + * Represents a command, shell or subsystem that can be used to send
> command.
> + * </p>
> + *
> + * <p>
> + * This command have direct streams, meaning those streams will be
> provided by the ssh server
> + * for the shell to use directly. This interface is suitable for
> implementing commands in java,
> + * rather than using external processes.  For wrapping such processes or
> using inverted streams,
> + * </p>
> + * see {@link org.apache.sshd.server.shell.InvertedShellWrapper}.
> + */
> +public interface Command extends CommandLifecycle {
> +
> +    /**
> +     * Set the input stream that can be used by the shell to read input.
> +     *
> +     * @param in The {@link InputStream}  used by the shell to read input.
> +     */
> +    void setInputStream(InputStream in);
> +
> +    /**
> +     * Set the output stream that can be used by the shell to write its
> output.
> +     *
> +     * @param out The {@link OutputStream} used by the shell to write its
> output
> +     */
> +    void setOutputStream(OutputStream out);
> +
> +    /**
> +     * Set the error stream that can be used by the shell to write its
> errors.
> +     *
> +     * @param err The {@link OutputStream} used by the shell to write its
> errors
> +     */
> +    void setErrorStream(OutputStream err);
> +
> +    /**
> +     * Set the callback that the shell has to call when it is closed.
> +     *
> +     * @param callback The {@link ExitCallback} to call when shell is
> closed
> +     */
> +    void setExitCallback(ExitCallback callback);
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> command/CommandFactory.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/command/CommandFactory.java
> b/sshd-core/src/main/java/org/apache/sshd/server/command/
> CommandFactory.java
> new file mode 100644
> index 0000000..aff407b
> --- /dev/null
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/command/
> CommandFactory.java
> @@ -0,0 +1,41 @@
> +/*
> + * 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 org.apache.sshd.server.command;
> +
> +import org.apache.sshd.common.NamedResource;
> +
> +/**
> + * A factory of commands.
> + * Commands are executed on the server side when an "exec" channel is
> + * requested by the SSH client.
> + *
> + * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
> + */
> +public interface CommandFactory extends NamedResource {
> +
> +    /**
> +     * Create a command with the given name.
> +     * If the command is not known, a dummy command should be returned to
> allow
> +     * the display output to be sent back to the client.
> +     *
> +     * @param command The command that will be run
> +     * @return a non {@code null} {@link Command} instance
> +     */
> +    Command createCommand(String command);
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> command/CommandLifecycle.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/command/CommandLifecycle.java
> b/sshd-core/src/main/java/org/apache/sshd/server/command/
> CommandLifecycle.java
> new file mode 100644
> index 0000000..ac694d5
> --- /dev/null
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/command/
> CommandLifecycle.java
> @@ -0,0 +1,50 @@
> +/*
> + * 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 org.apache.sshd.server.command;
> +
> +import java.io.IOException;
> +
> +import org.apache.sshd.server.Environment;
> +
> +/**
> + * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
> + */
> +public interface CommandLifecycle {
> +    /**
> +     * Starts the command execution. All streams must have been set
> <U>before</U>
> +     * calling this method. The command should implement {@link
> java.lang.Runnable},
> +     * and this method should spawn a new thread like:
> +     * <pre>
> +     * {@code Thread(this).start(); }
> +     * </pre>
> +     *
> +     * @param env The {@link Environment}
> +     * @throws IOException If failed to start
> +     */
> +    void start(Environment env) throws IOException;
> +
> +    /**
> +     * This method is called by the SSH server to destroy the command
> because
> +     * the client has disconnected somehow.
> +     *
> +     * @throws Exception if failed to destroy
> +     */
> +    void destroy() throws Exception;
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/command/
> DelegatingCommandFactory.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/command/DelegatingCommandFactory.java
> b/sshd-core/src/main/java/org/apache/sshd/server/command/
> DelegatingCommandFactory.java
> new file mode 100644
> index 0000000..e1ce89c
> --- /dev/null
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/command/
> DelegatingCommandFactory.java
> @@ -0,0 +1,43 @@
> +/*
> + * 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 org.apache.sshd.server.command;
> +
> +/**
> + * Represents a {@link CommandFactory} that filters the commands it
> recognizes
> + * and delegates the ones it doesn't to another delegate factory. The
> behavior
> + * of such a delegating factory is undefined if it receives a command it
> does
> + * not recognize and not delegate has been set. The recommended behavior
> in this
> + * case is to throw some exception - though this is not mandatory
> + *
> + * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
> + */
> +public interface DelegatingCommandFactory extends CommandFactory {
> +    CommandFactory getDelegateCommandFactory();
> +
> +    void setDelegateCommandFactory(CommandFactory factory);
> +
> +    /**
> +     * @param command The command about to be executed
> +     * @return {@code true} if this command is supported by the command
> +     * factory, {@code false} if it will be passed on to the
> +     * {@link #getDelegateCommandFactory() delegate} factory
> +     */
> +    boolean isSupportedCommand(String command);
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> shell/InvertedShell.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShell.java
> b/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShell.java
> index 3d7de3c..3abc523 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/
> InvertedShell.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> InvertedShell.java
> @@ -21,8 +21,8 @@ package org.apache.sshd.server.shell;
>  import java.io.InputStream;
>  import java.io.OutputStream;
>
> -import org.apache.sshd.server.CommandLifecycle;
>  import org.apache.sshd.server.SessionAware;
> +import org.apache.sshd.server.command.CommandLifecycle;
>
>  /**
>   * This shell have inverted streams, such as the one obtained when
> launching a
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> shell/InvertedShellWrapper.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java
> b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> InvertedShellWrapper.java
> index 4819064..3c19e2c 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/
> InvertedShellWrapper.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> InvertedShellWrapper.java
> @@ -31,10 +31,10 @@ import org.apache.sshd.common.util.ValidateUtils;
>  import org.apache.sshd.common.util.io.IoUtils;
>  import org.apache.sshd.common.util.logging.AbstractLoggingBean;
>  import org.apache.sshd.common.util.threads.ThreadUtils;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.Environment;
>  import org.apache.sshd.server.ExitCallback;
>  import org.apache.sshd.server.SessionAware;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.server.session.ServerSession;
>
>  /**
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> ProcessShellCommandFactory.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/main/java/org/apache/sshd/server/shell/
> ProcessShellCommandFactory.java b/sshd-core/src/main/java/org/
> apache/sshd/server/shell/ProcessShellCommandFactory.java
> new file mode 100644
> index 0000000..af9af82
> --- /dev/null
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> ProcessShellCommandFactory.java
> @@ -0,0 +1,50 @@
> +/*
> + * 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 org.apache.sshd.server.shell;
> +
> +import org.apache.sshd.common.Factory;
> +import org.apache.sshd.common.util.GenericUtils;
> +import org.apache.sshd.server.command.Command;
> +import org.apache.sshd.server.command.CommandFactory;
> +
> +/**
> + * Executes commands by invoking the underlying shell
> + *
> + * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
> + */
> +public class ProcessShellCommandFactory implements CommandFactory {
> +    public static final String FACTORY_NAME = "shell-command";
> +    public static final ProcessShellCommandFactory INSTANCE = new
> ProcessShellCommandFactory();
> +
> +    public ProcessShellCommandFactory() {
> +        super();
> +    }
> +
> +    @Override
> +    public String getName() {
> +        return FACTORY_NAME;
> +    }
> +
> +    @Override
> +    public Command createCommand(String command) {
> +        Factory<Command> factory = new 
> ProcessShellFactory(GenericUtils.split(command,
> ' '));
> +        return factory.create();
> +    }
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> shell/ProcessShellFactory.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/shell/ProcessShellFactory.java
> b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> ProcessShellFactory.java
> index 3398e63..529b701 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/
> ProcessShellFactory.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> ProcessShellFactory.java
> @@ -27,7 +27,7 @@ import org.apache.sshd.common.util.GenericUtils;
>  import org.apache.sshd.common.util.OsUtils;
>  import org.apache.sshd.common.util.ValidateUtils;
>  import org.apache.sshd.common.util.logging.AbstractLoggingBean;
> -import org.apache.sshd.server.Command;
> +import org.apache.sshd.server.command.Command;
>
>  /**
>   * A {@link Factory} of {@link Command} that will create a new process
> and bridge
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> shell/ShellFactory.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/shell/ShellFactory.java
> b/sshd-core/src/main/java/org/apache/sshd/server/shell/ShellFactory.java
> index 0a80f67..d403d42 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/
> ShellFactory.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> ShellFactory.java
> @@ -20,7 +20,7 @@
>  package org.apache.sshd.server.shell;
>
>  import org.apache.sshd.common.Factory;
> -import org.apache.sshd.server.Command;
> +import org.apache.sshd.server.command.Command;
>
>  /**
>   * Useful marker interface
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> shell/UnknownCommand.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/shell/UnknownCommand.java
> b/sshd-core/src/main/java/org/apache/sshd/server/shell/UnknownCommand.java
> index 59d970c..43b9b9f 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/
> UnknownCommand.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> UnknownCommand.java
> @@ -25,9 +25,9 @@ import java.nio.charset.StandardCharsets;
>  import java.util.Objects;
>
>  import org.apache.sshd.common.util.ValidateUtils;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.Environment;
>  import org.apache.sshd.server.ExitCallback;
> +import org.apache.sshd.server.command.Command;
>
>  /**
>   * Implementation of an unknown command that can be returned by
> <code>CommandFactory</code>
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> shell/UnknownCommandFactory.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/shell/UnknownCommandFactory.java
> b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> UnknownCommandFactory.java
> index 871ca60..ea94525 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/
> UnknownCommandFactory.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/
> UnknownCommandFactory.java
> @@ -19,13 +19,15 @@
>
>  package org.apache.sshd.server.shell;
>
> -import org.apache.sshd.server.Command;
> -import org.apache.sshd.server.CommandFactory;
> +import org.apache.sshd.server.command.Command;
> +import org.apache.sshd.server.command.CommandFactory;
>
>  /**
>   * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
>   */
>  public class UnknownCommandFactory implements CommandFactory {
> +    public static final String FACTORY_NAME = "unknown";
> +
>      public static final UnknownCommandFactory INSTANCE = new
> UnknownCommandFactory();
>
>      public UnknownCommandFactory() {
> @@ -33,6 +35,11 @@ public class UnknownCommandFactory implements
> CommandFactory {
>      }
>
>      @Override
> +    public String getName() {
> +        return FACTORY_NAME;
> +    }
> +
> +    @Override
>      public Command createCommand(String command) {
>          return new UnknownCommand(command);
>      }
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/main/java/org/apache/sshd/server/
> subsystem/SubsystemFactory.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/SubsystemFactory.java
> b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/
> SubsystemFactory.java
> index f9dbf0f..8b0cc3f 100644
> --- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/
> SubsystemFactory.java
> +++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/
> SubsystemFactory.java
> @@ -20,7 +20,7 @@
>  package org.apache.sshd.server.subsystem;
>
>  import org.apache.sshd.common.NamedFactory;
> -import org.apache.sshd.server.Command;
> +import org.apache.sshd.server.command.Command;
>
>  /**
>   * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
> b/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
> index dd649e5..4e09447 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
> @@ -32,8 +32,8 @@ import org.apache.sshd.client.session.ClientSession;
>  import org.apache.sshd.common.FactoryManager;
>  import org.apache.sshd.common.PropertyResolverUtils;
>  import org.apache.sshd.common.channel.Channel;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.SshServer;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.util.test.BaseTestSupport;
>  import org.apache.sshd.util.test.EchoShell;
>  import org.apache.sshd.util.test.EchoShellFactory;
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
> b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
> index f2ca9df..4fdb932 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
> @@ -55,10 +55,10 @@ import org.apache.sshd.common.session.Session;
>  import org.apache.sshd.common.session.SessionListener;
>  import org.apache.sshd.common.util.io.NullOutputStream;
>  import org.apache.sshd.common.util.security.SecurityUtils;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.Environment;
>  import org.apache.sshd.server.ExitCallback;
>  import org.apache.sshd.server.SshServer;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.server.subsystem.SubsystemFactory;
>  import org.apache.sshd.util.test.BaseTestSupport;
>  import org.apache.sshd.util.test.JSchLogger;
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java
> b/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java
> index cac8e32..fd1fd84 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java
> @@ -45,10 +45,10 @@ import org.apache.sshd.common.util.
> buffer.ByteArrayBuffer;
>  import org.apache.sshd.common.util.io.NoCloseOutputStream;
>  import org.apache.sshd.common.util.logging.AbstractLoggingBean;
>  import org.apache.sshd.common.util.threads.ThreadUtils;
> -import org.apache.sshd.server.AsyncCommand;
>  import org.apache.sshd.server.Environment;
>  import org.apache.sshd.server.ExitCallback;
>  import org.apache.sshd.server.SshServer;
> +import org.apache.sshd.server.command.AsyncCommand;
>  import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
>  import org.apache.sshd.util.test.BaseTestSupport;
>  import org.junit.After;
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
> b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
> index f252be7..7deebfc 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
> @@ -38,9 +38,9 @@ import org.apache.sshd.client.channel.ChannelShell;
>  import org.apache.sshd.client.session.ClientSession;
>  import org.apache.sshd.common.keyprovider.KeyPairProvider;
>  import org.apache.sshd.common.util.security.SecurityUtils;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.Environment;
>  import org.apache.sshd.server.SshServer;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
>  import org.apache.sshd.util.test.BaseTestSupport;
>  import org.apache.sshd.util.test.EchoShell;
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
> b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
> index f3d94a8..0026cc3 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
> @@ -95,13 +95,13 @@ import org.apache.sshd.common.util.buffer.Buffer;
>  import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
>  import org.apache.sshd.common.util.io.NoCloseOutputStream;
>  import org.apache.sshd.common.util.net.SshdSocketAddress;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.SshServer;
>  import org.apache.sshd.server.auth.keyboard.
> DefaultKeyboardInteractiveAuthenticator;
>  import org.apache.sshd.server.auth.keyboard.
> KeyboardInteractiveAuthenticator;
>  import org.apache.sshd.server.auth.password.
> RejectAllPasswordAuthenticator;
>  import org.apache.sshd.server.channel.ChannelSession;
>  import org.apache.sshd.server.channel.ChannelSessionFactory;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.server.forward.DirectTcpipFactory;
>  import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
>  import org.apache.sshd.server.session.ServerConnectionServiceFactory;
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/client/
> channel/ChannelExecTest.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/test/java/org/apache/sshd/client/channel/ChannelExecTest.java
> b/sshd-core/src/test/java/org/apache/sshd/client/channel/
> ChannelExecTest.java
> index 038ce55..8a48daf 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/client/channel/
> ChannelExecTest.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/client/channel/
> ChannelExecTest.java
> @@ -26,6 +26,8 @@ import java.util.concurrent.TimeUnit;
>  import org.apache.sshd.client.SshClient;
>  import org.apache.sshd.client.session.ClientSession;
>  import org.apache.sshd.server.SshServer;
> +import org.apache.sshd.server.command.Command;
> +import org.apache.sshd.server.command.CommandFactory;
>  import org.apache.sshd.util.test.BaseTestSupport;
>  import org.apache.sshd.util.test.CommandExecutionHelper;
>  import org.apache.sshd.util.test.Utils;
> @@ -51,13 +53,23 @@ public class ChannelExecTest extends BaseTestSupport {
>      @BeforeClass
>      public static void setupClientAndServer() throws Exception {
>          sshd = Utils.setupTestServer(ChannelExecTest.class);
> -        sshd.setCommandFactory(command -> new CommandExecutionHelper(command)
> {
> +        sshd.setCommandFactory(new CommandFactory() {
>              @Override
> -            protected boolean handleCommandLine(String command) throws
> Exception {
> -                OutputStream stdout = getOutputStream();
> -                stdout.write(command.getBytes(
> StandardCharsets.US_ASCII));
> -                stdout.flush();
> -                return false;
> +            public String getName() {
> +                return ChannelExecTest.class.getSimpleName();
> +            }
> +
> +            @Override
> +            public Command createCommand(String command) {
> +                return new CommandExecutionHelper(command) {
> +                    @Override
> +                    protected boolean handleCommandLine(String command)
> throws Exception {
> +                        OutputStream stdout = getOutputStream();
> +                        stdout.write(command.getBytes(
> StandardCharsets.US_ASCII));
> +                        stdout.flush();
> +                        return false;
> +                    }
> +                };
>              }
>          });
>          sshd.start();
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/client/
> session/ClientSessionTest.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/test/java/org/apache/sshd/client/session/ClientSessionTest.java
> b/sshd-core/src/test/java/org/apache/sshd/client/session/
> ClientSessionTest.java
> index aeb5e3b..517b07c 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/client/session/
> ClientSessionTest.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/client/session/
> ClientSessionTest.java
> @@ -26,9 +26,9 @@ import java.rmi.ServerException;
>  import java.util.concurrent.TimeUnit;
>
>  import org.apache.sshd.client.SshClient;
> -import org.apache.sshd.server.Command;
> -import org.apache.sshd.server.CommandFactory;
>  import org.apache.sshd.server.SshServer;
> +import org.apache.sshd.server.command.Command;
> +import org.apache.sshd.server.command.CommandFactory;
>  import org.apache.sshd.util.test.BaseTestSupport;
>  import org.apache.sshd.util.test.CommandExecutionHelper;
>  import org.apache.sshd.util.test.Utils;
> @@ -84,18 +84,28 @@ public class ClientSessionTest extends BaseTestSupport
> {
>      public void testDefaultExecuteCommandMethod() throws Exception {
>          final String expectedCommand = getCurrentTestName() + "-CMD";
>          final String expectedResponse = getCurrentTestName() + "-RSP";
> -        sshd.setCommandFactory(command -> new CommandExecutionHelper(command)
> {
> -            private boolean cmdProcessed;
> +        sshd.setCommandFactory(new CommandFactory() {
> +            @Override
> +            public String getName() {
> +                return getCurrentTestName();
> +            }
>
>              @Override
> -            protected boolean handleCommandLine(String command) throws
> Exception {
> -                assertEquals("Mismatched incoming command",
> expectedCommand, command);
> -                assertFalse("Duplicated command call", cmdProcessed);
> -                OutputStream stdout = getOutputStream();
> -                stdout.write(expectedResponse.
> getBytes(StandardCharsets.US_ASCII));
> -                stdout.flush();
> -                cmdProcessed = true;
> -                return false;
> +            public Command createCommand(String command) {
> +                return new CommandExecutionHelper(command) {
> +                    private boolean cmdProcessed;
> +
> +                    @Override
> +                    protected boolean handleCommandLine(String command)
> throws Exception {
> +                        assertEquals("Mismatched incoming command",
> expectedCommand, command);
> +                        assertFalse("Duplicated command call",
> cmdProcessed);
> +                        OutputStream stdout = getOutputStream();
> +                        stdout.write(expectedResponse.
> getBytes(StandardCharsets.US_ASCII));
> +                        stdout.flush();
> +                        cmdProcessed = true;
> +                        return false;
> +                    }
> +                };
>              }
>          });
>
> @@ -113,18 +123,28 @@ public class ClientSessionTest extends
> BaseTestSupport {
>      public void testExceptionThrownIfRemoteStderrWrittenTo() throws
> Exception {
>          final String expectedCommand = getCurrentTestName() + "-CMD";
>          final String expectedErrorMessage = getCurrentTestName() + "-ERR";
> -        sshd.setCommandFactory(command -> new CommandExecutionHelper(command)
> {
> -            private boolean cmdProcessed;
> +        sshd.setCommandFactory(new CommandFactory() {
> +            @Override
> +            public String getName() {
> +                return getCurrentTestName();
> +            }
>
>              @Override
> -            protected boolean handleCommandLine(String command) throws
> Exception {
> -                assertEquals("Mismatched incoming command",
> expectedCommand, command);
> -                assertFalse("Duplicated command call", cmdProcessed);
> -                OutputStream stderr = getErrorStream();
> -                stderr.write(expectedErrorMessage.getBytes(
> StandardCharsets.US_ASCII));
> -                stderr.flush();
> -                cmdProcessed = true;
> -                return false;
> +            public Command createCommand(String command) {
> +                return new CommandExecutionHelper(command) {
> +                    private boolean cmdProcessed;
> +
> +                    @Override
> +                    protected boolean handleCommandLine(String command)
> throws Exception {
> +                        assertEquals("Mismatched incoming command",
> expectedCommand, command);
> +                        assertFalse("Duplicated command call",
> cmdProcessed);
> +                        OutputStream stderr = getErrorStream();
> +                        stderr.write(expectedErrorMessage.getBytes(
> StandardCharsets.US_ASCII));
> +                        stderr.flush();
> +                        cmdProcessed = true;
> +                        return false;
> +                    }
> +                };
>              }
>          });
>
> @@ -158,6 +178,11 @@ public class ClientSessionTest extends
> BaseTestSupport {
>          final int exepectedErrorCode = 7365;
>          sshd.setCommandFactory(new CommandFactory() {
>              @Override
> +            public String getName() {
> +                return getCurrentTestName();
> +            }
> +
> +            @Override
>              public Command createCommand(String command) {
>                  return new CommandExecutionHelper(command) {
>                      private boolean cmdProcessed;
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/common/
> channel/WindowTest.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
> b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
> index 93c37be..864fc23 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/common/channel/
> WindowTest.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/common/channel/
> WindowTest.java
> @@ -45,10 +45,10 @@ import org.apache.sshd.common.io.IoReadFuture;
>  import org.apache.sshd.common.session.Session;
>  import org.apache.sshd.common.util.buffer.Buffer;
>  import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.SshServer;
>  import org.apache.sshd.server.channel.ChannelSession;
>  import org.apache.sshd.server.channel.ChannelSessionFactory;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.server.forward.DirectTcpipFactory;
>  import org.apache.sshd.server.session.ServerConnectionService;
>  import org.apache.sshd.server.session.ServerConnectionServiceFactory;
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
> ----------------------------------------------------------------------
> diff --git a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
> b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
> index 8c083a3..d1955ef 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
> @@ -72,6 +72,8 @@ import org.apache.sshd.server.auth.keyboard.
> KeyboardInteractiveAuthenticator;
>  import org.apache.sshd.server.auth.keyboard.PromptEntry;
>  import org.apache.sshd.server.auth.password.
> RejectAllPasswordAuthenticator;
>  import org.apache.sshd.server.auth.pubkey.RejectAllPublickeyAuthenticato
> r;
> +import org.apache.sshd.server.command.Command;
> +import org.apache.sshd.server.command.CommandFactory;
>  import org.apache.sshd.server.session.ServerSession;
>  import org.apache.sshd.server.session.ServerSessionImpl;
>  import org.apache.sshd.util.test.BaseTestSupport;
> @@ -522,43 +524,51 @@ public class ServerTest extends BaseTestSupport {
>      @Test   // see SSHD-645
>      public void testChannelStateChangeNotifications() throws Exception {
>          final Semaphore exitSignal = new Semaphore(0);
> -        sshd.setCommandFactory(command -> {
> -            
> ValidateUtils.checkTrue(String.CASE_INSENSITIVE_ORDER.compare(command,
> getCurrentTestName()) == 0, "Unexpected command: %s", command);
> +        sshd.setCommandFactory(new CommandFactory() {
> +            @Override
> +            public String getName() {
> +                return getCurrentTestName();
> +            }
>
> -            return new Command() {
> -                private ExitCallback cb;
> +            @Override
> +            public Command createCommand(String command) {
> +                
> ValidateUtils.checkTrue(String.CASE_INSENSITIVE_ORDER.compare(command,
> getCurrentTestName()) == 0, "Unexpected command: %s", command);
>
> -                @Override
> -                public void setOutputStream(OutputStream out) {
> -                    // ignored
> -                }
> +                return new Command() {
> +                    private ExitCallback cb;
>
> -                @Override
> -                public void setInputStream(InputStream in) {
> -                    // ignored
> -                }
> +                    @Override
> +                    public void setOutputStream(OutputStream out) {
> +                        // ignored
> +                    }
>
> -                @Override
> -                public void setExitCallback(ExitCallback callback) {
> -                    cb = callback;
> -                }
> +                    @Override
> +                    public void setInputStream(InputStream in) {
> +                        // ignored
> +                    }
>
> -                @Override
> -                public void setErrorStream(OutputStream err) {
> -                    // ignored
> -                }
> +                    @Override
> +                    public void setExitCallback(ExitCallback callback) {
> +                        cb = callback;
> +                    }
>
> -                @Override
> -                public void destroy() {
> -                    // ignored
> -                }
> +                    @Override
> +                    public void setErrorStream(OutputStream err) {
> +                        // ignored
> +                    }
>
> -                @Override
> -                public void start(Environment env) throws IOException {
> -                    exitSignal.release();
> -                    cb.onExit(0, command);
> -                }
> -            };
> +                    @Override
> +                    public void destroy() {
> +                        // ignored
> +                    }
> +
> +                    @Override
> +                    public void start(Environment env) throws IOException
> {
> +                        exitSignal.release();
> +                        cb.onExit(0, command);
> +                    }
> +                };
> +            }
>          });
>          sshd.start();
>          client.start();
> @@ -595,46 +605,54 @@ public class ServerTest extends BaseTestSupport {
>      @Test
>      public void testEnvironmentVariablesPropagationToServer() throws
> Exception {
>          final AtomicReference<Environment> envHolder = new
> AtomicReference<>(null);
> -        sshd.setCommandFactory(command -> {
> -            
> ValidateUtils.checkTrue(String.CASE_INSENSITIVE_ORDER.compare(command,
> getCurrentTestName()) == 0, "Unexpected command: %s", command);
> +        sshd.setCommandFactory(new CommandFactory() {
> +            @Override
> +            public String getName() {
> +                return getCurrentTestName();
> +            }
>
> -            return new Command() {
> -                private ExitCallback cb;
> +            @Override
> +            public Command createCommand(String command) {
> +                
> ValidateUtils.checkTrue(String.CASE_INSENSITIVE_ORDER.compare(command,
> getCurrentTestName()) == 0, "Unexpected command: %s", command);
>
> -                @Override
> -                public void setOutputStream(OutputStream out) {
> -                    // ignored
> -                }
> +                return new Command() {
> +                    private ExitCallback cb;
>
> -                @Override
> -                public void setInputStream(InputStream in) {
> -                    // ignored
> -                }
> +                    @Override
> +                    public void setOutputStream(OutputStream out) {
> +                        // ignored
> +                    }
>
> -                @Override
> -                public void setExitCallback(ExitCallback callback) {
> -                    cb = callback;
> -                }
> +                    @Override
> +                    public void setInputStream(InputStream in) {
> +                        // ignored
> +                    }
>
> -                @Override
> -                public void setErrorStream(OutputStream err) {
> -                    // ignored
> -                }
> +                    @Override
> +                    public void setExitCallback(ExitCallback callback) {
> +                        cb = callback;
> +                    }
>
> -                @Override
> -                public void destroy() {
> -                    // ignored
> -                }
> +                    @Override
> +                    public void setErrorStream(OutputStream err) {
> +                        // ignored
> +                    }
>
> -                @Override
> -                public void start(Environment env) throws IOException {
> -                    if (envHolder.getAndSet(env) != null) {
> -                        throw new StreamCorruptedException("Multiple
> starts for command=" + command);
> +                    @Override
> +                    public void destroy() {
> +                        // ignored
>                      }
>
> -                    cb.onExit(0, command);
> -                }
> -            };
> +                    @Override
> +                    public void start(Environment env) throws IOException
> {
> +                        if (envHolder.getAndSet(env) != null) {
> +                            throw new StreamCorruptedException("Multiple
> starts for command=" + command);
> +                        }
> +
> +                        cb.onExit(0, command);
> +                    }
> +                };
> +            }
>          });
>
>          TestChannelListener channelListener = new TestChannelListener(
> getCurrentTestName());
> @@ -934,6 +952,15 @@ public class ServerTest extends BaseTestSupport {
>          // CHECKSTYLE:ON
>
>          public static class Factory implements CommandFactory {
> +            public Factory() {
> +                super();
> +            }
> +
> +            @Override
> +            public String getName() {
> +                return getClass().getSimpleName();
> +            }
> +
>              @Override
>              public Command createCommand(String name) {
>                  return new StreamCommand(name);
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/util/
> test/AsyncEchoShellFactory.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/test/java/org/apache/sshd/util/test/AsyncEchoShellFactory.java
> b/sshd-core/src/test/java/org/apache/sshd/util/test/
> AsyncEchoShellFactory.java
> index 5193cec..de9dbf4 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/util/test/
> AsyncEchoShellFactory.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/util/test/
> AsyncEchoShellFactory.java
> @@ -29,13 +29,13 @@ import org.apache.sshd.common.io.IoInputStream;
>  import org.apache.sshd.common.io.IoOutputStream;
>  import org.apache.sshd.common.session.Session;
>  import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
> -import org.apache.sshd.server.AsyncCommand;
>  import org.apache.sshd.server.ChannelSessionAware;
> -import org.apache.sshd.server.Command;
>  import org.apache.sshd.server.Environment;
>  import org.apache.sshd.server.ExitCallback;
>  import org.apache.sshd.server.channel.ChannelDataReceiver;
>  import org.apache.sshd.server.channel.ChannelSession;
> +import org.apache.sshd.server.command.AsyncCommand;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.server.shell.ShellFactory;
>
>  /**
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/util/
> test/CommandExecutionHelper.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/test/java/org/apache/sshd/util/test/CommandExecutionHelper.java
> b/sshd-core/src/test/java/org/apache/sshd/util/test/
> CommandExecutionHelper.java
> index c44a2ad..c199a38 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/util/test/
> CommandExecutionHelper.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/util/test/
> CommandExecutionHelper.java
> @@ -26,7 +26,7 @@ import java.io.InterruptedIOException;
>  import java.io.OutputStream;
>  import java.nio.charset.StandardCharsets;
>
> -import org.apache.sshd.server.AbstractCommandSupport;
> +import org.apache.sshd.server.command.AbstractCommandSupport;
>
>  /**
>   * @author <a href="mailto:dev@mina.apache.org";>Apache MINA SSHD
> Project</a>
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-core/src/test/java/org/apache/sshd/util/
> test/EchoShellFactory.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-core/src/test/java/org/apache/sshd/util/test/EchoShellFactory.java
> b/sshd-core/src/test/java/org/apache/sshd/util/test/EchoShellFactory.java
> index fe97a2f..a9ec9d3 100644
> --- a/sshd-core/src/test/java/org/apache/sshd/util/test/
> EchoShellFactory.java
> +++ b/sshd-core/src/test/java/org/apache/sshd/util/test/
> EchoShellFactory.java
> @@ -18,7 +18,7 @@
>   */
>  package org.apache.sshd.util.test;
>
> -import org.apache.sshd.server.Command;
> +import org.apache.sshd.server.command.Command;
>  import org.apache.sshd.server.shell.ShellFactory;
>
>  /**
>
> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/
> f1a8077b/sshd-git/src/main/java/org/apache/sshd/git/
> AbstractGitCommand.java
> ----------------------------------------------------------------------
> diff --git 
> a/sshd-git/src/main/java/org/apache/sshd/git/AbstractGitCommand.java
> b/sshd-git/src/main/java/org/apache/sshd/git/AbstractGitCommand.java
> index d4dacfa..7315610 100644
> --- a/sshd-git/src/main/java/org/apache/sshd/git/AbstractGitCommand.java
> +++ b/sshd-git/src/main/java/org/apache/sshd/git/AbstractGitCommand.java
> @@ -29,8 +29,8 @@ import java.util.concurrent.ExecutorService;
>
>  import org.apache.sshd.common.channel.ChannelOutputStream;
>  import org.apache.sshd.common.file.FileSystemAware;
> -import org.apache.sshd.server.AbstractCommandSupport;
>  import org.apache.sshd.server.SessionAware;
> +import org.apache.sshd.server.command.AbstractCommandSupport;
>  import org.apache.sshd.server.session.ServerSession;
>  import org.apache.sshd.server.session.ServerSessionHolder;
>
>
>


-- 
------------------------
Guillaume Nodet

Reply via email to