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/23 21:48:48 UTC

svn commit: r1292947 - in /camel/trunk/components: ./ camel-jsch/ camel-jsch/src/ camel-jsch/src/main/ camel-jsch/src/main/java/ camel-jsch/src/main/java/org/ camel-jsch/src/main/java/org/apache/ camel-jsch/src/main/java/org/apache/camel/ camel-jsch/sr...

Author: hadrian
Date: Thu Feb 23 20:48:47 2012
New Revision: 1292947

URL: http://svn.apache.org/viewvc?rev=1292947&view=rev
Log:
CAMEL-5020. Add support for the scp protocol

Added:
    camel/trunk/components/camel-jsch/
    camel/trunk/components/camel-jsch/pom.xml
    camel/trunk/components/camel-jsch/src/
    camel/trunk/components/camel-jsch/src/main/
    camel/trunk/components/camel-jsch/src/main/java/
    camel/trunk/components/camel-jsch/src/main/java/org/
    camel/trunk/components/camel-jsch/src/main/java/org/apache/
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/JschComponent.java
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpConfiguration.java
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpEndpoint.java
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpFile.java
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpOperations.java
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProcessStrategyFactory.java
    camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProducer.java
    camel/trunk/components/camel-jsch/src/main/resources/
    camel/trunk/components/camel-jsch/src/main/resources/META-INF/
    camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/
    camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/org/
    camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/org/apache/
    camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/org/apache/camel/
    camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/org/apache/camel/component/
    camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/org/apache/camel/component/scp
    camel/trunk/components/camel-jsch/src/main/resources/log4j.properties
    camel/trunk/components/camel-jsch/src/test/
    camel/trunk/components/camel-jsch/src/test/java/
    camel/trunk/components/camel-jsch/src/test/java/org/
    camel/trunk/components/camel-jsch/src/test/java/org/apache/
    camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/
    camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/
    camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/
    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
    camel/trunk/components/camel-jsch/src/test/resources/
    camel/trunk/components/camel-jsch/src/test/resources/client.jks
    camel/trunk/components/camel-jsch/src/test/resources/hostkey.pem
    camel/trunk/components/camel-jsch/src/test/resources/log4j.properties
    camel/trunk/components/camel-jsch/src/test/resources/server.jks
Modified:
    camel/trunk/components/pom.xml

