You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/05/19 15:59:06 UTC

mina-sshd git commit: [SSHD-468] Propagate ExecutorService from DefaultIoServiceFactoryFactory to actual one

Repository: mina-sshd
Updated Branches:
  refs/heads/master 1c51deb35 -> 9c9f4a614


[SSHD-468] Propagate ExecutorService from DefaultIoServiceFactoryFactory to actual one


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/9c9f4a61
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/9c9f4a61
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/9c9f4a61

Branch: refs/heads/master
Commit: 9c9f4a6140903860f332fef52d3038635e9f7c2f
Parents: 1c51deb
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Tue May 19 16:58:54 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Tue May 19 16:58:54 2015 +0300

----------------------------------------------------------------------
 .../sshd/common/AbstractFactoryManager.java     |   2 +-
 .../common/io/AbstractIoServiceFactory.java     |   9 +-
 .../io/AbstractIoServiceFactoryFactory.java     |  29 ++-
 .../io/BuiltinIoServiceFactoryFactories.java    |  95 +++++++++
 .../io/DefaultIoServiceFactoryFactory.java      |  32 +++-
 .../sshd/common/io/ReadPendingException.java    |  16 ++
 .../sshd/common/io/WritePendingException.java   |  16 ++
 .../sshd/common/io/mina/MinaServiceFactory.java |   4 +-
 .../io/mina/MinaServiceFactoryFactory.java      |   3 +-
 .../sshd/common/io/nio2/Nio2ServiceFactory.java |   6 +-
 .../io/nio2/Nio2ServiceFactoryFactory.java      |   4 +-
 .../apache/sshd/common/io/nio2/Nio2Session.java |   3 +
 .../apache/sshd/common/util/ThreadUtils.java    | 190 ------------------
 .../util/threads/ExecutorServiceCarrier.java    |  35 ++++
 .../util/threads/ExecutorServiceConfigurer.java |  30 +++
 .../sshd/common/util/threads/ThreadUtils.java   | 192 +++++++++++++++++++
 .../apache/sshd/server/command/ScpCommand.java  |   2 +-
 .../sshd/server/command/ScpCommandFactory.java  |   9 +-
 .../apache/sshd/server/sftp/SftpSubsystem.java  |   2 +-
 .../sshd/server/sftp/SftpSubsystemFactory.java  |  10 +-
 .../sshd/server/shell/InvertedShellWrapper.java |   2 +-
 .../BuiltinIoServiceFactoryFactoriesTest.java   |  52 +++++
 .../io/DefaultIoServiceFactoryFactoryTest.java  |  83 ++++++++
 .../sshd/common/util/CloseableUtilsTest.java    |   1 +
 .../sshd/common/util/ThreadUtilsTest.java       |   1 +
 25 files changed, 612 insertions(+), 216 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
