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 2017/12/18 17:55:37 UTC
mina-sshd git commit: [SSHD-787] Provide fine-grained control over
SCP stream paths resolution
Repository: mina-sshd
Updated Branches:
refs/heads/master 014bf86c5 -> 1cd204b7a
[SSHD-787] Provide fine-grained control over SCP stream paths resolution
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/1cd204b7
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/1cd204b7
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/1cd204b7
Branch: refs/heads/master
Commit: 1cd204b7ad221d74211d67b3a4659b6210a6fa56
Parents: 014bf86
Author: Lyor Goldstein <ly...@gmail.com>
Authored: Fri Dec 15 19:05:27 2017 +0200
Committer: Lyor Goldstein <ly...@gmail.com>
Committed: Mon Dec 18 19:57:33 2017 +0200
----------------------------------------------------------------------
.../sshd/client/ClientFactoryManager.java | 2 +
.../java/org/apache/sshd/client/SshClient.java | 12 +++++
.../sshd/client/scp/DefaultScpClient.java | 16 +++++--
.../sshd/client/scp/ScpClientCreator.java | 29 +++++++++---
.../client/session/AbstractClientSession.java | 16 ++++++-
.../sshd/client/subsystem/sftp/SftpCommand.java | 2 +-
.../org/apache/sshd/common/scp/ScpHelper.java | 18 +++----
.../common/scp/ScpStreamResolverFactory.java | 32 +++++++++++++
.../scp/ScpStreamResolverFactoryHolder.java | 29 ++++++++++++
.../DefaultScpStreamResolverFactory.java | 50 ++++++++++++++++++++
.../org/apache/sshd/server/scp/ScpCommand.java | 10 ++--
.../sshd/server/scp/ScpCommandFactory.java | 27 ++++++++++-
.../org/apache/sshd/client/scp/ScpTest.java | 11 +++--
13 files changed, 224 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
index 31b2a22..e116651 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
@@ -24,6 +24,7 @@ import org.apache.sshd.client.session.ClientProxyConnectorHolder;
import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.scp.ScpFileOpenerHolder;
+import org.apache.sshd.common.scp.ScpStreamResolverFactoryHolder;
/**
* The <code>ClientFactoryManager</code> enable the retrieval of additional
@@ -34,6 +35,7 @@ import org.apache.sshd.common.scp.ScpFileOpenerHolder;
public interface ClientFactoryManager
extends FactoryManager,
ScpFileOpenerHolder,
+ ScpStreamResolverFactoryHolder,
ClientProxyConnectorHolder,
ClientAuthenticationManager {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
index 0e8979e..a23d098 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
@@ -115,6 +115,7 @@ import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.mac.BuiltinMacs;
import org.apache.sshd.common.mac.Mac;
import org.apache.sshd.common.scp.ScpFileOpener;
+import org.apache.sshd.common.scp.ScpStreamResolverFactory;
import org.apache.sshd.common.session.helpers.AbstractSession;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.OsUtils;
@@ -211,6 +212,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
private FilePasswordProvider filePasswordProvider;
private PasswordIdentityProvider passwordIdentityProvider;
private ScpFileOpener scpOpener;
+ private ScpStreamResolverFactory scpStreamFactory;
private final List<Object> identities = new CopyOnWriteArrayList<>();
private final AuthenticationIdentitiesProvider identitiesProvider;
@@ -248,6 +250,16 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
}
@Override
+ public ScpStreamResolverFactory getScpStreamResolverFactory() {
+ return scpStreamFactory;
+ }
+
+ @Override
+ public void setScpStreamResolverFactory(ScpStreamResolverFactory factory) {
+ scpStreamFactory = factory;
+ }
+
+ @Override
public ServerKeyVerifier getServerKeyVerifier() {
return serverKeyVerifier;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
index d69252c..ead4c52 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
@@ -47,9 +47,11 @@ import org.apache.sshd.common.file.util.MockPath;
import org.apache.sshd.common.scp.ScpFileOpener;
import org.apache.sshd.common.scp.ScpHelper;
import org.apache.sshd.common.scp.ScpLocation;
+import org.apache.sshd.common.scp.ScpStreamResolverFactory;
import org.apache.sshd.common.scp.ScpTimestamp;
import org.apache.sshd.common.scp.ScpTransferEventListener;
import org.apache.sshd.common.scp.helpers.DefaultScpFileOpener;
+import org.apache.sshd.common.scp.helpers.DefaultScpStreamResolverFactory;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.io.NoCloseInputStream;
@@ -64,12 +66,16 @@ public class DefaultScpClient extends AbstractScpClient {
public static final String SCP_PORT_OPTION = "-P";
protected final ScpFileOpener opener;
+ protected final ScpStreamResolverFactory streamFactory;
protected final ScpTransferEventListener listener;
private final ClientSession clientSession;
- public DefaultScpClient(ClientSession clientSession, ScpFileOpener fileOpener, ScpTransferEventListener eventListener) {
+ public DefaultScpClient(
+ ClientSession clientSession, ScpFileOpener fileOpener,
+ ScpStreamResolverFactory streamFactory, ScpTransferEventListener eventListener) {
this.clientSession = Objects.requireNonNull(clientSession, "No client session");
this.opener = (fileOpener == null) ? DefaultScpFileOpener.INSTANCE : fileOpener;
+ this.streamFactory = (streamFactory == null) ? DefaultScpStreamResolverFactory.INSTANCE : streamFactory;
this.listener = (eventListener == null) ? ScpTransferEventListener.EMPTY : eventListener;
}
@@ -86,7 +92,7 @@ public class DefaultScpClient extends AbstractScpClient {
try (InputStream invOut = channel.getInvertedOut();
OutputStream invIn = channel.getInvertedIn()) {
// NOTE: we use a mock file system since we expect no invocations for it
- ScpHelper helper = new ScpHelper(session, invOut, invIn, new MockFileSystem(remote), opener, listener);
+ ScpHelper helper = new ScpHelper(session, invOut, invIn, new MockFileSystem(remote), opener, streamFactory, listener);
helper.receiveFileStream(local, ScpHelper.DEFAULT_RECEIVE_BUFFER_SIZE);
handleCommandExitStatus(cmd, channel);
} finally {
@@ -101,7 +107,7 @@ public class DefaultScpClient extends AbstractScpClient {
ChannelExec channel = openCommandChannel(session, cmd);
try (InputStream invOut = channel.getInvertedOut();
OutputStream invIn = channel.getInvertedIn()) {
- ScpHelper helper = new ScpHelper(session, invOut, invIn, fs, opener, listener);
+ ScpHelper helper = new ScpHelper(session, invOut, invIn, fs, opener, streamFactory, listener);
helper.receive(local,
options.contains(Option.Recursive),
options.contains(Option.TargetIsDirectory),
@@ -126,7 +132,7 @@ public class DefaultScpClient extends AbstractScpClient {
try (InputStream invOut = channel.getInvertedOut();
OutputStream invIn = channel.getInvertedIn()) {
// NOTE: we use a mock file system since we expect no invocations for it
- ScpHelper helper = new ScpHelper(session, invOut, invIn, new MockFileSystem(remote), opener, listener);
+ ScpHelper helper = new ScpHelper(session, invOut, invIn, new MockFileSystem(remote), opener, streamFactory, listener);
Path mockPath = new MockPath(remote);
helper.sendStream(new DefaultScpStreamResolver(name, mockPath, perms, time, size, local, cmd),
options.contains(Option.PreserveAttributes), ScpHelper.DEFAULT_SEND_BUFFER_SIZE);
@@ -154,7 +160,7 @@ public class DefaultScpClient extends AbstractScpClient {
try (InputStream invOut = channel.getInvertedOut();
OutputStream invIn = channel.getInvertedIn()) {
- ScpHelper helper = new ScpHelper(session, invOut, invIn, fs, opener, listener);
+ ScpHelper helper = new ScpHelper(session, invOut, invIn, fs, opener, streamFactory, listener);
executor.execute(helper, local, options);
} finally {
try {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/client/scp/ScpClientCreator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/scp/ScpClientCreator.java b/sshd-core/src/main/java/org/apache/sshd/client/scp/ScpClientCreator.java
index b3199b2..502e5aa 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/scp/ScpClientCreator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/scp/ScpClientCreator.java
@@ -21,22 +21,26 @@ package org.apache.sshd.client.scp;
import org.apache.sshd.common.scp.ScpFileOpener;
import org.apache.sshd.common.scp.ScpFileOpenerHolder;
+import org.apache.sshd.common.scp.ScpStreamResolverFactory;
+import org.apache.sshd.common.scp.ScpStreamResolverFactoryHolder;
import org.apache.sshd.common.scp.ScpTransferEventListener;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public interface ScpClientCreator extends ScpFileOpenerHolder {
+public interface ScpClientCreator extends ScpFileOpenerHolder, ScpStreamResolverFactoryHolder {
/**
* Create an SCP client from this session.
*
* @return An {@link ScpClient} instance. <B>Note:</B> uses the currently
- * registered {@link ScpTransferEventListener} and {@link ScpFileOpener} if any
+ * registered {@link ScpTransferEventListener}, {@link ScpStreamResolverFactoryHolder}
+ * and {@link ScpFileOpener} if any
* @see #setScpFileOpener(ScpFileOpener)
+ * @see #setScpStreamResolverFactory(ScpStreamResolverFactory)
* @see #setScpTransferEventListener(ScpTransferEventListener)
*/
default ScpClient createScpClient() {
- return createScpClient(getScpFileOpener(), getScpTransferEventListener());
+ return createScpClient(getScpFileOpener(), getScpStreamResolverFactory(), getScpTransferEventListener());
}
/**
@@ -49,7 +53,7 @@ public interface ScpClientCreator extends ScpFileOpenerHolder {
* @return An {@link ScpClient} instance
*/
default ScpClient createScpClient(ScpTransferEventListener listener) {
- return createScpClient(getScpFileOpener(), listener);
+ return createScpClient(getScpFileOpener(), getScpStreamResolverFactory(), listener);
}
/**
@@ -62,7 +66,18 @@ public interface ScpClientCreator extends ScpFileOpenerHolder {
* @return An {@link ScpClient} instance
*/
default ScpClient createScpClient(ScpFileOpener opener) {
- return createScpClient(opener, getScpTransferEventListener());
+ return createScpClient(opener, getScpStreamResolverFactory(), getScpTransferEventListener());
+ }
+
+ /**
+ * Create an SCP client from this session.
+ *
+ * @param factory The {@link ScpStreamResolverFactory} used to create input/output stream
+ * for incoming/outgoing files
+ * @return An {@link ScpClient} instance
+ */
+ default ScpClient createScpClient(ScpStreamResolverFactory factory) {
+ return createScpClient(getScpFileOpener(), factory, getScpTransferEventListener());
}
/**
@@ -72,13 +87,15 @@ public interface ScpClientCreator extends ScpFileOpenerHolder {
* are read/written. If {@code null} then a default opener is used.
* <B>Note:</B> this opener is used <U>instead</U> of any instance
* set via {@link #setScpFileOpener(ScpFileOpener)}
+ * @param factory The {@link ScpStreamResolverFactory} to use in order to create
+ * incoming/outgoing streams for received/sent files
* @param listener A {@link ScpTransferEventListener} that can be used
* to receive information about the SCP operations - may be {@code null}
* to indicate no more events are required. <B>Note:</B> this listener
* is used <U>instead</U> of any listener set via {@link #setScpTransferEventListener(ScpTransferEventListener)}
* @return An {@link ScpClient} instance
*/
- ScpClient createScpClient(ScpFileOpener opener, ScpTransferEventListener listener);
+ ScpClient createScpClient(ScpFileOpener opener, ScpStreamResolverFactory factory, ScpTransferEventListener listener);
/**
* @return The last {@link ScpTransferEventListener} set via
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
index b67310d..ee8c550 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
@@ -66,6 +66,7 @@ import org.apache.sshd.common.io.IoWriteFuture;
import org.apache.sshd.common.kex.KexProposalOption;
import org.apache.sshd.common.kex.KexState;
import org.apache.sshd.common.scp.ScpFileOpener;
+import org.apache.sshd.common.scp.ScpStreamResolverFactory;
import org.apache.sshd.common.scp.ScpTransferEventListener;
import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.session.Session;
@@ -90,6 +91,7 @@ public abstract class AbstractClientSession extends AbstractSession implements C
private List<NamedFactory<UserAuth>> userAuthFactories;
private ScpTransferEventListener scpListener;
private ScpFileOpener scpOpener;
+ private ScpStreamResolverFactory scpStreamFactory;
private SocketAddress connectAddress;
private ClientProxyConnector proxyConnector;
@@ -317,6 +319,16 @@ public abstract class AbstractClientSession extends AbstractSession implements C
}
@Override
+ public ScpStreamResolverFactory getScpStreamResolverFactory() {
+ return resolveEffectiveProvider(ScpStreamResolverFactory.class, scpStreamFactory, getFactoryManager().getScpStreamResolverFactory());
+ }
+
+ @Override
+ public void setScpStreamResolverFactory(ScpStreamResolverFactory factory) {
+ scpStreamFactory = factory;
+ }
+
+ @Override
public ScpTransferEventListener getScpTransferEventListener() {
return scpListener;
}
@@ -327,8 +339,8 @@ public abstract class AbstractClientSession extends AbstractSession implements C
}
@Override
- public ScpClient createScpClient(ScpFileOpener opener, ScpTransferEventListener listener) {
- return new DefaultScpClient(this, opener, listener);
+ public ScpClient createScpClient(ScpFileOpener opener, ScpStreamResolverFactory factory, ScpTransferEventListener listener) {
+ return new DefaultScpClient(this, opener, factory, listener);
}
@Override
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
index 4865431..3b8e88f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
@@ -81,7 +81,7 @@ public class SftpCommand implements Channel {
public SftpCommand(SftpClient client) {
this.client = Objects.requireNonNull(client, "No client");
- Map<String, CommandExecutor> map = new TreeMap<>();
+ Map<String, CommandExecutor> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (CommandExecutor e : Arrays.asList(
new ExitCommandExecutor(),
new PwdCommandExecutor(),
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java b/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java
index 9918e02..0e75e83 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java
@@ -48,8 +48,7 @@ import org.apache.sshd.common.SshException;
import org.apache.sshd.common.file.util.MockPath;
import org.apache.sshd.common.scp.ScpTransferEventListener.FileOperation;
import org.apache.sshd.common.scp.helpers.DefaultScpFileOpener;
-import org.apache.sshd.common.scp.helpers.LocalFileScpSourceStreamResolver;
-import org.apache.sshd.common.scp.helpers.LocalFileScpTargetStreamResolver;
+import org.apache.sshd.common.scp.helpers.DefaultScpStreamResolverFactory;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.session.SessionHolder;
import org.apache.sshd.common.util.GenericUtils;
@@ -104,17 +103,20 @@ public class ScpHelper extends AbstractLoggingBean implements SessionHolder<Sess
protected final OutputStream out;
protected final FileSystem fileSystem;
protected final ScpFileOpener opener;
+ protected final ScpStreamResolverFactory streamFactory;
protected final ScpTransferEventListener listener;
private final Session sessionInstance;
public ScpHelper(Session session, InputStream in, OutputStream out,
- FileSystem fileSystem, ScpFileOpener opener, ScpTransferEventListener eventListener) {
+ FileSystem fileSystem, ScpFileOpener opener,
+ ScpStreamResolverFactory streamFactory, ScpTransferEventListener eventListener) {
this.sessionInstance = Objects.requireNonNull(session, "No session");
this.in = Objects.requireNonNull(in, "No input stream");
this.out = Objects.requireNonNull(out, "No output stream");
this.fileSystem = fileSystem;
this.opener = (opener == null) ? DefaultScpFileOpener.INSTANCE : opener;
+ this.streamFactory = (streamFactory == null) ? DefaultScpStreamResolverFactory.INSTANCE : streamFactory;
this.listener = (eventListener == null) ? ScpTransferEventListener.EMPTY : eventListener;
}
@@ -129,7 +131,7 @@ public class ScpHelper extends AbstractLoggingBean implements SessionHolder<Sess
throw new StreamCorruptedException("Cannot download a directory into a file stream: " + line);
}
- final Path path = new MockPath(line);
+ Path path = new MockPath(line);
receiveStream(line, new ScpTargetStreamResolver() {
@SuppressWarnings("synthetic-access")
@Override
@@ -147,8 +149,8 @@ public class ScpHelper extends AbstractLoggingBean implements SessionHolder<Sess
return path;
}
- @Override
@SuppressWarnings("synthetic-access")
+ @Override
public void postProcessReceivedData(String name, boolean preserve, Set<PosixFilePermission> perms, ScpTimestamp time) throws IOException {
if (log.isDebugEnabled()) {
log.debug("postProcessReceivedData({}) name={}, perms={}, preserve={} time={}",
@@ -164,7 +166,7 @@ public class ScpHelper extends AbstractLoggingBean implements SessionHolder<Sess
});
}
- public void receive(Path local, boolean recursive, boolean shouldBeDir, boolean preserve, final int bufferSize) throws IOException {
+ public void receive(Path local, boolean recursive, boolean shouldBeDir, boolean preserve, int bufferSize) throws IOException {
Path path = Objects.requireNonNull(local, "No local path").normalize().toAbsolutePath();
if (shouldBeDir) {
LinkOption[] options = IoUtils.getLinkOptions(true);
@@ -338,7 +340,7 @@ public class ScpHelper extends AbstractLoggingBean implements SessionHolder<Sess
this, header, path, preserve, time, bufferSize);
}
- receiveStream(header, new LocalFileScpTargetStreamResolver(path, opener), time, preserve, bufferSize);
+ receiveStream(header, streamFactory.createScpTargetStreamResolver(path, opener), time, preserve, bufferSize);
}
public void receiveStream(String header, ScpTargetStreamResolver resolver, ScpTimestamp time, boolean preserve, int bufferSize) throws IOException {
@@ -558,7 +560,7 @@ public class ScpHelper extends AbstractLoggingBean implements SessionHolder<Sess
log.debug("sendFile({})[preserve={},buffer-size={}] Sending file {}", this, preserve, bufferSize, path);
}
- sendStream(new LocalFileScpSourceStreamResolver(path, opener), preserve, bufferSize);
+ sendStream(streamFactory.createScpSourceStreamResolver(path, opener), preserve, bufferSize);
}
public void sendStream(ScpSourceStreamResolver resolver, boolean preserve, int bufferSize) throws IOException {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpStreamResolverFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpStreamResolverFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpStreamResolverFactory.java
new file mode 100644
index 0000000..0dce708
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpStreamResolverFactory.java
@@ -0,0 +1,32 @@
+/*
+ * 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.scp;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface ScpStreamResolverFactory {
+ ScpSourceStreamResolver createScpSourceStreamResolver(Path path, ScpFileOpener opener) throws IOException;
+
+ ScpTargetStreamResolver createScpTargetStreamResolver(Path path, ScpFileOpener opener) throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpStreamResolverFactoryHolder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpStreamResolverFactoryHolder.java b/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpStreamResolverFactoryHolder.java
new file mode 100644
index 0000000..3483629
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpStreamResolverFactoryHolder.java
@@ -0,0 +1,29 @@
+/*
+ * 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.scp;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface ScpStreamResolverFactoryHolder {
+ ScpStreamResolverFactory getScpStreamResolverFactory();
+
+ void setScpStreamResolverFactory(ScpStreamResolverFactory factory);
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/common/scp/helpers/DefaultScpStreamResolverFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/scp/helpers/DefaultScpStreamResolverFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/scp/helpers/DefaultScpStreamResolverFactory.java
new file mode 100644
index 0000000..60933e0
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/scp/helpers/DefaultScpStreamResolverFactory.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.common.scp.helpers;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import org.apache.sshd.common.scp.ScpFileOpener;
+import org.apache.sshd.common.scp.ScpSourceStreamResolver;
+import org.apache.sshd.common.scp.ScpStreamResolverFactory;
+import org.apache.sshd.common.scp.ScpTargetStreamResolver;
+import org.apache.sshd.common.util.logging.AbstractLoggingBean;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DefaultScpStreamResolverFactory extends AbstractLoggingBean implements ScpStreamResolverFactory {
+ public static final DefaultScpStreamResolverFactory INSTANCE = new DefaultScpStreamResolverFactory();
+
+ public DefaultScpStreamResolverFactory() {
+ super();
+ }
+
+ @Override
+ public ScpSourceStreamResolver createScpSourceStreamResolver(Path path, ScpFileOpener opener) throws IOException {
+ return new LocalFileScpSourceStreamResolver(path, opener);
+ }
+
+ @Override
+ public ScpTargetStreamResolver createScpTargetStreamResolver(Path path, ScpFileOpener opener) throws IOException {
+ return new LocalFileScpTargetStreamResolver(path, opener);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommand.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommand.java b/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommand.java
index e59a331..3667aa1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommand.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommand.java
@@ -31,8 +31,10 @@ import org.apache.sshd.common.file.FileSystemAware;
import org.apache.sshd.common.scp.ScpException;
import org.apache.sshd.common.scp.ScpFileOpener;
import org.apache.sshd.common.scp.ScpHelper;
+import org.apache.sshd.common.scp.ScpStreamResolverFactory;
import org.apache.sshd.common.scp.ScpTransferEventListener;
import org.apache.sshd.common.scp.helpers.DefaultScpFileOpener;
+import org.apache.sshd.common.scp.helpers.DefaultScpStreamResolverFactory;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.session.SessionHolder;
import org.apache.sshd.common.util.GenericUtils;
@@ -61,7 +63,7 @@ public class ScpCommand
protected final int sendBufferSize;
protected final int receiveBufferSize;
protected final ScpFileOpener opener;
-
+ protected final ScpStreamResolverFactory streamFactory;
protected boolean optR;
protected boolean optT;
protected boolean optF;
@@ -91,6 +93,7 @@ public class ScpCommand
* @param sendSize Size (in bytes) of buffer to use when sending files
* @param receiveSize Size (in bytes) of buffer to use when receiving files
* @param fileOpener The {@link ScpFileOpener} - if {@code null} then {@link DefaultScpFileOpener} is used
+ * @param factory The {@link ScpStreamResolverFactory} - if {@code null} then {@link DefaultScpStreamResolverFactory} is used
* @param eventListener An {@link ScpTransferEventListener} - may be {@code null}
* @see ThreadUtils#newSingleThreadExecutor(String)
* @see ScpHelper#MIN_SEND_BUFFER_SIZE
@@ -99,7 +102,7 @@ public class ScpCommand
public ScpCommand(String command,
ExecutorService executorService, boolean shutdownOnExit,
int sendSize, int receiveSize,
- ScpFileOpener fileOpener, ScpTransferEventListener eventListener) {
+ ScpFileOpener fileOpener, ScpStreamResolverFactory factory, ScpTransferEventListener eventListener) {
name = command;
if (executorService == null) {
@@ -126,6 +129,7 @@ public class ScpCommand
receiveBufferSize = receiveSize;
opener = (fileOpener == null) ? DefaultScpFileOpener.INSTANCE : fileOpener;
+ streamFactory = (factory == null) ? DefaultScpStreamResolverFactory.INSTANCE : factory;
listener = (eventListener == null) ? ScpTransferEventListener.EMPTY : eventListener;
if (log.isDebugEnabled()) {
@@ -269,7 +273,7 @@ public class ScpCommand
public void run() {
int exitValue = ScpHelper.OK;
String exitMessage = null;
- ScpHelper helper = new ScpHelper(getServerSession(), in, out, fileSystem, opener, listener);
+ ScpHelper helper = new ScpHelper(getServerSession(), in, out, fileSystem, opener, streamFactory, listener);
try {
if (optT) {
helper.receive(helper.resolveLocalPath(path), optR, optD, optP, receiveBufferSize);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommandFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommandFactory.java b/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommandFactory.java
index 67549b5..b3b2d89 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommandFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/scp/ScpCommandFactory.java
@@ -25,6 +25,8 @@ import java.util.concurrent.ExecutorService;
import org.apache.sshd.common.scp.ScpFileOpener;
import org.apache.sshd.common.scp.ScpFileOpenerHolder;
import org.apache.sshd.common.scp.ScpHelper;
+import org.apache.sshd.common.scp.ScpStreamResolverFactory;
+import org.apache.sshd.common.scp.ScpStreamResolverFactoryHolder;
import org.apache.sshd.common.scp.ScpTransferEventListener;
import org.apache.sshd.common.util.EventListenerUtils;
import org.apache.sshd.common.util.ObjectBuilder;
@@ -40,7 +42,12 @@ import org.apache.sshd.server.CommandFactory;
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
* @see ScpCommand
*/
-public class ScpCommandFactory implements ScpFileOpenerHolder, CommandFactory, Cloneable, ExecutorServiceConfigurer {
+public class ScpCommandFactory
+ implements ScpFileOpenerHolder,
+ ScpStreamResolverFactoryHolder,
+ CommandFactory,
+ Cloneable,
+ ExecutorServiceConfigurer {
/**
* A useful {@link ObjectBuilder} for {@link ScpCommandFactory}
*/
@@ -56,6 +63,11 @@ public class ScpCommandFactory implements ScpFileOpenerHolder, CommandFactory, C
return this;
}
+ public Builder withScpStreamResolverFactory(ScpStreamResolverFactory streamFactory) {
+ factory.setScpStreamResolverFactory(streamFactory);
+ return this;
+ }
+
public Builder withDelegate(CommandFactory delegate) {
factory.setDelegateCommandFactory(delegate);
return this;
@@ -105,6 +117,7 @@ public class ScpCommandFactory implements ScpFileOpenerHolder, CommandFactory, C
private ExecutorService executors;
private boolean shutdownExecutor;
private ScpFileOpener fileOpener;
+ private ScpStreamResolverFactory streamFactory;
private int sendBufferSize = ScpHelper.MIN_SEND_BUFFER_SIZE;
private int receiveBufferSize = ScpHelper.MIN_RECEIVE_BUFFER_SIZE;
private Collection<ScpTransferEventListener> listeners = new CopyOnWriteArraySet<>();
@@ -124,6 +137,16 @@ public class ScpCommandFactory implements ScpFileOpenerHolder, CommandFactory, C
this.fileOpener = fileOpener;
}
+ @Override
+ public ScpStreamResolverFactory getScpStreamResolverFactory() {
+ return streamFactory;
+ }
+
+ @Override
+ public void setScpStreamResolverFactory(ScpStreamResolverFactory streamFactory) {
+ this.streamFactory = streamFactory;
+ }
+
public CommandFactory getDelegateCommandFactory() {
return delegate;
}
@@ -242,7 +265,7 @@ public class ScpCommandFactory implements ScpFileOpenerHolder, CommandFactory, C
return new ScpCommand(command,
getExecutorService(), isShutdownOnExit(),
getSendBufferSize(), getReceiveBufferSize(),
- getScpFileOpener(), listenerProxy);
+ getScpFileOpener(), getScpStreamResolverFactory(), listenerProxy);
}
CommandFactory factory = getDelegateCommandFactory();
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1cd204b7/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
index 42907d6..56ee962 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
@@ -53,8 +53,10 @@ import org.apache.sshd.common.random.Random;
import org.apache.sshd.common.scp.ScpException;
import org.apache.sshd.common.scp.ScpFileOpener;
import org.apache.sshd.common.scp.ScpHelper;
+import org.apache.sshd.common.scp.ScpStreamResolverFactory;
import org.apache.sshd.common.scp.ScpTransferEventListener;
import org.apache.sshd.common.scp.helpers.DefaultScpFileOpener;
+import org.apache.sshd.common.scp.helpers.DefaultScpStreamResolverFactory;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.OsUtils;
@@ -768,8 +770,9 @@ public class ScpTest extends BaseTestSupport {
private ExitCallback delegate;
InternalScpCommand(String command, ExecutorService executorService, boolean shutdownOnExit,
- int sendSize, int receiveSize, ScpFileOpener opener, ScpTransferEventListener eventListener) {
- super(command, executorService, shutdownOnExit, sendSize, receiveSize, opener, eventListener);
+ int sendSize, int receiveSize, ScpFileOpener opener,
+ ScpStreamResolverFactory factory, ScpTransferEventListener eventListener) {
+ super(command, executorService, shutdownOnExit, sendSize, receiveSize, opener, factory, eventListener);
}
@Override
@@ -808,7 +811,9 @@ public class ScpTest extends BaseTestSupport {
return new InternalScpCommand(command,
getExecutorService(), isShutdownOnExit(),
getSendBufferSize(), getReceiveBufferSize(),
- DefaultScpFileOpener.INSTANCE, ScpTransferEventListener.EMPTY);
+ DefaultScpFileOpener.INSTANCE,
+ DefaultScpStreamResolverFactory.INSTANCE,
+ ScpTransferEventListener.EMPTY);
}
});