Added: camel/trunk/components/camel-jsch/pom.xml
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/pom.xml?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/pom.xml (added)
+++ camel/trunk/components/camel-jsch/pom.xml Thu Feb 23 20:48:47 2012
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-parent</artifactId>
+    <version>2.10-SNAPSHOT</version>
+    <relativePath>../../parent</relativePath>
+  </parent>
+
+  <artifactId>camel-jsch</artifactId>
+  <packaging>bundle</packaging>
+  <name>Camel :: Jsch</name>
+  <description>Camel SCP Support</description>
+
+  <properties>
+    <camel.osgi.import.before.defaults>
+        com.jcraft.jsch.*;version="[0.1.40,0.1.50)",
+        org.apache.camel.component.file.strategy;${camel.osgi.import.strict.version}
+    </camel.osgi.import.before.defaults>
+    <camel.osgi.export.pkg>org.apache.camel.component.jsch.*</camel.osgi.export.pkg>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core</artifactId>
+    </dependency>  
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-ftp</artifactId>
+    </dependency>  
+    <dependency>
+      <groupId>com.jcraft</groupId>
+      <artifactId>jsch</artifactId>
+      <version>${jsch-version}</version>
+    </dependency>
+
+    <!-- logging -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>      
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId> 
+      <artifactId>log4j</artifactId> 
+      <scope>test</scope> 
+    </dependency>
+
+    <!-- for testing -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sshd</groupId>
+      <artifactId>sshd-core</artifactId>
+      <version>${sshd-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <!-- needed by sshd server -->
+    <dependency>
+      <groupId>org.apache.mina</groupId>
+      <artifactId>mina-core</artifactId>
+      <version>${mina2-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcprov-jdk16</artifactId>
+      <version>${bouncycastle-version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <defaultGoal>install</defaultGoal>
+  </build>
+</project>

Added: camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/JschComponent.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/JschComponent.java?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/JschComponent.java (added)
+++ camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/JschComponent.java Thu Feb 23 20:48:47 2012
@@ -0,0 +1,84 @@
+/**
+ * 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.camel.component.jsch;
+
+import com.jcraft.jsch.JSch;
+
+import java.net.URI;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.file.GenericFileEndpoint;
+import org.apache.camel.component.file.remote.RemoteFileComponent;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *  Component providing secure messaging using JSch
+ */
+public class JschComponent extends RemoteFileComponent<ScpFile> {
+    private static final transient Logger LOG = LoggerFactory.getLogger(JschComponent.class);
+    static {
+        JSch.setConfig("StrictHostKeyChecking",  "yes");
+        JSch.setLogger(new com.jcraft.jsch.Logger() {
+            @Override
+            public boolean isEnabled(int level) {
+                return level == FATAL || level == ERROR ? LOG.isErrorEnabled()
+                    : level == WARN ? LOG.isWarnEnabled()
+                    : level == INFO ? LOG.isInfoEnabled() : LOG.isDebugEnabled();
+            }
+            @Override
+            public void log(int level, String message) {
+                if (level == FATAL || level == ERROR) {
+                    LOG.error("[JSCH] {}", message);
+                } else if (level == WARN) {
+                    LOG.warn("[JSCH] {}", message);
+                } else if (level == INFO) {
+                    LOG.info("[JSCH] {}", message);
+                } else {
+                    LOG.debug("[JSCH] {}", message);
+                }
+            }
+        });
+    }
+
+    public JschComponent() {
+    }
+
+    public JschComponent(CamelContext context) {
+        super(context);
+    }
+
+    @Override
+    protected GenericFileEndpoint<ScpFile> buildFileEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+        // TODO: revisit stripping the query part; should not be needed with valid uris
+        int query = uri.indexOf("?");
+        return new ScpEndpoint(uri, this, new ScpConfiguration(new URI(query >= 0 ? uri.substring(0, query) : uri)));
+    }
+
+    protected void afterPropertiesSet(GenericFileEndpoint<ScpFile> endpoint) throws Exception {
+        // noop
+    }
+
+    @Override
+    public void doStop() throws Exception {
+        // TODO: close all sessions
+        super.doStop();
+    }
+}
+

Added: camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpConfiguration.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpConfiguration.java?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpConfiguration.java (added)
+++ camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpConfiguration.java Thu Feb 23 20:48:47 2012
@@ -0,0 +1,125 @@
+/**
+ * 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.camel.component.jsch;
+
+import java.net.URI;
+
+import org.apache.camel.component.file.remote.RemoteFileConfiguration;
+
+/**
+ * Secure FTP configuration
+ */
+public class ScpConfiguration extends RemoteFileConfiguration {
+
+    public static final int DEFAULT_SFTP_PORT = 22;
+    private String knownHostsFile;
+    private String privateKeyFile;
+    private String privateKeyFilePassphrase;
+    private String strictHostKeyChecking = "no";
+    private int serverAliveInterval;
+    private int serverAliveCountMax = 1;
+    private String chmod;
+    // comma separated list of ciphers. 
+    // null means default jsch list will be used
+    private String ciphers;
+    private int compression;
+
+    public ScpConfiguration() {
+        setProtocol("sftp");
+    }
+
+    public ScpConfiguration(URI uri) {
+        super(uri);
+    }
+
+    @Override
+    protected void setDefaultPort() {
+        setPort(DEFAULT_SFTP_PORT);
+    }
+
+    public String getKnownHostsFile() {
+        return knownHostsFile;
+    }
+
+    public void setKnownHostsFile(String knownHostsFile) {
+        this.knownHostsFile = knownHostsFile;
+    }
+
+    public String getPrivateKeyFile() {
+        return privateKeyFile;
+    }
+
+    public void setPrivateKeyFile(String privateKeyFile) {
+        this.privateKeyFile = privateKeyFile;
+    }
+
+    public String getPrivateKeyFilePassphrase() {
+        return privateKeyFilePassphrase;
+    }
+
+    public void setPrivateKeyFilePassphrase(String privateKeyFilePassphrase) {
+        this.privateKeyFilePassphrase = privateKeyFilePassphrase;
+    }
+
+    public String getStrictHostKeyChecking() {
+        return strictHostKeyChecking;
+    }
+
+    public void setStrictHostKeyChecking(String strictHostKeyChecking) {
+        this.strictHostKeyChecking = strictHostKeyChecking;
+    }
+
+    public void setServerAliveInterval(int serverAliveInterval) {
+        this.serverAliveInterval = serverAliveInterval;
+    }
+
+    public int getServerAliveInterval() {
+        return serverAliveInterval;
+    }
+
+    public void setServerAliveCountMax(int serverAliveCountMax) {
+        this.serverAliveCountMax = serverAliveCountMax;
+    }
+
+    public int getServerAliveCountMax() {
+        return serverAliveCountMax;
+    }
+
+    public void setChmod(String chmod) {
+        this.chmod = chmod;
+    }
+
+    public String getChmod() {
+        return chmod;
+    }
+
+    public void setCiphers(String ciphers) {
+        this.ciphers = ciphers;
+    }
+
+    public String getCiphers() {
+        return ciphers;
+    }
+
+    public int getCompression() {
+        return compression;
+    }
+
+    public void setCompression(int compression) {
+        this.compression = compression;
+    }
+}

Added: camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpEndpoint.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpEndpoint.java?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpEndpoint.java (added)
+++ camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpEndpoint.java Thu Feb 23 20:48:47 2012
@@ -0,0 +1,69 @@
+/**
+ * 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.camel.component.jsch;
+
+import org.apache.camel.Expression;
+import org.apache.camel.Processor;
+import org.apache.camel.component.file.GenericFileProducer;
+import org.apache.camel.component.file.remote.RemoteFileConfiguration;
+import org.apache.camel.component.file.remote.RemoteFileConsumer;
+import org.apache.camel.component.file.remote.RemoteFileEndpoint;
+import org.apache.camel.component.file.remote.RemoteFileOperations;
+
+/**
+ * Secure Copy Endpoint
+ */
+public class ScpEndpoint extends RemoteFileEndpoint<ScpFile> {
+
+    public ScpEndpoint() {
+    }
+
+    public ScpEndpoint(String uri, JschComponent component, RemoteFileConfiguration configuration) {
+        super(uri, component, configuration);
+    }
+
+    @Override
+    public ScpConfiguration getConfiguration() {
+        return (ScpConfiguration) this.configuration;
+    }
+
+    @Override
+    protected RemoteFileConsumer<ScpFile> buildConsumer(Processor processor) {
+        return null; // new ScpConsumer(this, processor, createRemoteFileOperations());
+    }
+
+    protected GenericFileProducer<ScpFile> buildProducer() {
+        return new ScpProducer(this, createRemoteFileOperations());
+    }
+
+    public RemoteFileOperations<ScpFile> createRemoteFileOperations() {
+        ScpOperations operations = new ScpOperations();
+        operations.setEndpoint(this);
+        return operations;
+    }
+
+    @Override
+    public String getScheme() {
+        return "scp";
+    }
+    
+    @Override
+    public Expression getTempFileName() {
+        log.debug("Creation of temporary files not supported by the scp: protocol.");
+        return null;
+    }
+}

Added: camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpFile.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpFile.java?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpFile.java (added)
+++ camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpFile.java Thu Feb 23 20:48:47 2012
@@ -0,0 +1,71 @@
+/**
+ * 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.camel.component.jsch;
+
+
+/**
+ * SFTP remote file operations
+ */
+public class ScpFile {
+    private boolean directory;
+    private int attrs;
+    private int length;
+    private String name;
+    private String parent;
+
+    public String header() {
+        StringBuffer buffer = new StringBuffer();
+        buffer.append(directory ? "D" : "C");
+        buffer.append(" ");
+        return buffer.toString();
+    }
+
+    public boolean isDirectory() {
+        return directory;
+    }
+    public void setDirectory(boolean directory) {
+        this.directory = directory;
+    }
+    public int getAttrs() {
+        return attrs;
+    }
+    public void setAttrs(int attrs) {
+        this.attrs = attrs;
+    }
+    public int getLength() {
+        return length;
+    }
+    public void setLength(int length) {
+        this.length = length;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getParent() {
+        return parent;
+    }
+
+    public void setParent(String parent) {
+        this.parent = parent;
+    }
+}

Added: 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=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpOperations.java (added)
+++ camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpOperations.java Thu Feb 23 20:48:47 2012
@@ -0,0 +1,302 @@
+/**
+ * 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.camel.component.jsch;
+
+import static org.apache.camel.util.ObjectHelper.isNotEmpty;
+import com.jcraft.jsch.ChannelExec;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.UIKeyboardInteractive;
+import com.jcraft.jsch.UserInfo;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.apache.camel.Exchange;
+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.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SCP remote file operations
+ */
+public class ScpOperations implements RemoteFileOperations<ScpFile> {
+    private static final String DEFAULT_KNOWN_HOSTS = "META-INF/.ssh/known_hosts";
+    private static final transient Logger LOG = LoggerFactory.getLogger(ScpOperations.class);
+
+    private ScpEndpoint endpoint;
+    private Session session;
+    private ChannelExec channel;
+
+    @Override
+    public void setEndpoint(GenericFileEndpoint<ScpFile> endpoint) {
+        this.endpoint = (ScpEndpoint)endpoint;
+    }
+
+    @Override
+    public boolean deleteFile(String name) throws GenericFileOperationFailedException {
+        throw new GenericFileOperationFailedException("Operation 'delete' not supported by the scp: protocol");
+    }
+
+    @Override
+    public boolean existsFile(String name) throws GenericFileOperationFailedException {
+        // maybe... cannot determine using the scp: protocol
+        return false;
+    }
+
+    @Override
+    public boolean renameFile(String from, String to) throws GenericFileOperationFailedException {
+        throw new GenericFileOperationFailedException("Operation 'rename' not supported by the scp: protocol");
+    }
+
+    @Override
+    public boolean buildDirectory(String directory, boolean absolute) throws GenericFileOperationFailedException {
+        // done by the server
+        return true;
+    }
+
+    @Override
+    public boolean retrieveFile(String name, Exchange exchange) throws GenericFileOperationFailedException {
+        // TODO: implement
+        return false;
+    }
+
+    @Override
+    public boolean storeFile(String name, Exchange exchange) throws GenericFileOperationFailedException {
+        ObjectHelper.notNull(session, "session");
+        ScpConfiguration cfg = endpoint.getConfiguration();
+        
+        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.connect(timeout);
+            LOG.trace("Channel connected to {}", cfg.remoteServerInformation());
+
+            try {
+                writeFile(channel, file, "foo");
+            } catch (IOException e) {
+                throw new GenericFileOperationFailedException("Failed to write file " + file, e);
+            }
+        } catch (JSchException e) {
+            LOG.warn("Failed to secure copy file " + file, e);
+            return false;
+        } finally {
+            if (channel != null) {
+                LOG.trace("Disconnecting 'exec' scp channel");
+                channel.disconnect();
+                channel = null;
+                LOG.trace("Channel disconnected from {}", cfg.remoteServerInformation());
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public String getCurrentDirectory() throws GenericFileOperationFailedException {
+        return endpoint.getConfiguration().getDirectory();
+    }
+
+    @Override
+    public void changeCurrentDirectory(String path) throws GenericFileOperationFailedException {
+        throw new GenericFileOperationFailedException("Operation 'cd " + path + "' not supported by the scp: protocol");
+    }
+
+    @Override
+    public void changeToParentDirectory() throws GenericFileOperationFailedException {
+        throw new GenericFileOperationFailedException("Operation 'cd ..' not supported by the scp: protocol");
+    }
+
+    @Override
+    public List<ScpFile> listFiles() throws GenericFileOperationFailedException {
+        throw new GenericFileOperationFailedException("Operation 'ls' not supported by the scp: protocol");
+    }
+
+    @Override
+    public List<ScpFile> listFiles(String path) throws GenericFileOperationFailedException {
+        throw new GenericFileOperationFailedException("Operation 'ls " + path + "' not supported by the scp: protocol");
+    }
+
+    @Override
+    public boolean connect(RemoteFileConfiguration configuration) throws GenericFileOperationFailedException {
+        if (!isConnected()) {
+            session = createSession(configuration instanceof ScpConfiguration ? (ScpConfiguration)configuration : null);
+            // TODO: deal with reconnection attempts
+            if (!isConnected()) {
+                session = null;
+                throw new GenericFileOperationFailedException("Failed to connect to " + configuration.remoteServerInformation());
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean isConnected() throws GenericFileOperationFailedException {
+        return session != null && session.isConnected();
+    }
+
+    @Override
+    public void disconnect() throws GenericFileOperationFailedException {
+        if (isConnected()) {
+            session.disconnect();
+        }
+        session = null;
+    }
+
+    @Override
+    public boolean sendNoop() throws GenericFileOperationFailedException {
+        // not supported by scp:
+        return true;
+    }
+
+    @Override
+    public boolean sendSiteCommand(String command) throws GenericFileOperationFailedException {
+        // TODO: not really used, maybe implement at a later time
+        return true;
+    }
+    
+    private Session createSession(ScpConfiguration config) {
+        ObjectHelper.notNull(config, "ScpConfiguration");
+        try {
+            final JSch jsch = new JSch();
+            // get from configuration
+            if (isNotEmpty(config.getCiphers())) {
+                LOG.debug("Using ciphers: {}", config.getCiphers());
+                Hashtable<String, String> ciphers = new Hashtable<String, String>();
+                ciphers.put("cipher.s2c", config.getCiphers());
+                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());
+            session.setTimeout(config.getTimeout());
+            session.setUserInfo(new SessionUserInfo(config));
+
+            int timeout = config.getConnectTimeout();
+            LOG.debug("Connecting to {} with {} timeout...", config.remoteServerInformation(),
+                timeout > 0 ? (Integer.toString(timeout) + " ms") : "no");
+            if (timeout > 0) {
+                session.connect(timeout);
+            } else {
+                session.connect();
+            }
+        } catch (JSchException e) {
+            session = null;
+            LOG.warn("Could not create ssh session for " + config.remoteServerInformation(), e);
+        }
+        return session;
+    }
+    
+    private void writeFile(ChannelExec c, String name, String data) throws IOException {
+        data = "Hello World";
+        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();
+        os.close();
+        is.close();
+    }
+    
+    private static String getRemoteTarget(ScpConfiguration config) {
+        // use current dir (".") if target directory not specified in uri
+        return config.getDirectory().isEmpty() ? "." : config.getDirectory();
+    }
+
+    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;
+    }
+
+
+    protected static final class SessionUserInfo implements UserInfo, UIKeyboardInteractive {
+        private final ScpConfiguration config;
+        public SessionUserInfo(ScpConfiguration config) {
+            ObjectHelper.notNull(config, "config");
+            this.config = config;
+        }
+        
+        @Override
+        public String getPassphrase() {
+            LOG.info("Private Key authentication not supported");
+            return null;
+        }
+        @Override
+        public String getPassword() {
+            LOG.debug("Providing password for ssh authentication of user '{}'", config.getUsername());
+            return config.getPassword();
+        }
+        @Override
+        public boolean promptPassword(String message) {
+            LOG.debug(message);
+            return true;
+        }
+        @Override
+        public boolean promptPassphrase(String message) {
+            LOG.debug(message);
+            return true;
+        }
+        @Override
+        public boolean promptYesNo(String message) {
+            LOG.debug(message);
+            return false;
+        }
+        @Override
+        public void showMessage(String message) {
+            LOG.debug(message);
+        }
+
+        @Override
+        public String[] promptKeyboardInteractive(String destination, String name, 
+            String instruction, String[] prompt, boolean[] echo) {
+            LOG.debug(instruction);
+            // Called for either SSH_MSG_USERAUTH_INFO_REQUEST or SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
+            // The most secure choice (especially for the second case) is to return null
+            return null;
+        }
+    }
+}

Added: camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProcessStrategyFactory.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProcessStrategyFactory.java?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProcessStrategyFactory.java (added)
+++ camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProcessStrategyFactory.java Thu Feb 23 20:48:47 2012
@@ -0,0 +1,85 @@
+/**
+ * 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.camel.component.jsch;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.file.GenericFileExclusiveReadLockStrategy;
+import org.apache.camel.component.file.GenericFileProcessStrategy;
+import org.apache.camel.component.file.strategy.GenericFileNoOpProcessStrategy;
+
+public final class ScpProcessStrategyFactory {
+
+    private ScpProcessStrategyFactory() {
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <LsEntry> GenericFileProcessStrategy<LsEntry> createGenericFileProcessStrategy(CamelContext context, Map<String, Object> params) {
+
+        /*
+        // We assume a value is present only if its value not null for String and 'true' for boolean
+        Expression moveExpression = (Expression) params.get("move");
+        Expression moveFailedExpression = (Expression) params.get("moveFailed");
+        Expression preMoveExpression = (Expression) params.get("preMove");
+        boolean isNoop = params.get("noop") != null;
+        boolean isDelete = params.get("delete") != null;
+        boolean isMove = moveExpression != null || preMoveExpression != null || moveFailedExpression != null;
+        */
+
+        // default strategy will do nothing
+        GenericFileNoOpProcessStrategy<LsEntry> strategy = new GenericFileNoOpProcessStrategy<LsEntry>();
+        strategy.setExclusiveReadLockStrategy((GenericFileExclusiveReadLockStrategy<LsEntry>) getExclusiveReadLockStrategy(params));
+        return strategy;
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private static <LsEntry> GenericFileExclusiveReadLockStrategy<LsEntry> getExclusiveReadLockStrategy(Map<String, Object> params) {
+        GenericFileExclusiveReadLockStrategy<LsEntry> strategy = (GenericFileExclusiveReadLockStrategy<LsEntry>) params.get("exclusiveReadLockStrategy");
+        if (strategy != null) {
+            return strategy;
+        }
+/*
+        // no explicit strategy set then fallback to readLock option
+        String readLock = (String) params.get("readLock");
+        if (ObjectHelper.isNotEmpty(readLock)) {
+            if ("none".equals(readLock) || "false".equals(readLock)) {
+                return null;
+            } else if ("rename".equals(readLock)) {
+                GenericFileRenameExclusiveReadLockStrategy<LsEntry> readLockStrategy = new GenericFileRenameExclusiveReadLockStrategy<LsEntry>();
+                Long timeout = (Long) params.get("readLockTimeout");
+                if (timeout != null) {
+                    readLockStrategy.setTimeout(timeout);
+                }
+                return readLockStrategy;
+            } else if ("changed".equals(readLock)) {
+                GenericFileExclusiveReadLockStrategy readLockStrategy = new SftpChangedExclusiveReadLockStrategy();
+                Long timeout = (Long) params.get("readLockTimeout");
+                if (timeout != null) {
+                    readLockStrategy.setTimeout(timeout);
+                }
+                Long checkInterval = (Long) params.get("readLockCheckInterval");
+                if (checkInterval != null) {
+                    readLockStrategy.setCheckInterval(checkInterval);
+                }
+                return readLockStrategy;
+            }
+        }
+*/
+        return null;
+    }
+}

Added: camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProducer.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProducer.java?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProducer.java (added)
+++ camel/trunk/components/camel-jsch/src/main/java/org/apache/camel/component/jsch/ScpProducer.java Thu Feb 23 20:48:47 2012
@@ -0,0 +1,28 @@
+/**
+ * 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.camel.component.jsch;
+
+import org.apache.camel.component.file.remote.RemoteFileEndpoint;
+import org.apache.camel.component.file.remote.RemoteFileOperations;
+import org.apache.camel.component.file.remote.RemoteFileProducer;
+
+public class ScpProducer extends RemoteFileProducer<ScpFile> {
+
+    protected ScpProducer(RemoteFileEndpoint<ScpFile> endpoint, RemoteFileOperations<ScpFile> operations) {
+        super(endpoint, operations);
+    }
+}

Added: camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/org/apache/camel/component/scp
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/org/apache/camel/component/scp?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/org/apache/camel/component/scp (added)
+++ camel/trunk/components/camel-jsch/src/main/resources/META-INF/services/org/apache/camel/component/scp Thu Feb 23 20:48:47 2012
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+class=org.apache.camel.component.jsch.JschComponent
+strategy.factory.class=org.apache.camel.component.jsch.ScpProcessStrategyFactory

Added: camel/trunk/components/camel-jsch/src/main/resources/log4j.properties
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/main/resources/log4j.properties?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/main/resources/log4j.properties (added)
+++ camel/trunk/components/camel-jsch/src/main/resources/log4j.properties Thu Feb 23 20:48:47 2012
@@ -0,0 +1,16 @@
+
+#
+# The logging properties used
+#
+log4j.rootLogger=INFO, out
+
+# uncomment the following line to turn on Camel debugging
+#log4j.logger.org.apache.camel=DEBUG
+
+# CONSOLE appender not used by default
+log4j.appender.out=org.apache.log4j.ConsoleAppender
+log4j.appender.out.layout=org.apache.log4j.PatternLayout
+log4j.appender.out.layout.ConversionPattern=[%30.30t] %-30.30c{1} %-5p %m%n
+#log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
+
+log4j.throwableRenderer=org.apache.log4j.EnhancedThrowableRenderer
\ No newline at end of file

Added: 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=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpServerTestSupport.java (added)
+++ camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpServerTestSupport.java Thu Feb 23 20:48:47 2012
@@ -0,0 +1,206 @@
+/**
+ * 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.camel.component.jsch;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.UserInfo;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.Provider;
+import java.security.Provider.Service;
+import java.security.Security;
+
+import org.apache.camel.test.AvailablePortFinder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.FileUtil;
+import org.apache.sshd.SshServer;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
+import org.apache.sshd.server.PasswordAuthenticator;
+import org.apache.sshd.server.command.ScpCommandFactory;
+import org.apache.sshd.server.session.ServerSession;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version 
+ */
+public abstract class ScpServerTestSupport extends CamelTestSupport {
+    protected static final Logger LOG = LoggerFactory.getLogger(ScpServerTestSupport.class);
+    protected static final String SCP_ROOT_DIR = "target/scp";
+    protected static final String KNOWN_HOSTS = "known_hosts";
+    protected static int port;
+
+    private boolean acceptLocalhostConnections = true;
+    private String knownHostsFile;
+
+    private boolean setupComplete;
+    private SshServer sshd;
+
+    protected ScpServerTestSupport() {
+        this(true);
+    }
+
+    protected ScpServerTestSupport(boolean acceptLocalhostConnections) {
+        this.acceptLocalhostConnections = acceptLocalhostConnections;
+    }
+
+    protected int getPort() {
+        return port;
+    }
+
+    protected SshServer getSshd() {
+        return sshd;
+    }
+
+    @BeforeClass
+    public static void initPort() throws Exception {
+        port = AvailablePortFinder.getNextAvailable(21000);
+    }
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        File root = new File(SCP_ROOT_DIR);
+        root.mkdirs();
+
+        setupComplete = startSshd();
+        setupKnownHosts();
+        super.setUp();
+    }
+
+    @Override
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+        if (sshd != null) {
+            try {
+                sshd.stop();
+                sshd = null;
+            } catch (Exception e) {
+                // ignore while shutting down as we could be polling during shutdown
+                // and get errors when the ssh server is stopping.
+            }
+        }
+        FileUtil.deleteFile(new File(knownHostsFile));
+    }
+
+    protected boolean startSshd() {
+        sshd = SshServer.setUpDefaultServer();
+        sshd.setPort(getPort());
+        sshd.setKeyPairProvider(new FileKeyPairProvider(new String[]{"src/test/resources/hostkey.pem"}));
+        sshd.setCommandFactory(new ScpCommandFactory());
+        sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
+            @Override
+            public boolean authenticate(String username, String password, ServerSession session) {
+                // dummy authentication: allow any user whose password is the same as the username
+                return username != null && username.equals(password);
+            }
+        });
+        
+        try {
+            sshd.start();
+            return true;
+        } catch (IOException e) {
+            LOG.info("Failed to start ssh server.", e);
+        }
+        return false;
+    }
+    
+    protected void setupKnownHosts() {
+        knownHostsFile = SCP_ROOT_DIR + "/" + KNOWN_HOSTS + "-" + getPort();
+        FileUtil.deleteFile(new File(knownHostsFile));
+        if (!acceptLocalhostConnections) {
+            return;
+        }
+
+        // For security reasons (avoiding man in the middle attacks),
+        // camel-jsch will only connect to known hosts. For unit testing
+        // 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).
+        //
+        // [localhost]:21000 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDd \
+        // fIWeSV4o68dRrKSzFd/Bk51E65UTmmSrmW0O1ohtzi6HzsDPjXgCtlTt3F \
+        // qTcfFfI92IlTr4JWqC9UK1QT1ZTeng0MkPQmv68hDANHbt5CpETZHjW5q4 \
+        // OOgWhVvj5IyOC2NZHtKlJBkdsMAa15ouOOJLzBvAvbqOR/yUROsEiQ==
+
+        JSch jsch = new JSch();
+        try {
+            LOG.debug("Using '{}' for known hosts.", knownHostsFile);
+            jsch.setKnownHosts(knownHostsFile);
+            Session s = jsch.getSession("admin", "localhost", getPort());
+            s.setConfig("StrictHostKeyChecking",  "ask");
+            s.setConfig("HashKnownHosts",  "yes");
+            s.setUserInfo(new UserInfo() {
+                @Override
+                public String getPassphrase() {
+                    return null;
+                }
+                @Override
+                public String getPassword() {
+                    return "admin";
+                }
+                @Override
+                public boolean promptPassword(String message) {
+                    return true;
+                }
+                @Override
+                public boolean promptPassphrase(String message) {
+                    return false;
+                }
+                @Override
+                public boolean promptYesNo(String message) {
+                    // accept host authenticity
+                    return true;
+                }
+                @Override
+                public void showMessage(String message) {
+                }
+            });
+            // in the process of connecting, "[localhost]:<port>" is added to the knownHostsFile
+            s.connect();
+            s.disconnect();
+        } catch (JSchException e) {
+            LOG.info("Could not add [localhost] to known hosts", e);
+        }
+    }
+
+    public String getKnownHostsFile() {
+        return knownHostsFile;
+    }
+
+    public boolean isSetupComplete() {
+        return setupComplete;
+    }
+
+    protected static void traceSecurityProviders() {
+        for (Provider p : Security.getProviders()) {
+            for (Service s : p.getServices()) {
+                LOG.trace("Security provider {} for '{}' algorithm", s.getClassName(), s.getAlgorithm());
+            }
+        }
+    }
+}

Added: 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=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpSimpleProduceTest.java (added)
+++ camel/trunk/components/camel-jsch/src/test/java/org/apache/camel/component/jsch/ScpSimpleProduceTest.java Thu Feb 23 20:48:47 2012
@@ -0,0 +1,73 @@
+/**
+ * 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.camel.component.jsch;
+
+import java.io.File;
+
+import org.apache.camel.Exchange;
+import org.junit.Assume;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * @version 
+ */
+public class ScpSimpleProduceTest extends ScpServerTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testScpSimpleProduce() throws Exception {
+        Assume.assumeTrue(this.isSetupComplete());
+
+        String uri = "scp://localhost:" + getPort() + "/target/scp?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();
+        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");
+
+        File file = new File(SCP_ROOT_DIR + "/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");
+
+        File file = new File(SCP_ROOT_DIR + "/mysub/myother/farewell.txt").getAbsoluteFile();
+        assertTrue("File should exist: " + file, file.exists());
+        assertEquals("Farewell World", context.getTypeConverter().convertTo(String.class, file));
+    }
+}

Added: camel/trunk/components/camel-jsch/src/test/resources/client.jks
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/test/resources/client.jks?rev=1292947&view=auto
==============================================================================
Files camel/trunk/components/camel-jsch/src/test/resources/client.jks (added) and camel/trunk/components/camel-jsch/src/test/resources/client.jks Thu Feb 23 20:48:47 2012 differ

Added: camel/trunk/components/camel-jsch/src/test/resources/hostkey.pem
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/test/resources/hostkey.pem?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/test/resources/hostkey.pem (added)
+++ camel/trunk/components/camel-jsch/src/test/resources/hostkey.pem Thu Feb 23 20:48:47 2012
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDdfIWeSV4o68dRrKSzFd/Bk51E65UTmmSrmW0O1ohtzi6HzsDP
+jXgCtlTt3FqTcfFfI92IlTr4JWqC9UK1QT1ZTeng0MkPQmv68hDANHbt5CpETZHj
+W5q4OOgWhVvj5IyOC2NZHtKlJBkdsMAa15ouOOJLzBvAvbqOR/yUROsEiQIDAQAB
+AoGBANG3JDW6NoP8rF/zXoeLgLCj+tfVUPSczhGFVrQkAk4mWfyRkhN0WlwHFOec
+K89MpkV1ij/XPVzU4MNbQ2yod1KiDylzvweYv+EaEhASCmYNs6LS03punml42SL9
+97tOmWfVJXxlQoLiY6jHPU97vTc65k8gL+gmmrpchsW0aqmZAkEA/c8zfmKvY37T
+cxcLLwzwsqqH7g2KZGTf9aRmx2ebdW+QKviJJhbdluDgl1TNNFj5vCLznFDRHiqJ
+wq0wkZ39cwJBAN9l5v3kdXj21UrurNPdlV0n2GZBt2vblooQC37XHF97r2zM7Ou+
+Lg6MyfJClyguhWL9dxnGbf3btQ0l3KDstxMCQCRaiEqjAfIjWVATzeNIXDWLHXso
+b1kf5cA+cwY+vdKdTy4IeUR+Y/DXdvPWDqpf0C11aCVMohdLCn5a5ikFUycCQDhV
+K/BuAallJNfmY7JxN87r00fF3ojWMJnT/fIYMFFrkQrwifXQWTDWE76BSDibsosJ
+u1TGksnm8zrDh2UVC/0CQFrHTiSl/3DHvWAbOJawGKg46cnlDcAhSyV8Frs8/dlP
+7YGG3eqkw++lsghqmFO6mRUTKsBmiiB2wgLGhL5pyYY=
+-----END RSA PRIVATE KEY-----
\ No newline at end of file

Added: camel/trunk/components/camel-jsch/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/test/resources/log4j.properties?rev=1292947&view=auto
==============================================================================
--- camel/trunk/components/camel-jsch/src/test/resources/log4j.properties (added)
+++ camel/trunk/components/camel-jsch/src/test/resources/log4j.properties Thu Feb 23 20:48:47 2012
@@ -0,0 +1,38 @@
+## ------------------------------------------------------------------------
+## 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.
+## ------------------------------------------------------------------------
+
+#
+# The logging properties used for eclipse testing, We want to see debug output on the console.
+#
+log4j.rootLogger=INFO, file
+
+# uncomment the following to enable camel debugging
+# log4j.logger.org.apache.camel=DEBUG
+# log4j.logger.org.apache.camel.component.jsch=TRACE
+# log4j.logger.org.apache.sshd=DEBUG
+
+# CONSOLE appender not used by default
+log4j.appender.out=org.apache.log4j.ConsoleAppender
+log4j.appender.out.layout=org.apache.log4j.PatternLayout
+#log4j.appender.out.layout.ConversionPattern=[%30.30t] %-30.30c{1} %-5p %m%n
+log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
+
+# File appender
+log4j.appender.file=org.apache.log4j.FileAppender
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
+log4j.appender.file.file=target/camel-jsch-test.log
\ No newline at end of file

Added: camel/trunk/components/camel-jsch/src/test/resources/server.jks
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jsch/src/test/resources/server.jks?rev=1292947&view=auto
==============================================================================
Files camel/trunk/components/camel-jsch/src/test/resources/server.jks (added) and camel/trunk/components/camel-jsch/src/test/resources/server.jks Thu Feb 23 20:48:47 2012 differ

Modified: camel/trunk/components/pom.xml
URL: http://svn.apache.org/viewvc/camel/trunk/components/pom.xml?rev=1292947&r1=1292946&r2=1292947&view=diff
==============================================================================
--- camel/trunk/components/pom.xml (original)
+++ camel/trunk/components/pom.xml Thu Feb 23 20:48:47 2012
@@ -99,6 +99,7 @@
     <module>camel-jmx</module>
     <module>camel-josql</module>
     <module>camel-jpa</module>
+    <module>camel-jsch</module>
     <module>camel-jt400</module>
     <module>camel-juel</module>
     <module>camel-jxpath</module>