index 91ef180..10b64db 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
@@ -38,8 +38,8 @@ import org.apache.sshd.common.session.ConnectionService;
 import org.apache.sshd.common.session.SessionTimeoutListener;
 import org.apache.sshd.common.util.CloseableUtils;
 import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.ThreadUtils;
 import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.threads.ThreadUtils;
 
 /**
  * TODO Add javadoc

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java
index 8acf795..242e427 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java
@@ -25,11 +25,12 @@ import java.util.concurrent.TimeUnit;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.FactoryManagerUtils;
 import org.apache.sshd.common.util.CloseableUtils;
+import org.apache.sshd.common.util.threads.ExecutorServiceCarrier;
 
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public abstract class AbstractIoServiceFactory extends CloseableUtils.AbstractCloseable implements IoServiceFactory {
+public abstract class AbstractIoServiceFactory extends CloseableUtils.AbstractCloseable implements IoServiceFactory, ExecutorServiceCarrier {
 
     private final FactoryManager manager;
     private final ExecutorService executor;
@@ -45,11 +46,13 @@ public abstract class AbstractIoServiceFactory extends CloseableUtils.AbstractCl
         return manager;
     }
 
+    @Override
     public final ExecutorService getExecutorService() {
         return executor;
     }
 
-    public final boolean isShutdownExecutor() {
+    @Override
+    public final boolean isShutdownOnExit() {
         return shutdownExecutor;
     }
 
@@ -57,7 +60,7 @@ public abstract class AbstractIoServiceFactory extends CloseableUtils.AbstractCl
     protected void doCloseImmediately() {
         try {
             ExecutorService service = getExecutorService();
-            if ((service != null) && isShutdownExecutor() && (!service.isShutdown())) {
+            if ((service != null) && isShutdownOnExit() && (!service.isShutdown())) {
                 log.debug("Shutdown executor");
                 service.shutdownNow();
                 if (service.awaitTermination(5, TimeUnit.SECONDS)) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactoryFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactoryFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactoryFactory.java
index 1451770..0cb85f6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactoryFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactoryFactory.java
@@ -21,13 +21,18 @@ package org.apache.sshd.common.io;
 
 import java.util.concurrent.ExecutorService;
 
+import org.apache.sshd.common.util.AbstractLoggingBean;
+import org.apache.sshd.common.util.threads.ExecutorServiceConfigurer;
+
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public abstract class AbstractIoServiceFactoryFactory implements IoServiceFactoryFactory {
+public abstract class AbstractIoServiceFactoryFactory
+                extends AbstractLoggingBean
+                implements IoServiceFactoryFactory, ExecutorServiceConfigurer {
 
-    private final ExecutorService executorService;
-    private final boolean shutdownExecutor;
+    private ExecutorService executorService;
+    private boolean shutdownExecutor;
 
     /**
      * @param executors      The {@link ExecutorService} to use for spawning threads.
@@ -43,11 +48,25 @@ public abstract class AbstractIoServiceFactoryFactory implements IoServiceFactor
         shutdownExecutor = shutdownOnExit;
     }
 
-    public final ExecutorService getExecutorService() {
+    @Override
+    public ExecutorService getExecutorService() {
         return executorService;
     }
 
-    public final boolean isShutdownExecutor() {
+    @Override
+    public void setExecutorService(ExecutorService service) {
+        executorService = service;
+        
+    }
+
+    @Override
+    public boolean isShutdownOnExit() {
         return shutdownExecutor;
     }
+
+    @Override
+    public void setShutdownOnExit(boolean shutdown) {
+        shutdownExecutor = shutdown;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactories.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactories.java b/sshd-core/src/main/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactories.java
new file mode 100644
index 0000000..7d60b0e
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactories.java
@@ -0,0 +1,95 @@
+/*
+ * 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.common.io;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.io.mina.MinaServiceFactoryFactory;
+import org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory;
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public enum BuiltinIoServiceFactoryFactories implements NamedFactory<IoServiceFactoryFactory> {
+    NIO2(Nio2ServiceFactoryFactory.class),
+    NMINA(MinaServiceFactoryFactory.class);
+
+    private final Class<? extends IoServiceFactoryFactory> factoryClass;
+    public final Class<? extends IoServiceFactoryFactory> getFactoryClass() {
+        return factoryClass;
+    }
+
+    BuiltinIoServiceFactoryFactories(Class<? extends IoServiceFactoryFactory> clazz) {
+        factoryClass = clazz;
+    }
+
+    @Override
+    public final String getName() {
+        return name().toLowerCase();
+    }
+    
+    @Override
+    public final IoServiceFactoryFactory create() {
+        Class<? extends IoServiceFactoryFactory>    clazz=getFactoryClass();
+        try {
+            return clazz.newInstance();
+        } catch(Exception e) {
+            if (e instanceof RuntimeException) {
+                throw (RuntimeException) e;
+            } else {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+    
+    public static final Set<BuiltinIoServiceFactoryFactories> VALUES = 
+            Collections.unmodifiableSet(EnumSet.allOf(BuiltinIoServiceFactoryFactories.class));
+    public static final BuiltinIoServiceFactoryFactories fromFactoryName(String name) {
+        if (GenericUtils.isEmpty(name)) {
+            return null;
+        }
+        
+        for (BuiltinIoServiceFactoryFactories f : VALUES) {
+            if (name.equalsIgnoreCase(f.getName())) {
+                return f;
+            }
+        }
+        
+        return null;
+    }
+    
+    public static final BuiltinIoServiceFactoryFactories fromFactoryClass(Class<?> clazz) {
+        if ((clazz == null) || (!IoServiceFactoryFactory.class.isAssignableFrom(clazz))) {
+            return null;
+        }
+        
+        for (BuiltinIoServiceFactoryFactories f : VALUES) {
+            if (clazz.isAssignableFrom(f.getFactoryClass())) {
+                return f;
+            }
+        }
+        
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java
index f40700c..0dcb30d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java
@@ -20,19 +20,30 @@ package org.apache.sshd.common.io;
 
 import java.util.Iterator;
 import java.util.ServiceLoader;
+import java.util.concurrent.ExecutorService;
 
 import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.threads.ExecutorServiceConfigurer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  */
