You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ha...@apache.org on 2012/02/28 04:18:33 UTC
svn commit: r1294451 - in /camel/trunk/components/camel-jsch/src:
main/java/org/apache/camel/component/jsch/
test/java/org/apache/camel/component/jsch/ test/resources/
Author: hadrian
Date: Tue Feb 28 03:18:33 2012
New Revision: 1294451
URL: http://svn.apache.org/viewvc?rev=1294451&view=rev
Log:
CAMEL-5020. Support for recursive copy
Removed:
camel/trunk/components/camel-jsch/src/test/resources/client.jks
camel/trunk/components/camel-jsch/src/test/resources/server.jks
Modified:
camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpOperations.java
camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpServerTestSupport.java
camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpSimpleProduceTest.java
Modified: camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpOperations.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpOperations.java?rev=1294451&r1=1294450&r2=1294451&view=diff
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpOperations.java (original)
+++ camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpOperations.java Tue Feb 28 03:18:33 2012
@@ -16,6 +16,7 @@
*/
package org.apache.camel.component.jsch;
+import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -30,10 +31,12 @@ import com.jcraft.jsch.UIKeyboardInterac
import com.jcraft.jsch.UserInfo;
import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
import org.apache.camel.component.file.GenericFileEndpoint;
import org.apache.camel.component.file.GenericFileOperationFailedException;
import org.apache.camel.component.file.remote.RemoteFileConfiguration;
import org.apache.camel.component.file.remote.RemoteFileOperations;
+import org.apache.camel.util.ExchangeHelper;
import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -92,20 +95,17 @@ public class ScpOperations implements Re
int timeout = cfg.getConnectTimeout();
LOG.trace("Opening channel to {} with {} timeout...", cfg.remoteServerInformation(),
timeout > 0 ? (Integer.toString(timeout) + " ms") : "no");
- String target = getRemoteTarget(cfg);
String file = getRemoteFile(name, cfg);
try {
channel = (ChannelExec) session.openChannel("exec");
- // TODO: need config for scp *-p* (preserves modification times, access times, and modes from the original file)
- // String command="scp " + (ptimestamp ? "-p " : "") + "-t " + configuration.getDirectory();
- // TODO: refactor to use generic command
- String command = "scp -t " + target;
- channel.setCommand(command);
+ channel.setCommand(getScpCommand(cfg, file));
channel.connect(timeout);
LOG.trace("Channel connected to {}", cfg.remoteServerInformation());
try {
- writeFile(channel, file, "foo");
+ write(channel, file, ExchangeHelper.getMandatoryInBody(exchange, InputStream.class));
+ } catch (InvalidPayloadException e) {
+ throw new GenericFileOperationFailedException("Failed extract message body as InputStream", e);
} catch (IOException e) {
throw new GenericFileOperationFailedException("Failed to write file " + file, e);
}
@@ -198,10 +198,7 @@ public class ScpOperations implements Re
ciphers.put("cipher.c2s", config.getCiphers());
JSch.setConfig(ciphers);
}
-
-
-
String knownHostsFile = config.getKnownHostsFile();
jsch.setKnownHosts(ObjectHelper.isEmpty(knownHostsFile) ? DEFAULT_KNOWN_HOSTS : knownHostsFile);
session = jsch.getSession(config.getUsername(), config.getHost(), config.getPort());
@@ -223,24 +220,59 @@ public class ScpOperations implements Re
return session;
}
- private void writeFile(ChannelExec c, String name, String data) throws IOException {
- data = "Hello World";
+ private void write(ChannelExec c, String name, InputStream data) throws IOException {
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
- os.write(("C7777 " + data.length() + " " + name + "\n").getBytes());
- os.flush();
- is.read();
-
- os.write(data.getBytes());
- os.flush();
- is.read();
-
- os.write(0);
- os.flush();
+ writeFile(name, data, os, is);
+
os.close();
is.close();
}
+
+ private void writeFile(String filename, InputStream data, OutputStream os, InputStream is) throws IOException {
+ int pos = filename.indexOf('/');
+ if (pos >= 0) {
+ // write to child directory
+ String dir = filename.substring(0, pos);
+ os.write(("D0775 0 " + dir + "\n").getBytes());
+ os.flush();
+ is.read();
+
+ writeFile(filename.substring(pos + 1), data, os, is);
+
+ os.write(("E\n").getBytes());
+ os.flush();
+ is.read();
+ } else {
+ int count = 0;
+ int read = 0;
+ int size = endpoint.getBufferSize();
+ byte[] bytes = new byte[size];
+
+ // figure out the stream size as we need to pass it in the header
+ BufferedInputStream buffer = new BufferedInputStream(data, size);
+ buffer.mark(Integer.MAX_VALUE);
+ while ((read = buffer.read(bytes)) != -1) {
+ count += read;
+ }
+
+ // send the header
+ os.write(("C0775 " + count + " " + filename + "\n").getBytes());
+ os.flush();
+ is.read();
+
+ // now send the stream
+ buffer.reset();
+ while ((read = buffer.read(bytes)) != -1) {
+ os.write(bytes, 0, read);
+ }
+ os.flush();
+ is.read();
+ }
+ os.write(0);
+ os.flush();
+ }
private static String getRemoteTarget(ScpConfiguration config) {
// use current dir (".") if target directory not specified in uri
@@ -248,12 +280,27 @@ public class ScpOperations implements Re
}
private static String getRemoteFile(String name, ScpConfiguration config) {
- // assume that the directory path of 'name' is the same as config.getDirectory()
- int pos = name.lastIndexOf('/');
- return pos >= 0 ? name.substring(pos + 1) : name;
+ String dir = config.getDirectory();
+ dir = dir.endsWith("/") ? dir : dir + "/";
+ return name.startsWith(dir) ? name.substring(dir.length()) : name;
+ }
+
+ private static boolean isRecursiveScp(String name) {
+ return name.indexOf('/') > 0;
+ }
+
+ private static String getScpCommand(ScpConfiguration config, String name) {
+ StringBuilder cmd = new StringBuilder();
+ cmd.append("scp ");
+ // TODO: need config for scp *-p* (preserves modification times, access times, and modes from the original file)
+ // String command="scp " + (ptimestamp ? "-p " : "") + "-t " + configuration.getDirectory();
+ // TODO: refactor to use generic command
+ cmd.append(isRecursiveScp(name) ? "-r " : "");
+ cmd.append("-t ");
+ cmd.append(getRemoteTarget(config));
+ return cmd.toString();
}
-
protected static final class SessionUserInfo implements UserInfo, UIKeyboardInteractive {
private final ScpConfiguration config;
public SessionUserInfo(ScpConfiguration config) {
Modified: camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpServerTestSupport.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpServerTestSupport.java?rev=1294451&r1=1294450&r2=1294451&view=diff
==============================================================================
--- camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpServerTestSupport.java (original)
+++ camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpServerTestSupport.java Tue Feb 28 03:18:33 2012
@@ -80,8 +80,8 @@ public abstract class ScpServerTestSuppo
@Override
@Before
public void setUp() throws Exception {
- File root = new File(SCP_ROOT_DIR);
- root.mkdirs();
+ File root = new File(getScpPath());
+ root.mkdirs(); // implicitly create sshd home dir
setupComplete = startSshd();
setupKnownHosts();
@@ -105,6 +105,17 @@ public abstract class ScpServerTestSuppo
FileUtil.deleteFile(new File(knownHostsFile));
}
+ protected final String getScpPath() {
+ // use this convention and use separate directories for tests
+ // (easier to debug and avoid interference)
+ return SCP_ROOT_DIR + "/" + getClass().getSimpleName();
+ }
+
+ protected String getScpUri() {
+ return "scp://localhost:" + getPort() + "/" + getScpPath();
+ }
+
+
protected boolean startSshd() {
sshd = SshServer.setUpDefaultServer();
sshd.setPort(getPort());
@@ -139,8 +150,8 @@ public abstract class ScpServerTestSuppo
// we use a known key, but since the port it dynamic, the
// known_hosts file will be generated by the following code and
// should should contain a line like below (if
- // "HashKnownHosts"=="yes" the hostname:port part will look
- // a bit more complicated).
+ // "HashKnownHosts"=="yes" the hostname:port part will be
+ // hashed and look a bit more complicated).
//
// [localhost]:21000 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDd \
// fIWeSV4o68dRrKSzFd/Bk51E65UTmmSrmW0O1ohtzi6HzsDPjXgCtlTt3F \
Modified: camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpSimpleProduceTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpSimpleProduceTest.java?rev=1294451&r1=1294450&r2=1294451&view=diff
==============================================================================
--- camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpSimpleProduceTest.java (original)
+++ camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpSimpleProduceTest.java Tue Feb 28 03:18:33 2012
@@ -27,7 +27,6 @@ import org.junit.Test;
* @version
*/
public class ScpSimpleProduceTest extends ScpServerTestSupport {
-
@Override
public boolean isUseRouteBuilder() {
return false;
@@ -37,36 +36,34 @@ public class ScpSimpleProduceTest extend
public void testScpSimpleProduce() throws Exception {
Assume.assumeTrue(this.isSetupComplete());
- String uri = "scp://localhost:" + getPort() + "/target/scp?username=admin&password=admin&knownHostsFile=" + getKnownHostsFile();
+ String uri = getScpUri() + "?username=admin&password=admin&knownHostsFile=" + getKnownHostsFile();
template.sendBodyAndHeader(uri, "Hello World", Exchange.FILE_NAME, "hello.txt");
- File file = new File(SCP_ROOT_DIR + "/hello.txt").getAbsoluteFile();
+ File file = new File(getScpPath() + "/hello.txt").getAbsoluteFile();
assertTrue("File should exist: " + file, file.exists());
assertEquals("Hello World", context.getTypeConverter().convertTo(String.class, file));
}
@Test
- @Ignore("Scenario not supported by scp but could be emulated with recursive copy")
public void testScpSimpleSubPathProduce() throws Exception {
Assume.assumeTrue(this.isSetupComplete());
- String uri = "scp://localhost:" + getPort() + "/target/scp?username=admin&password=admin&knownHostsFile=" + getKnownHostsFile();
- template.sendBodyAndHeader(uri, "Bye World", Exchange.FILE_NAME, "bye.txt");
+ String uri = getScpUri() + "?username=admin&password=admin&knownHostsFile=" + getKnownHostsFile();
+ template.sendBodyAndHeader(uri, "Bye World", Exchange.FILE_NAME, "mysub/bye.txt");
- File file = new File(SCP_ROOT_DIR + "/mysub/bye.txt").getAbsoluteFile();
+ File file = new File(getScpPath() + "/mysub/bye.txt").getAbsoluteFile();
assertTrue("File should exist: " + file, file.exists());
assertEquals("Bye World", context.getTypeConverter().convertTo(String.class, file));
}
@Test
- @Ignore("Scenario not supported by scp but could be emulated with recursive copy")
public void testScpSimpleTwoSubPathProduce() throws Exception {
Assume.assumeTrue(this.isSetupComplete());
- String uri = "scp://localhost:" + getPort() + "/target/scp?username=admin&password=admin&knownHostsFile=" + getKnownHostsFile();
- template.sendBodyAndHeader(uri, "Farewell World", Exchange.FILE_NAME, "farewell.txt");
+ String uri = getScpUri() + "?username=admin&password=admin&knownHostsFile=" + getKnownHostsFile();
+ template.sendBodyAndHeader(uri, "Farewell World", Exchange.FILE_NAME, "mysub/mysubsub/farewell.txt");
- File file = new File(SCP_ROOT_DIR + "/mysub/myother/farewell.txt").getAbsoluteFile();
+ File file = new File(getScpPath() + "/mysub/mysubsub/farewell.txt").getAbsoluteFile();
assertTrue("File should exist: " + file, file.exists());
assertEquals("Farewell World", context.getTypeConverter().convertTo(String.class, file));
}