-public class DefaultIoServiceFactoryFactory implements IoServiceFactoryFactory {
+public class DefaultIoServiceFactoryFactory extends AbstractIoServiceFactoryFactory {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(DefaultIoServiceFactoryFactory.class);
 
     private IoServiceFactoryFactory factory;
 
+    public DefaultIoServiceFactoryFactory() {
+        this(null, true);
+    }
+    
+    protected DefaultIoServiceFactoryFactory(ExecutorService executors, boolean shutdownOnExit) {
+        super(executors, shutdownOnExit);
+    }
+
     @Override
     public IoServiceFactory create(FactoryManager manager) {
         return getFactory().create(manager);
@@ -42,16 +53,22 @@ public class DefaultIoServiceFactoryFactory implements IoServiceFactoryFactory {
         synchronized (this) {
             if (factory == null) {
                 factory = newInstance(IoServiceFactoryFactory.class);
+                if (factory instanceof ExecutorServiceConfigurer) {
+                    ExecutorServiceConfigurer   configurer=(ExecutorServiceConfigurer) factory;
+                    configurer.setExecutorService(getExecutorService());
+                    configurer.setShutdownOnExit(isShutdownOnExit());
+                }
             }
         }
         return factory;
     }
 
-    private static <T> T newInstance(Class<T> clazz) {
+    public static <T extends IoServiceFactoryFactory> T newInstance(Class<T> clazz) {
         String factory = System.getProperty(clazz.getName());
-        if (factory != null) {
+        if (!GenericUtils.isEmpty(factory)) {
             return newInstance(clazz, factory);
         }
+
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
         if (cl != null) {
             T t = tryLoad(ServiceLoader.load(clazz, cl));
@@ -68,7 +85,7 @@ public class DefaultIoServiceFactoryFactory implements IoServiceFactoryFactory {
         throw new IllegalStateException("Could not find a valid sshd io provider");
     }
 
-    private static <T> T tryLoad(ServiceLoader<T> loader) {
+    public static <T extends IoServiceFactoryFactory> T tryLoad(ServiceLoader<T> loader) {
         Iterator<T> it = loader.iterator();
         try {
             while (it.hasNext()) {
@@ -84,7 +101,12 @@ public class DefaultIoServiceFactoryFactory implements IoServiceFactoryFactory {
         return null;
     }
 
-    private static <T> T newInstance(Class<T> clazz, String factory) {
+    public static <T extends IoServiceFactoryFactory> T newInstance(Class<T> clazz, String factory) {
+        BuiltinIoServiceFactoryFactories    builtin = BuiltinIoServiceFactoryFactories.fromFactoryName(factory);
+        if (builtin != null) {
+            return clazz.cast(builtin.create());
+        }
+
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
         if (cl != null) {
             try {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/ReadPendingException.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/ReadPendingException.java b/sshd-core/src/main/java/org/apache/sshd/common/io/ReadPendingException.java
index 261acac..a15865a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/ReadPendingException.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/ReadPendingException.java
@@ -19,5 +19,21 @@
 package org.apache.sshd.common.io;
 
 public class ReadPendingException extends IllegalStateException {
+    private static final long serialVersionUID = -3407225601154249841L;
 
+    public ReadPendingException() {
+        super();
+    }
+
+    public ReadPendingException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ReadPendingException(String s) {
+        super(s);
+    }
+
+    public ReadPendingException(Throwable cause) {
+        super(cause);
+    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/WritePendingException.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/WritePendingException.java b/sshd-core/src/main/java/org/apache/sshd/common/io/WritePendingException.java
index 5fde663..2ba281f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/WritePendingException.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/WritePendingException.java
@@ -19,5 +19,21 @@
 package org.apache.sshd.common.io;
 
 public class WritePendingException extends IllegalStateException {
+    private static final long serialVersionUID = 8814014909076826576L;
 
+    public WritePendingException() {
+        super();
+    }
+
+    public WritePendingException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public WritePendingException(String s) {
+        super(s);
+    }
+
+    public WritePendingException(Throwable cause) {
+        super(cause);
+    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
index 7e46407..902e902 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
@@ -29,7 +29,7 @@ import org.apache.sshd.common.io.AbstractIoServiceFactory;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoConnector;
 import org.apache.sshd.common.io.IoHandler;
-import org.apache.sshd.common.util.ThreadUtils;
+import org.apache.sshd.common.util.threads.ThreadUtils;
 
 /**
  */
@@ -44,10 +44,12 @@ public class MinaServiceFactory extends AbstractIoServiceFactory {
         ioProcessor = new SimpleIoProcessorPool<>(NioProcessor.class, getExecutorService(), getNioWorkers(factoryManager), null);
     }
 
+    @Override
     public IoConnector createConnector(IoHandler handler) {
         return new MinaConnector(getFactoryManager(), handler, ioProcessor);
     }
 
+    @Override
     public IoAcceptor createAcceptor(IoHandler handler) {
         return new MinaAcceptor(getFactoryManager(), handler, ioProcessor);
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java
index 1409dc5..e6e913e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactoryFactory.java
@@ -44,7 +44,8 @@ public class MinaServiceFactoryFactory extends AbstractIoServiceFactoryFactory {
         super(executors, shutdownOnExit);
     }
 
+    @Override
     public IoServiceFactory create(FactoryManager manager) {
-        return new MinaServiceFactory(manager, getExecutorService(), isShutdownExecutor());
+        return new MinaServiceFactory(manager, getExecutorService(), isShutdownOnExit());
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
index 5b144d8..6bdd1ba 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
@@ -29,7 +29,7 @@ import org.apache.sshd.common.io.AbstractIoServiceFactory;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoConnector;
 import org.apache.sshd.common.io.IoHandler;
-import org.apache.sshd.common.util.ThreadUtils;
+import org.apache.sshd.common.util.threads.ThreadUtils;
 
 /**
  */
@@ -42,7 +42,7 @@ public class Nio2ServiceFactory extends AbstractIoServiceFactory {
               service == null ? ThreadUtils.newFixedThreadPool(factoryManager.toString() + "-nio2", getNioWorkers(factoryManager)) : service,
               service == null || shutdownOnExit);
         try {
-            group = AsynchronousChannelGroup.withThreadPool(ThreadUtils.protectExecutorServiceShutdown(getExecutorService(), isShutdownExecutor()));
+            group = AsynchronousChannelGroup.withThreadPool(ThreadUtils.protectExecutorServiceShutdown(getExecutorService(), isShutdownOnExit()));
         } catch(IOException e) {
             log.warn("Failed (" + e.getClass().getSimpleName() + " to start async. channel group: " + e.getMessage(), e);
             throw new RuntimeSshException(e);
@@ -67,7 +67,7 @@ public class Nio2ServiceFactory extends AbstractIoServiceFactory {
                 group.shutdownNow();
             
                 // if we protect the executor then the await will fail since we didn't really shut it down...
-                if (isShutdownExecutor()) {
+                if (isShutdownOnExit()) {
                     if (group.awaitTermination(5, TimeUnit.SECONDS)) {
                         log.debug("Group successfully shut down");
                     } else {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java
index 791a1d9..c108fa1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactoryFactory.java
@@ -48,8 +48,8 @@ public class Nio2ServiceFactoryFactory extends AbstractIoServiceFactoryFactory {
         Class<?> clazz = AsynchronousChannel.class;
     }
 
+    @Override
     public IoServiceFactory create(FactoryManager manager) {
-        return new Nio2ServiceFactory(manager, getExecutorService(), isShutdownExecutor());
+        return new Nio2ServiceFactory(manager, getExecutorService(), isShutdownOnExit());
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
index d98f46a..350ac17 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
@@ -248,6 +248,7 @@ public class Nio2Session extends CloseableUtils.AbstractCloseable implements IoS
         socket.read(buffer, null, completion);
     }
 
+    @SuppressWarnings("synthetic-access")
     private void startWriting() {
         final DefaultIoWriteFuture future = writes.peek();
         if (future != null) {
@@ -270,12 +271,14 @@ public class Nio2Session extends CloseableUtils.AbstractCloseable implements IoS
                                 finishWrite();
                             }
                         }
+
                         @Override
                         protected void onFailed(Throwable exc, Object attachment) {
                             future.setException(exc);
                             exceptionCaught(exc);
                             finishWrite();
                         }
+
                         private void finishWrite() {
                             writes.remove(future);
                             currentWrite.compareAndSet(future, null);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/util/ThreadUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/ThreadUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/ThreadUtils.java
deleted file mode 100644
index c5030ab..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/ThreadUtils.java
+++ /dev/null
@@ -1,190 +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.common.util;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.Collections;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Utility class for thread pools.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ThreadUtils {
-
-    /**
-     * Wraps an {@link ExecutorService} in such a way as to &quot;protect&quot;
-     * it for calls to the {@link ExecutorService#shutdown()} or
-     * {@link ExecutorService#shutdownNow()}. All other calls are delegated as-is
-     * to the original service. <B>Note:</B> the exposed wrapped proxy will
-     * answer correctly the {@link ExecutorService#isShutdown()} query if indeed
-     * one of the {@code shutdown} methods was invoked.
-     *
-     * @param executorService The original service - ignored if {@code null}
-     * @param shutdownOnExit  If {@code true} then it is OK to shutdown the executor
-     *                        so no wrapping takes place.
-     * @return Either the original service or a wrapped one - depending on the
-     * value of the <tt>shutdownOnExit</tt> parameter
-     */
-    public static ExecutorService protectExecutorServiceShutdown(final ExecutorService executorService, boolean shutdownOnExit) {
-        if (executorService == null || shutdownOnExit) {
-            return executorService;
-        } else {
-            return (ExecutorService) Proxy.newProxyInstance(
-                    resolveDefaultClassLoader(executorService),
-                    new Class<?>[]{ExecutorService.class},
-                    new InvocationHandler() {
-                        private final AtomicBoolean stopped = new AtomicBoolean(false);
-
-                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-                            String name = method.getName();
-                            if ("isShutdown".equals(name)) {
-                                return stopped.get();
-                            } else if ("shutdown".equals(name)) {
-                                stopped.set(true);
-                                return null;    // void...
-                            } else if ("shutdownNow".equals(name)) {
-                                stopped.set(true);
-                                return Collections.emptyList();
-                            } else {
-                                return method.invoke(executorService, args);
-                            }
-                        }
-                    });
-        }
-    }
-
-    public static ClassLoader resolveDefaultClassLoader(Object anchor) {
-        return resolveDefaultClassLoader(anchor == null ? null : anchor.getClass());
-    }
-
-    /**
-     * Attempts to find the most suitable {@link ClassLoader} as follows:</BR>
-     * <UL>
-     * <LI>
-     * Check the {@link Thread#getContextClassLoader()} value
-     * </LI>
-     * <p/>
-     * <LI>
-     * If no thread context class loader then check the anchor
-     * class (if given) for its class loader
-     * </LI>
-     * <p/>
-     * <LI>
-     * If still no loader available, then use {@link ClassLoader#getSystemClassLoader()}
-     * </LI>
-     * </UL>
-     *
-     * @param anchor
-     * @return
-     */
-    public static ClassLoader resolveDefaultClassLoader(Class<?> anchor) {
-        Thread thread = Thread.currentThread();
-        ClassLoader cl = thread.getContextClassLoader();
-        if (cl != null) {
-            return cl;
-        }
-
-        if (anchor != null) {
-            cl = anchor.getClassLoader();
-        }
-
-        if (cl == null) {   // can happen for core Java classes
-            cl = ClassLoader.getSystemClassLoader();
-        }
-
-        return cl;
-    }
-
-    public static ExecutorService newFixedThreadPool(
-            String poolName,
-            int nThreads
-    ) {
-        return new ThreadPoolExecutor(nThreads, nThreads,
-                0L, TimeUnit.MILLISECONDS,
-                new LinkedBlockingQueue<Runnable>(),
-                new SshdThreadFactory(poolName),
-                new ThreadPoolExecutor.CallerRunsPolicy());
-    }
-
-    public static ExecutorService newCachedThreadPool(
-            String poolName
-    ) {
-        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
-                60L, TimeUnit.SECONDS,
-                new SynchronousQueue<Runnable>(),
-                new SshdThreadFactory(poolName),
-                new ThreadPoolExecutor.CallerRunsPolicy());
-    }
-
-    public static ScheduledExecutorService newSingleThreadScheduledExecutor(
-            String poolName
-    ) {
-        return new ScheduledThreadPoolExecutor(
-                1,
-                new SshdThreadFactory(poolName));
-    }
-
-    public static ExecutorService newSingleThreadExecutor(
-            String poolName
-    ) {
-        return newFixedThreadPool(poolName, 1);
-    }
-
-    public static class SshdThreadFactory implements ThreadFactory {
-
-        private final ThreadGroup group;
-        private final AtomicInteger threadNumber = new AtomicInteger(1);
-        private final String namePrefix;
-
-        public SshdThreadFactory(String name) {
-            SecurityManager s = System.getSecurityManager();
-            group = (s != null) ? s.getThreadGroup() :
-                    Thread.currentThread().getThreadGroup();
-            namePrefix = "sshd-" + name + "-thread-";
-        }
-
-        public Thread newThread(Runnable r) {
-            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
-            if (t.isDaemon())
-                t.setDaemon(false);
-            if (t.getPriority() != Thread.NORM_PRIORITY)
-                t.setPriority(Thread.NORM_PRIORITY);
-            return t;
-        }
-
-    }
-
-    private ThreadUtils() {
-        // no instance allowe
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ExecutorServiceCarrier.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ExecutorServiceCarrier.java b/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ExecutorServiceCarrier.java
new file mode 100644
index 0000000..e208352
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ExecutorServiceCarrier.java
@@ -0,0 +1,35 @@
+/*
+ * 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.common.util.threads;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface ExecutorServiceCarrier {
+    ExecutorService getExecutorService();
+    /**
+     * @return If {@code true} then the {@link ExecutorService#shutdownNow()}
+     * will be called (unless it is an internally allocated service which is always
+     * closed)
+     */
+    boolean isShutdownOnExit();
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ExecutorServiceConfigurer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ExecutorServiceConfigurer.java b/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ExecutorServiceConfigurer.java
new file mode 100644
index 0000000..a29415c
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ExecutorServiceConfigurer.java
@@ -0,0 +1,30 @@
+/*
+ * 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.common.util.threads;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface ExecutorServiceConfigurer extends ExecutorServiceCarrier {
+    void setExecutorService(ExecutorService service);
+    void setShutdownOnExit(boolean shutdown);
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ThreadUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ThreadUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ThreadUtils.java
new file mode 100644
index 0000000..cffa5c2
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/threads/ThreadUtils.java
@@ -0,0 +1,192 @@
+/*
+ * 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.common.util.threads;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collections;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Utility class for thread pools.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ThreadUtils {
+
+    /**
+     * Wraps an {@link ExecutorService} in such a way as to &quot;protect&quot;
+     * it for calls to the {@link ExecutorService#shutdown()} or
+     * {@link ExecutorService#shutdownNow()}. All other calls are delegated as-is
+     * to the original service. <B>Note:</B> the exposed wrapped proxy will
+     * answer correctly the {@link ExecutorService#isShutdown()} query if indeed
+     * one of the {@code shutdown} methods was invoked.
+     *
+     * @param executorService The original service - ignored if {@code null}
+     * @param shutdownOnExit  If {@code true} then it is OK to shutdown the executor
+     *                        so no wrapping takes place.
+     * @return Either the original service or a wrapped one - depending on the
+     * value of the <tt>shutdownOnExit</tt> parameter
+     */
+    public static ExecutorService protectExecutorServiceShutdown(final ExecutorService executorService, boolean shutdownOnExit) {
+        if (executorService == null || shutdownOnExit) {
+            return executorService;
+        } else {
+            return (ExecutorService) Proxy.newProxyInstance(
+                    resolveDefaultClassLoader(executorService),
+                    new Class<?>[]{ExecutorService.class},
+                    new InvocationHandler() {
+                        private final AtomicBoolean stopped = new AtomicBoolean(false);
+
+                        @Override
+                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                            String name = method.getName();
+                            if ("isShutdown".equals(name)) {
+                                return Boolean.valueOf(stopped.get());
+                            } else if ("shutdown".equals(name)) {
+                                stopped.set(true);
+                                return null;    // void...
+                            } else if ("shutdownNow".equals(name)) {
+                                stopped.set(true);
+                                return Collections.emptyList();
+                            } else {
+                                return method.invoke(executorService, args);
+                            }
+                        }
+                    });
+        }
+    }
+
+    public static ClassLoader resolveDefaultClassLoader(Object anchor) {
+        return resolveDefaultClassLoader(anchor == null ? null : anchor.getClass());
+    }
+
+    /**
+     * Attempts to find the most suitable {@link ClassLoader} as follows:</BR>
+     * <UL>
+     * <LI>
+     * Check the {@link Thread#getContextClassLoader()} value
+     * </LI>
+     * <p/>
+     * <LI>
+     * If no thread context class loader then check the anchor
+     * class (if given) for its class loader
+     * </LI>
+     * <p/>
+     * <LI>
+     * If still no loader available, then use {@link ClassLoader#getSystemClassLoader()}
+     * </LI>
+     * </UL>
+     *
+     * @param anchor
+     * @return
+     */
+    public static ClassLoader resolveDefaultClassLoader(Class<?> anchor) {
+        Thread thread = Thread.currentThread();
+        ClassLoader cl = thread.getContextClassLoader();
+        if (cl != null) {
+            return cl;
+        }
+
+        if (anchor != null) {
+            cl = anchor.getClassLoader();
+        }
+
+        if (cl == null) {   // can happen for core Java classes
+            cl = ClassLoader.getSystemClassLoader();
+        }
+
+        return cl;
+    }
+
+    public static ExecutorService newFixedThreadPool(
+            String poolName,
+            int nThreads
+    ) {
+        return new ThreadPoolExecutor(nThreads, nThreads,
+                0L, TimeUnit.MILLISECONDS,
+                new LinkedBlockingQueue<Runnable>(),
+                new SshdThreadFactory(poolName),
+                new ThreadPoolExecutor.CallerRunsPolicy());
+    }
+
+    public static ExecutorService newCachedThreadPool(
+            String poolName
+    ) {
+        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
+                60L, TimeUnit.SECONDS,
+                new SynchronousQueue<Runnable>(),
+                new SshdThreadFactory(poolName),
+                new ThreadPoolExecutor.CallerRunsPolicy());
+    }
+
+    public static ScheduledExecutorService newSingleThreadScheduledExecutor(
+            String poolName
+    ) {
+        return new ScheduledThreadPoolExecutor(
+                1,
+                new SshdThreadFactory(poolName));
+    }
+
+    public static ExecutorService newSingleThreadExecutor(
+            String poolName
+    ) {
+        return newFixedThreadPool(poolName, 1);
+    }
+
+    public static class SshdThreadFactory implements ThreadFactory {
+
+        private final ThreadGroup group;
+        private final AtomicInteger threadNumber = new AtomicInteger(1);
+        private final String namePrefix;
+
+        public SshdThreadFactory(String name) {
+            SecurityManager s = System.getSecurityManager();
+            group = (s != null) ? s.getThreadGroup() :
+                    Thread.currentThread().getThreadGroup();
+            namePrefix = "sshd-" + name + "-thread-";
+        }
+
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
+            if (t.isDaemon())
+                t.setDaemon(false);
+            if (t.getPriority() != Thread.NORM_PRIORITY)
+                t.setPriority(Thread.NORM_PRIORITY);
+            return t;
+        }
+
+    }
+
+    private ThreadUtils() {
+        // no instance allowe
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java b/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
index 593ed43..2cd4638 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
@@ -31,7 +31,7 @@ import org.apache.sshd.common.file.FileSystemAware;
 import org.apache.sshd.common.scp.ScpHelper;
 import org.apache.sshd.common.scp.ScpTransferEventListener;
 import org.apache.sshd.common.util.AbstractLoggingBean;
-import org.apache.sshd.common.util.ThreadUtils;
+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;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java b/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java
index ed3db39..1a96157 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java
@@ -26,6 +26,7 @@ import org.apache.sshd.common.scp.ScpHelper;
 import org.apache.sshd.common.scp.ScpTransferEventListener;
 import org.apache.sshd.common.util.EventListenerUtils;
 import org.apache.sshd.common.util.ObjectBuilder;
+import org.apache.sshd.common.util.threads.ExecutorServiceConfigurer;
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.CommandFactory;
 
@@ -38,7 +39,7 @@ import org.apache.sshd.server.CommandFactory;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class ScpCommandFactory implements CommandFactory, Cloneable {
+public class ScpCommandFactory implements CommandFactory, Cloneable, ExecutorServiceConfigurer {
     /**
      * Command prefix used to identify SCP commands
      */
@@ -89,6 +90,7 @@ public class ScpCommandFactory implements CommandFactory, Cloneable {
             return this;
         }
 
+        @Override
         public ScpCommandFactory build() {
             return factory.clone();
         }
@@ -124,6 +126,7 @@ public class ScpCommandFactory implements CommandFactory, Cloneable {
         delegate = factory;
     }
 
+    @Override
     public ExecutorService getExecutorService() {
         return executors;
     }
@@ -135,10 +138,12 @@ public class ScpCommandFactory implements CommandFactory, Cloneable {
      *                when the command is terminated - unless it is the ad-hoc service, which will be
      *                shutdown regardless
      */
+    @Override
     public void setExecutorService(ExecutorService service) {
         executors = service;
     }
 
+    @Override
     public boolean isShutdownOnExit() {
         return shutdownExecutor;
     }
@@ -148,6 +153,7 @@ public class ScpCommandFactory implements CommandFactory, Cloneable {
      *                  will be called when command terminates - unless it is the ad-hoc
      *                 service, which will be shutdown regardless
      */
+    @Override
     public void setShutdownOnExit(boolean shutdown) {
         shutdownExecutor = shutdown;
     }
@@ -219,6 +225,7 @@ public class ScpCommandFactory implements CommandFactory, Cloneable {
      *         delegate command factory is available
      * @see #SCP_COMMAND_PREFIX
      */
+    @Override
     public Command createCommand(String command) {
         if (command.startsWith(SCP_COMMAND_PREFIX)) {
             return new ScpCommand(command, getExecutorService(), isShutdownOnExit(), getSendBufferSize(), getReceiveBufferSize(), listenerProxy);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
index f4be035..d332508 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java
@@ -85,9 +85,9 @@ import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.IoUtils;
 import org.apache.sshd.common.util.OsUtils;
 import org.apache.sshd.common.util.SelectorUtils;
-import org.apache.sshd.common.util.ThreadUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
+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;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystemFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystemFactory.java b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystemFactory.java
index 2b98fb3..e3a59c6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystemFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystemFactory.java
@@ -23,12 +23,13 @@ import java.util.concurrent.ExecutorService;
 
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.util.ObjectBuilder;
+import org.apache.sshd.common.util.threads.ExecutorServiceConfigurer;
 import org.apache.sshd.server.Command;
 
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class SftpSubsystemFactory implements NamedFactory<Command>, Cloneable {
+public class SftpSubsystemFactory implements NamedFactory<Command>, Cloneable, ExecutorServiceConfigurer {
     public static final String NAME = "sftp";
     public static final UnsupportedAttributePolicy DEFAULT_POLICY = UnsupportedAttributePolicy.Warn;
 
@@ -54,6 +55,7 @@ public class SftpSubsystemFactory implements NamedFactory<Command>, Cloneable {
             return this;
         }
 
+        @Override
         public SftpSubsystemFactory build() {
             // return a clone so that each invocation returns a different instance - avoid shared instances
             return factory.clone();
@@ -68,10 +70,12 @@ public class SftpSubsystemFactory implements NamedFactory<Command>, Cloneable {
         super();
     }
 
+    @Override
     public String getName() {
         return NAME;
     }
 
+    @Override
     public ExecutorService getExecutorService() {
         return executors;
     }
@@ -80,10 +84,12 @@ public class SftpSubsystemFactory implements NamedFactory<Command>, Cloneable {
      * @param service The {@link ExecutorService} to be used by the {@link SftpSubsystem}
      *                command when starting execution. If {@code null} then a single-threaded ad-hoc service is used.
      */
+    @Override
     public void setExecutorService(ExecutorService service) {
         executors = service;
     }
 
+    @Override
     public boolean isShutdownOnExit() {
         return shutdownExecutor;
     }
@@ -93,6 +99,7 @@ public class SftpSubsystemFactory implements NamedFactory<Command>, Cloneable {
      *                       will be called when subsystem terminates - unless it is the ad-hoc service, which
      *                       will be shutdown regardless
      */
+    @Override
     public void setShutdownOnExit(boolean shutdownOnExit) {
         shutdownExecutor = shutdownOnExit;
     }
@@ -113,6 +120,7 @@ public class SftpSubsystemFactory implements NamedFactory<Command>, Cloneable {
         policy = p;
     }
 
+    @Override
     public Command create() {
         return new SftpSubsystem(getExecutorService(), isShutdownOnExit(), getUnsupportedAttributePolicy());
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/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 397f111..69d9379 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
@@ -24,7 +24,7 @@ import java.io.OutputStream;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 
-import org.apache.sshd.common.util.ThreadUtils;
+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;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/test/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactoriesTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactoriesTest.java b/sshd-core/src/test/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactoriesTest.java
new file mode 100644
index 0000000..05d8449
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactoriesTest.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.common.io;
+
+import org.apache.sshd.util.BaseTestSupport;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class BuiltinIoServiceFactoryFactoriesTest extends BaseTestSupport {
+    public BuiltinIoServiceFactoryFactoriesTest() {
+        super();
+    }
+
+    @Test
+    public void testFromFactoryName() {
+        for (String name : new String[] { null, "", getCurrentTestName() }) {
+            assertNull("Unexpected success for name='" + name + "'", BuiltinIoServiceFactoryFactories.fromFactoryName(name));
+        }
+
+        for (BuiltinIoServiceFactoryFactories expected : BuiltinIoServiceFactoryFactories.VALUES) {
+            String  name=expected.getName();
+            assertSame(name, expected, BuiltinIoServiceFactoryFactories.fromFactoryName(name));
+        }
+    }
+
+    @Test
+    public void testFromFactoryClass() {
+        for (BuiltinIoServiceFactoryFactories expected : BuiltinIoServiceFactoryFactories.VALUES) {
+            Class<?>    clazz=expected.getFactoryClass();
+            assertSame(clazz.getSimpleName(), expected, BuiltinIoServiceFactoryFactories.fromFactoryClass(clazz));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/test/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactoryTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactoryTest.java b/sshd-core/src/test/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactoryTest.java
new file mode 100644
index 0000000..dea271d
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactoryTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.common.io;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.concurrent.ExecutorService;
+
+import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.util.threads.ExecutorServiceCarrier;
+import org.apache.sshd.util.BaseTestSupport;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DefaultIoServiceFactoryFactoryTest extends BaseTestSupport {
+    public DefaultIoServiceFactoryFactoryTest() {
+        super();
+    }
+
+    @Test
+    public void testBuiltinIoServiceFactoryFactories() {
+        for (BuiltinIoServiceFactoryFactories f : BuiltinIoServiceFactoryFactories.VALUES) {
+            String name = f.getName();
+            IoServiceFactoryFactory factoryInstance = 
+                    DefaultIoServiceFactoryFactory.newInstance(IoServiceFactoryFactory.class, name);
+            Class<?>    expected = f.getFactoryClass(), actual = factoryInstance.getClass();
+            assertSame(name, expected, actual);
+        }
+    }
+
+    @SuppressWarnings("boxing")
+    @Test
+    public void testExecutorServiceInitialization() throws IOException {
+        ExecutorService service = Mockito.mock(ExecutorService.class);
+        Mockito.when(service.shutdownNow()).thenReturn(Collections.<Runnable>emptyList());
+        Mockito.when(service.isShutdown()).thenReturn(Boolean.TRUE);
+        Mockito.when(service.isTerminated()).thenReturn(Boolean.TRUE);
+
+        FactoryManager manager = Mockito.mock(FactoryManager.class);
+        Mockito.when(manager.getProperties()).thenReturn(Collections.<String,String>emptyMap());
+
+        String propName = IoServiceFactoryFactory.class.getName();
+        for (BuiltinIoServiceFactoryFactories f : BuiltinIoServiceFactoryFactories.VALUES) {
+            String name = f.getName();
+            try {
+                System.setProperty(propName, name);
+                for (boolean shutdownOnExit : new boolean[] { true, false } ) {
+                    DefaultIoServiceFactoryFactory defaultFactory = new DefaultIoServiceFactoryFactory(service, shutdownOnExit);
+
+                    try(IoServiceFactory factory = defaultFactory.create(manager)) {
+                        assertObjectInstanceOf(name + "/" + shutdownOnExit + " no executor service configuration", ExecutorServiceCarrier.class, factory);
+                        
+                        ExecutorServiceCarrier  carrier = (ExecutorServiceCarrier) factory;
+                        assertSame(name + "/" + shutdownOnExit + " - mismatched executor service", service, carrier.getExecutorService());
+                        assertEquals(name + "/" + shutdownOnExit + " - mismatched shutdown on exit", shutdownOnExit, carrier.isShutdownOnExit());
+                    }
+                }
+            }  finally {
+                System.clearProperty(propName);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/test/java/org/apache/sshd/common/util/CloseableUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/util/CloseableUtilsTest.java b/sshd-core/src/test/java/org/apache/sshd/common/util/CloseableUtilsTest.java
index 518cf6b..17723eb 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/util/CloseableUtilsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/util/CloseableUtilsTest.java
@@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.future.DefaultCloseFuture;
+import org.apache.sshd.common.util.threads.ThreadUtils;
 import org.apache.sshd.util.BaseTestSupport;
 import org.junit.Test;
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/9c9f4a61/sshd-core/src/test/java/org/apache/sshd/common/util/ThreadUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/util/ThreadUtilsTest.java b/sshd-core/src/test/java/org/apache/sshd/common/util/ThreadUtilsTest.java
index 7af65d5..d1c291c 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/util/ThreadUtilsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/util/ThreadUtilsTest.java
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
+import org.apache.sshd.common.util.threads.ThreadUtils;
 import org.apache.sshd.util.BaseTestSupport;
 import org.junit.Test;