From 3b2436bbc91255087690029ea8cb0e29010b82bf Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Mon, 19 Dec 2011 16:52:06 -0500 Subject: [PATCH 01/32] initial implementation of camel-ssh --- components/camel-ssh/ReadMe.txt | 11 ++ components/camel-ssh/pom.xml | 99 +++++++++++++++++ .../camel/component/ssh/SshComponent.java | 37 ++++++ .../camel/component/ssh/SshConfiguration.java | 95 ++++++++++++++++ .../camel/component/ssh/SshConsumer.java | 57 ++++++++++ .../camel/component/ssh/SshEndpoint.java | 92 +++++++++++++++ .../camel/component/ssh/SshProducer.java | 70 ++++++++++++ .../services/org/apache/camel/component/ssh | 18 +++ .../src/main/resources/log4j.properties | 16 +++ .../ssh/BogusPasswordAuthenticator.java | 34 ++++++ .../ssh/BogusPublickeyAuthenticator.java | 36 ++++++ .../camel/component/ssh/EchoShellFactory.java | 92 +++++++++++++++ .../camel/component/ssh/SshComponentTest.java | 105 ++++++++++++++++++ .../src/test/resources/dsaprivkey.pem | 12 ++ .../camel-ssh/src/test/resources/hostkey.pem | 15 +++ components/pom.xml | 1 + 16 files changed, 790 insertions(+) create mode 100644 components/camel-ssh/ReadMe.txt create mode 100644 components/camel-ssh/pom.xml create mode 100644 components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java create mode 100644 components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java create mode 100644 components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java create mode 100644 components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java create mode 100644 components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java create mode 100644 components/camel-ssh/src/main/resources/META-INF/services/org/apache/camel/component/ssh create mode 100644 components/camel-ssh/src/main/resources/log4j.properties create mode 100644 components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPasswordAuthenticator.java create mode 100644 components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPublickeyAuthenticator.java create mode 100644 components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java create mode 100644 components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java create mode 100644 components/camel-ssh/src/test/resources/dsaprivkey.pem create mode 100644 components/camel-ssh/src/test/resources/hostkey.pem diff --git a/components/camel-ssh/ReadMe.txt b/components/camel-ssh/ReadMe.txt new file mode 100644 index 0000000000000..3cc57d1e8468c --- /dev/null +++ b/components/camel-ssh/ReadMe.txt @@ -0,0 +1,11 @@ +Camel Component Project +==================== +This Project is a template of the Camel component. +When you create the component project, you need to move the META-INF/services/org/apache/camel/component/${name} +file to META-INF/services/org/apache/camel/component/foo where "foo" is the URI scheme for your component and any + related endpoints created on the fly. + +For more help see the Apache Camel documentation + + http://camel.apache.org/writing-components.html + diff --git a/components/camel-ssh/pom.xml b/components/camel-ssh/pom.xml new file mode 100644 index 0000000000000..9e28e67ca3f94 --- /dev/null +++ b/components/camel-ssh/pom.xml @@ -0,0 +1,99 @@ + + + + + components + org.apache.camel + 2.9-SNAPSHOT + + + 4.0.0 + + camel-ssh + jar + + Camel :: SSH + http://www.myorganization.org + + + + org.apache.camel + camel-core + + + org.apache.mina + mina-core + 2.0.1 + + + org.apache.sshd + sshd-core + 0.5.0 + + + + + org.apache.camel + camel-test + test + + + + bouncycastle + bcprov-jdk15 + 140 + test + + + + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + test + + + log4j + log4j + test + + + + + install + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java new file mode 100644 index 0000000000000..7722f4622f263 --- /dev/null +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java @@ -0,0 +1,37 @@ +/** + * 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.ssh; + +import java.net.URI; +import java.util.Map; + +import org.apache.camel.Endpoint; +import org.apache.camel.impl.DefaultComponent; + +/** + * Represents the component that manages {@link SshEndpoint}. + */ +public class SshComponent extends DefaultComponent { + + protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { + SshConfiguration config = new SshConfiguration(new URI(uri)); + + Endpoint endpoint = new SshEndpoint(uri, this, config); + setProperties(endpoint, parameters); + return endpoint; + } +} diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java new file mode 100644 index 0000000000000..18e939db747bb --- /dev/null +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java @@ -0,0 +1,95 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.ssh; + +import org.apache.camel.util.ObjectHelper; + +import java.net.URI; + +public class SshConfiguration { + public static final int DEFAULT_SSH_PORT = 22; + + private String username; + private String host; + private int port; + private String password; + + public SshConfiguration() { + } + + public SshConfiguration(URI uri) { + configure(uri); + } + + protected void setDefaultPort() { + setPort(DEFAULT_SSH_PORT); + } + + public void configure(URI uri) { + setDefaultPort(); + + // UserInfo can contain both username and password as: user:pwd@sshserver + // see: http://en.wikipedia.org/wiki/URI_scheme + String username = uri.getUserInfo(); + String pw = null; + if (username != null && username.contains(":")) { + pw = ObjectHelper.after(username, ":"); + username = ObjectHelper.before(username, ":"); + } + if (username != null) { + setUsername(username); + } + if (pw != null) { + setPassword(pw); + } + + setHost(uri.getHost()); + setPort(uri.getPort()); + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java new file mode 100644 index 0000000000000..0085c5b3ddd78 --- /dev/null +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java @@ -0,0 +1,57 @@ +/** + * 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.ssh; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.impl.DefaultProducer; +import org.apache.camel.impl.ScheduledPollConsumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +public class SshConsumer extends ScheduledPollConsumer { + private static final transient Logger LOG = LoggerFactory.getLogger(SshConsumer.class); + + private final SshEndpoint endpoint; + + public SshConsumer(SshEndpoint endpoint, Processor processor) { + super(endpoint, processor); + this.endpoint = endpoint; + } + + @Override + protected int poll() throws Exception { + Exchange exchange = endpoint.createExchange(); + + // create a message body + Date now = new Date(); + exchange.getIn().setBody("Hello World! The time is " + now); + + try { + // send message to next processor in the route + getProcessor().process(exchange); + return 1; // number of messages polled + } finally { + // log exception if an exception occurred and was not handled + if (exchange.getException() != null) { + getExceptionHandler().handleException("Error processing exchange", exchange, exchange.getException()); + } + } + } +} diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java new file mode 100644 index 0000000000000..2bdf6b9dad47e --- /dev/null +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -0,0 +1,92 @@ +/** + * 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.ssh; + +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.impl.DefaultEndpoint; +import org.apache.sshd.ClientChannel; +import org.apache.sshd.ClientSession; +import org.apache.sshd.SshClient; + +/** + * Represents a HelloWorld endpoint. + */ +public class SshEndpoint extends DefaultEndpoint { + + private SshConfiguration config; + private SshClient client; + private int port; + + public SshEndpoint() { + } + + public SshEndpoint(String endpointUri) { + super(endpointUri); + } + + public SshEndpoint(String uri, SshComponent component) { + super(uri, component); + } + + public SshEndpoint(String uri, SshComponent component, SshConfiguration config) { + super(uri, component); + this.config = config; + } + + public Producer createProducer() throws Exception { + return new SshProducer(this); + } + + public Consumer createConsumer(Processor processor) throws Exception { + return new SshConsumer(this, processor); + } + + public boolean isSingleton() { + return false; + } + + ClientSession createSession() throws Exception { + ClientSession session = client.connect(config.getHost(), config.getPort()).await().getSession(); + session.authPassword(config.getUsername(), config.getPassword()).await().isSuccess(); + + return session; + } + + @Override + protected void doStart() throws Exception { + super.doStart(); + + client = SshClient.setUpDefaultClient(); + client.start(); + } + + @Override + protected void doStop() throws Exception { + if (client != null) { + client.stop(); + client = null; + } + + super.doStop(); + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java new file mode 100644 index 0000000000000..180fbca1c0f72 --- /dev/null +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java @@ -0,0 +1,70 @@ +/** + * 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.ssh; + +import org.apache.camel.Exchange; +import org.apache.camel.impl.DefaultProducer; +import org.apache.sshd.ClientChannel; +import org.apache.sshd.ClientSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; + +/** + * The HelloWorld producer. + */ +public class SshProducer extends DefaultProducer { + private static final transient Logger LOG = LoggerFactory.getLogger(SshProducer.class); + + private SshEndpoint endpoint; + + public SshProducer(SshEndpoint endpoint) { + super(endpoint); + this.endpoint = endpoint; + } + + public void process(Exchange exchange) throws Exception { + System.out.println(exchange.getIn().getBody()); + + ClientSession session = endpoint.createSession(); + + ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL); + + PipedOutputStream pipedIn = new PipedOutputStream(); + channel.setIn(new PipedInputStream(pipedIn)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayOutputStream err = new ByteArrayOutputStream(); + channel.setOut(out); + channel.setErr(err); + channel.open(); + + pipedIn.write(exchange.getIn().getBody(byte[].class)); + pipedIn.flush(); + + channel.waitFor(ClientChannel.CLOSED, 0); + + channel.close(false); + session.close(false); + + exchange.getOut().setBody(out.toByteArray()); + } + +} diff --git a/components/camel-ssh/src/main/resources/META-INF/services/org/apache/camel/component/ssh b/components/camel-ssh/src/main/resources/META-INF/services/org/apache/camel/component/ssh new file mode 100644 index 0000000000000..1f76f468d7f2a --- /dev/null +++ b/components/camel-ssh/src/main/resources/META-INF/services/org/apache/camel/component/ssh @@ -0,0 +1,18 @@ +# +# 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.ssh.SshComponent diff --git a/components/camel-ssh/src/main/resources/log4j.properties b/components/camel-ssh/src/main/resources/log4j.properties new file mode 100644 index 0000000000000..4621723d31a1b --- /dev/null +++ b/components/camel-ssh/src/main/resources/log4j.properties @@ -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 diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPasswordAuthenticator.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPasswordAuthenticator.java new file mode 100644 index 0000000000000..c76e7705887a4 --- /dev/null +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPasswordAuthenticator.java @@ -0,0 +1,34 @@ +/* + * 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.ssh; + +import org.apache.sshd.server.PasswordAuthenticator; +import org.apache.sshd.server.session.ServerSession; + +/** + * TODO Add javadoc + * + * @author Apache MINA SSHD Project + */ +public class BogusPasswordAuthenticator implements PasswordAuthenticator { + + public boolean authenticate(String username, String password, ServerSession session) { + return username != null && username.equals(password); + } +} diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPublickeyAuthenticator.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPublickeyAuthenticator.java new file mode 100644 index 0000000000000..3da7f25530edc --- /dev/null +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPublickeyAuthenticator.java @@ -0,0 +1,36 @@ +/* + * 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.ssh; + +import org.apache.sshd.server.PublickeyAuthenticator; +import org.apache.sshd.server.session.ServerSession; + +import java.security.PublicKey; + +/** + * TODO Add javadoc + * + * @author Apache MINA SSHD Project + */ +public class BogusPublickeyAuthenticator implements PublickeyAuthenticator { + + public boolean authenticate(String username, PublicKey key, ServerSession session) { + return true; + } +} diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java new file mode 100644 index 0000000000000..a1d5c91e36601 --- /dev/null +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java @@ -0,0 +1,92 @@ +/* + * 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.ssh; + +import org.apache.sshd.common.Factory; +import org.apache.sshd.server.Command; +import org.apache.sshd.server.Environment; +import org.apache.sshd.server.ExitCallback; + +import java.io.*; + +/** + * TODO Add javadoc + * + * @author Apache MINA SSHD Project + */ +public class EchoShellFactory implements Factory { + + public Command create() { + return new EchoShell(); + } + + protected static class EchoShell implements Command, Runnable { + private InputStream in; + private OutputStream out; + private OutputStream err; + private ExitCallback callback; + private Thread thread; + + public void setInputStream(InputStream in) { + this.in = in; + } + + public void setOutputStream(OutputStream out) { + this.out = out; + } + + public void setErrorStream(OutputStream err) { + this.err = err; + } + + public void setExitCallback(ExitCallback callback) { + this.callback = callback; + } + + public void start(Environment env) throws IOException { + thread = new Thread(this, "EchoShell"); + thread.start(); + } + + public void destroy() { + thread.interrupt(); + } + + public void run() { + BufferedReader r = new BufferedReader(new InputStreamReader(in)); + try { + for (;;) { + String s = r.readLine(); + if (s == null) { + return; + } + out.write((s + "\n").getBytes()); + out.flush(); + if ("exit".equals(s)) { + return; + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + callback.onExit(0); + } + } + } +} diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java new file mode 100644 index 0000000000000..25f85f4b41dc9 --- /dev/null +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java @@ -0,0 +1,105 @@ +/** + * 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.ssh; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.sshd.SshServer; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; +import org.apache.sshd.server.Command; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.net.ServerSocket; +import java.util.concurrent.CountDownLatch; + +public class SshComponentTest extends CamelTestSupport { + + private SshServer sshd; + private int port; + + @Override + public void setUp() throws Exception { + ServerSocket s = new ServerSocket(0); + port = s.getLocalPort(); + s.close(); + + sshd = SshServer.setUpDefaultServer(); + sshd.setPort(port); + sshd.setKeyPairProvider(new FileKeyPairProvider(new String[] { "src/test/resources/hostkey.pem" })); + sshd.setShellFactory(new TestEchoShellFactory()); + sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator()); + sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator()); + sshd.start(); + + super.setUp(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + + if (sshd != null) { + sshd.stop(true); + Thread.sleep(50); + } + } + + @Test + public void testHelloWorld() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + public void configure() { + from("timer://foo?fixedRate=true&period=5000") + .setBody().constant("test\nexit\n") + .to("ssh://smx:smx@localhost:"+port) + .to("mock:result") + .to("log:foo?showAll=true"); + } + }; + } + + public static class TestEchoShellFactory extends EchoShellFactory { + @Override + public Command create() { + return new TestEchoShell(); + } + + public static class TestEchoShell extends EchoShell { + + public static CountDownLatch latch = new CountDownLatch(1); + + @Override + public void destroy() { + if (latch != null) { + latch.countDown(); + } + super.destroy(); + } + } + } + +} diff --git a/components/camel-ssh/src/test/resources/dsaprivkey.pem b/components/camel-ssh/src/test/resources/dsaprivkey.pem new file mode 100644 index 0000000000000..c920b7fc04e23 --- /dev/null +++ b/components/camel-ssh/src/test/resources/dsaprivkey.pem @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQDEA7leYDKyJOFJU3h0uPpWN52iTpJk8+IM53Vc/91k7pBIjjka ++MP24BMh+sI2SRhxg2AtvwnzRRBVJWzEA4+tuCI6WukgeDQtSNp3YuWzOMefZ6Wb +SAk1Y4goZb7nyqV9HZSFNSqUFQRZM10L768VURBlerNqR//GqdVd8bp7lwIVAM39 +h6x2DeXbqUM8iOi01bh5jpLFAoGAEi1oFGFMEZXH/hCX+Y2VE5WvR+fBaoS9WuZl +3E0wsWPzQhbL13yD+6Htxd3XoQvrHnzyrIgi2AiAmr3mLokQbZ3d92IxEBcNB/0p +nVi020TXSeD/lWkpk5FRvgBiJ82/LeC2Lj6cssznX73aLUhR0tsSoJoXxas0sQKa +/UJgq5wCgYAtgeY99J0JxplWGSyGY/1DUpgzhdgpLdDA/o/qIjBEeHXN0QX4Ajoa +vHggJ2SwNtAxbQedBxqmB3mquFRtpfEP5zGzsVx5HHnljSH8u0SqEoLnYKFpluwh +tZ/Q3F2NHslXw8Hw+pIaPe4PAINQPAu3U+BknNUkGpLg8zU6h5+B+wIVAKRqeps1 +Xl7MxZcSZp7FnmmmMecB +-----END DSA PRIVATE KEY----- diff --git a/components/camel-ssh/src/test/resources/hostkey.pem b/components/camel-ssh/src/test/resources/hostkey.pem new file mode 100644 index 0000000000000..6b6974c78e606 --- /dev/null +++ b/components/camel-ssh/src/test/resources/hostkey.pem @@ -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----- diff --git a/components/pom.xml b/components/pom.xml index 0206953305ea0..f3b7d3274d201 100644 --- a/components/pom.xml +++ b/components/pom.xml @@ -132,6 +132,7 @@ camel-spring-security camel-spring-ws camel-sql + camel-ssh camel-stax camel-stream camel-stringtemplate From 0e6fe3e22d011ba4b317ea70e86d9158e5755f61 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Tue, 20 Dec 2011 08:33:19 -0500 Subject: [PATCH 02/32] add OSGi settings to camel-ssh --- components/camel-ssh/pom.xml | 35 +++++++------------ .../features/src/main/resources/features.xml | 15 +++++--- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/components/camel-ssh/pom.xml b/components/camel-ssh/pom.xml index 9e28e67ca3f94..db0849187359c 100644 --- a/components/camel-ssh/pom.xml +++ b/components/camel-ssh/pom.xml @@ -19,19 +19,24 @@ --> + + 4.0.0 + - components org.apache.camel - 2.9-SNAPSHOT + camel-parent + 2.10-SNAPSHOT + ../../parent - 4.0.0 - camel-ssh - jar - + bundle Camel :: SSH - http://www.myorganization.org + Camel SSH support + + + org.apache.camel.component.ssh.* + @@ -80,20 +85,4 @@ test - - - install - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - diff --git a/platforms/karaf/features/src/main/resources/features.xml b/platforms/karaf/features/src/main/resources/features.xml index 1e5485d404c74..370986776040a 100644 --- a/platforms/karaf/features/src/main/resources/features.xml +++ b/platforms/karaf/features/src/main/resources/features.xml @@ -642,10 +642,17 @@ camel-core mvn:org.apache.camel/camel-sql/${pom.version} - - camel-core - mvn:org.apache.camel/camel-stax/${pom.version} - + + camel-core + + mvn:org.apache.camel/camel-ssh/${pom.version} + + + camel-core + mvn:org.apache.camel/camel-stax/${pom.version} + camel-core mvn:org.apache.camel/camel-stream/${pom.version} From 535ca30cfb12a8dc9c2affc8b567d3e6f4f5b272 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 22 Dec 2011 17:14:12 -0500 Subject: [PATCH 03/32] creating camel-example-ssh --- examples/camel-example-ssh/pom.xml | 95 ++++++++++++++++++++++++++++++ examples/pom.xml | 1 + 2 files changed, 96 insertions(+) create mode 100644 examples/camel-example-ssh/pom.xml diff --git a/examples/camel-example-ssh/pom.xml b/examples/camel-example-ssh/pom.xml new file mode 100644 index 0000000000000..43c41c3089978 --- /dev/null +++ b/examples/camel-example-ssh/pom.xml @@ -0,0 +1,95 @@ + + + + + + + 4.0.0 + + + org.apache.camel + examples + 2.10-SNAPSHOT + .. + + + camel-example-ssh + bundle + Camel :: Example :: SSH + A simple SSH example which creates a bundle that can be dropped into any OSGi container + + + org.apache.camel.example.ssh.* + + + + + + org.apache.camel + camel-core + + + org.apache.camel + camel-ssh + ${project.version} + + + + + org.slf4j + slf4j-simple + ${slf4j-version} + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + target/classes/features.xml + xml + features + + + + + + + + + + org.apache.camel + camel-maven-plugin + ${project.version} + + + + + + diff --git a/examples/pom.xml b/examples/pom.xml index ba9b99f6477b0..ae7bc3ab13534 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -64,6 +64,7 @@ camel-example-spring-xquery camel-example-spring-security camel-example-tracer + camel-example-ssh From 2611a2ba3a756d1641691912f960ec83db46595d Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 23 Dec 2011 09:39:50 -0500 Subject: [PATCH 04/32] camel-example-ssh working in karaf --- examples/camel-example-ssh/README.txt | 42 ++++ examples/camel-example-ssh/pom.xml | 24 +++ .../src/main/resources/META-INF/LICENSE.txt | 203 ++++++++++++++++++ .../src/main/resources/META-INF/NOTICE.txt | 11 + .../META-INF/spring/camelContext.xml | 37 ++++ .../src/main/resources/features.xml | 26 +++ examples/pom.xml | 2 +- .../features/src/main/resources/features.xml | 4 +- 8 files changed, 345 insertions(+), 4 deletions(-) create mode 100644 examples/camel-example-ssh/README.txt create mode 100644 examples/camel-example-ssh/src/main/resources/META-INF/LICENSE.txt create mode 100644 examples/camel-example-ssh/src/main/resources/META-INF/NOTICE.txt create mode 100644 examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml create mode 100644 examples/camel-example-ssh/src/main/resources/features.xml diff --git a/examples/camel-example-ssh/README.txt b/examples/camel-example-ssh/README.txt new file mode 100644 index 0000000000000..ddec65458751e --- /dev/null +++ b/examples/camel-example-ssh/README.txt @@ -0,0 +1,42 @@ +OSGi Example +===================== + +This example shows how use SSH with Camel. It can be run using Maven. + +This example is built assuming you have a running Apache ServiceMix container with the default SSH port 8101 and +username / password of smx/smx. + +Running from cmd line outside OSGi container +============================================ + +You will need to compile this example first: + mvn compile + +To run the example using Maven type + mvn camel:run + +To stop the example hit ctrl + c + + + +Running inside OSGi container +============================= + +You will need to compile and install this example first: + mvn compile install + +If using Apache Karaf / Apache ServiceMix you can install this example +from the shell + + > features:addurl mvn:org.apache.camel/camel-example-ssh/2.10-SNAPSHOT/xml/features + > features:install camel-example-ssh + +If you hit any problems please let us know on the Camel Forums + http://camel.apache.org/discussion-forums.html + +Please help us make Apache Camel better - we appreciate any feedback you +may have. Enjoy! + +------------------------ +The Camel riders! + diff --git a/examples/camel-example-ssh/pom.xml b/examples/camel-example-ssh/pom.xml index 43c41c3089978..0399c392d9ec1 100644 --- a/examples/camel-example-ssh/pom.xml +++ b/examples/camel-example-ssh/pom.xml @@ -42,11 +42,20 @@ org.apache.camel camel-core + + org.apache.camel + camel-spring + org.apache.camel camel-ssh ${project.version} + + org.apache.mina + mina-core + 2.0.1 + @@ -59,6 +68,21 @@ + + + org.apache.felix + maven-bundle-plugin + true + + + + org.apache.camel.component.ssh, + * + + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/examples/camel-example-ssh/src/main/resources/META-INF/LICENSE.txt b/examples/camel-example-ssh/src/main/resources/META-INF/LICENSE.txt new file mode 100644 index 0000000000000..6b0b1270ff0ca --- /dev/null +++ b/examples/camel-example-ssh/src/main/resources/META-INF/LICENSE.txt @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. + diff --git a/examples/camel-example-ssh/src/main/resources/META-INF/NOTICE.txt b/examples/camel-example-ssh/src/main/resources/META-INF/NOTICE.txt new file mode 100644 index 0000000000000..2e215bf2e6b1f --- /dev/null +++ b/examples/camel-example-ssh/src/main/resources/META-INF/NOTICE.txt @@ -0,0 +1,11 @@ + ========================================================================= + == NOTICE file corresponding to the section 4 d of == + == the Apache License, Version 2.0, == + == in this case for the Apache Camel distribution. == + ========================================================================= + + This product includes software developed by + The Apache Software Foundation (http://www.apache.org/). + + Please read the different LICENSE files present in the licenses directory of + this distribution. diff --git a/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml b/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml new file mode 100644 index 0000000000000..17cfdd486afda --- /dev/null +++ b/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml @@ -0,0 +1,37 @@ + + + + + + + + + + osgi:list shell:logout + + + + + + + diff --git a/examples/camel-example-ssh/src/main/resources/features.xml b/examples/camel-example-ssh/src/main/resources/features.xml new file mode 100644 index 0000000000000..4f081d68bd223 --- /dev/null +++ b/examples/camel-example-ssh/src/main/resources/features.xml @@ -0,0 +1,26 @@ + + + + mvn:org.apache.camel.karaf/apache-camel/${project.version}/xml/features + + + camel-ssh + mvn:org.apache.camel/camel-example-ssh/${project.version} + + + \ No newline at end of file diff --git a/examples/pom.xml b/examples/pom.xml index ae7bc3ab13534..3051cfe657461 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -63,8 +63,8 @@ camel-example-spring-ws camel-example-spring-xquery camel-example-spring-security + camel-example-ssh camel-example-tracer - camel-example-ssh diff --git a/platforms/karaf/features/src/main/resources/features.xml b/platforms/karaf/features/src/main/resources/features.xml index 848877f766467..01853af1c6cee 100644 --- a/platforms/karaf/features/src/main/resources/features.xml +++ b/platforms/karaf/features/src/main/resources/features.xml @@ -647,9 +647,7 @@ camel-core - + mvn:org.apache.mina/mina-core/2.0.1 mvn:org.apache.camel/camel-ssh/${pom.version} From 8f3c72e85d96c555077e5a76c3325f920022d9f7 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 23 Dec 2011 10:28:57 -0500 Subject: [PATCH 05/32] merged with camel trunk --- components/camel-ssh/pom.xml | 2 +- examples/camel-example-ssh/README.txt | 2 +- examples/camel-example-ssh/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/camel-ssh/pom.xml b/components/camel-ssh/pom.xml index db0849187359c..117c45773fa73 100644 --- a/components/camel-ssh/pom.xml +++ b/components/camel-ssh/pom.xml @@ -25,7 +25,7 @@ org.apache.camel camel-parent - 2.10-SNAPSHOT + 2.9-SNAPSHOT ../../parent diff --git a/examples/camel-example-ssh/README.txt b/examples/camel-example-ssh/README.txt index ddec65458751e..2838c07781d5c 100644 --- a/examples/camel-example-ssh/README.txt +++ b/examples/camel-example-ssh/README.txt @@ -28,7 +28,7 @@ You will need to compile and install this example first: If using Apache Karaf / Apache ServiceMix you can install this example from the shell - > features:addurl mvn:org.apache.camel/camel-example-ssh/2.10-SNAPSHOT/xml/features + > features:addurl mvn:org.apache.camel/camel-example-ssh/2.9-SNAPSHOT/xml/features > features:install camel-example-ssh If you hit any problems please let us know on the Camel Forums diff --git a/examples/camel-example-ssh/pom.xml b/examples/camel-example-ssh/pom.xml index 0399c392d9ec1..b51415566c844 100644 --- a/examples/camel-example-ssh/pom.xml +++ b/examples/camel-example-ssh/pom.xml @@ -23,7 +23,7 @@ org.apache.camel examples - 2.10-SNAPSHOT + 2.9-SNAPSHOT .. From 761200b5914c8773124a85496f8d6d2f7b7624df Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 29 Dec 2011 10:08:00 -0500 Subject: [PATCH 06/32] merged with latest Camel trunk --- components/camel-ssh/pom.xml | 2 +- examples/camel-example-ssh/README.txt | 2 +- examples/camel-example-ssh/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/camel-ssh/pom.xml b/components/camel-ssh/pom.xml index 117c45773fa73..db0849187359c 100644 --- a/components/camel-ssh/pom.xml +++ b/components/camel-ssh/pom.xml @@ -25,7 +25,7 @@ org.apache.camel camel-parent - 2.9-SNAPSHOT + 2.10-SNAPSHOT ../../parent diff --git a/examples/camel-example-ssh/README.txt b/examples/camel-example-ssh/README.txt index 2838c07781d5c..ddec65458751e 100644 --- a/examples/camel-example-ssh/README.txt +++ b/examples/camel-example-ssh/README.txt @@ -28,7 +28,7 @@ You will need to compile and install this example first: If using Apache Karaf / Apache ServiceMix you can install this example from the shell - > features:addurl mvn:org.apache.camel/camel-example-ssh/2.9-SNAPSHOT/xml/features + > features:addurl mvn:org.apache.camel/camel-example-ssh/2.10-SNAPSHOT/xml/features > features:install camel-example-ssh If you hit any problems please let us know on the Camel Forums diff --git a/examples/camel-example-ssh/pom.xml b/examples/camel-example-ssh/pom.xml index b51415566c844..0399c392d9ec1 100644 --- a/examples/camel-example-ssh/pom.xml +++ b/examples/camel-example-ssh/pom.xml @@ -23,7 +23,7 @@ org.apache.camel examples - 2.9-SNAPSHOT + 2.10-SNAPSHOT .. From 3f193f193ae2d2fb931ca6e8d329df388d93db41 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 29 Dec 2011 11:06:25 -0500 Subject: [PATCH 07/32] Cleanup to make check style happy --- .../camel/component/ssh/SshComponent.java | 5 ++- .../camel/component/ssh/SshConfiguration.java | 4 +- .../camel/component/ssh/SshConsumer.java | 7 ++-- .../camel/component/ssh/SshEndpoint.java | 4 +- .../camel/component/ssh/SshProducer.java | 8 ++-- .../ssh/BogusPasswordAuthenticator.java | 29 +++++++------ .../ssh/BogusPublickeyAuthenticator.java | 33 +++++++-------- .../camel/component/ssh/EchoShellFactory.java | 42 +++++++++++-------- .../camel/component/ssh/SshComponentTest.java | 23 +++++----- examples/camel-example-ssh/pom.xml | 3 +- .../META-INF/spring/camelContext.xml | 20 ++++----- .../src/main/resources/features.xml | 2 +- 12 files changed, 92 insertions(+), 88 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java index 7722f4622f263..68174506056c5 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java @@ -16,8 +16,8 @@ */ package org.apache.camel.component.ssh; -import java.net.URI; -import java.util.Map; +import java.net.*; +import java.util.*; import org.apache.camel.Endpoint; import org.apache.camel.impl.DefaultComponent; @@ -27,6 +27,7 @@ */ public class SshComponent extends DefaultComponent { + @Override protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { SshConfiguration config = new SshConfiguration(new URI(uri)); diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java index 18e939db747bb..4640907342f90 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java @@ -16,9 +16,9 @@ */ package org.apache.camel.component.ssh; -import org.apache.camel.util.ObjectHelper; +import java.net.*; -import java.net.URI; +import org.apache.camel.util.ObjectHelper; public class SshConfiguration { public static final int DEFAULT_SSH_PORT = 22; diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java index 0085c5b3ddd78..cda4897fff8e3 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java @@ -16,15 +16,14 @@ */ package org.apache.camel.component.ssh; +import java.util.*; + import org.apache.camel.Exchange; import org.apache.camel.Processor; -import org.apache.camel.impl.DefaultProducer; import org.apache.camel.impl.ScheduledPollConsumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; - public class SshConsumer extends ScheduledPollConsumer { private static final transient Logger LOG = LoggerFactory.getLogger(SshConsumer.class); @@ -34,7 +33,7 @@ public SshConsumer(SshEndpoint endpoint, Processor processor) { super(endpoint, processor); this.endpoint = endpoint; } - + @Override protected int poll() throws Exception { Exchange exchange = endpoint.createExchange(); diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index 2bdf6b9dad47e..f80e52144fa21 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -20,7 +20,6 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.impl.DefaultEndpoint; -import org.apache.sshd.ClientChannel; import org.apache.sshd.ClientSession; import org.apache.sshd.SshClient; @@ -49,14 +48,17 @@ public SshEndpoint(String uri, SshComponent component, SshConfiguration config) this.config = config; } + @Override public Producer createProducer() throws Exception { return new SshProducer(this); } + @Override public Consumer createConsumer(Processor processor) throws Exception { return new SshConsumer(this, processor); } + @Override public boolean isSingleton() { return false; } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java index 180fbca1c0f72..1165477fc45c4 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.ssh; +import java.io.*; + import org.apache.camel.Exchange; import org.apache.camel.impl.DefaultProducer; import org.apache.sshd.ClientChannel; @@ -23,11 +25,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; - /** * The HelloWorld producer. */ @@ -41,6 +38,7 @@ public SshProducer(SshEndpoint endpoint) { this.endpoint = endpoint; } + @Override public void process(Exchange exchange) throws Exception { System.out.println(exchange.getIn().getBody()); diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPasswordAuthenticator.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPasswordAuthenticator.java index c76e7705887a4..9ad5ee2aede19 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPasswordAuthenticator.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPasswordAuthenticator.java @@ -1,20 +1,18 @@ -/* - * 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 +/** + * 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 + * 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. + * 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.ssh; @@ -28,6 +26,7 @@ */ public class BogusPasswordAuthenticator implements PasswordAuthenticator { + @Override public boolean authenticate(String username, String password, ServerSession session) { return username != null && username.equals(password); } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPublickeyAuthenticator.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPublickeyAuthenticator.java index 3da7f25530edc..52e05d3329f08 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPublickeyAuthenticator.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/BogusPublickeyAuthenticator.java @@ -1,28 +1,26 @@ -/* - * 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 +/** + * 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 + * 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. + * 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.ssh; +import java.security.PublicKey; + import org.apache.sshd.server.PublickeyAuthenticator; import org.apache.sshd.server.session.ServerSession; -import java.security.PublicKey; - /** * TODO Add javadoc * @@ -30,6 +28,7 @@ */ public class BogusPublickeyAuthenticator implements PublickeyAuthenticator { + @Override public boolean authenticate(String username, PublicKey key, ServerSession session) { return true; } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java index a1d5c91e36601..b9436fe3a9226 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java @@ -1,30 +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 +/** + * 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 + * 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. + * 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.ssh; +import java.io.*; + import org.apache.sshd.common.Factory; import org.apache.sshd.server.Command; import org.apache.sshd.server.Environment; import org.apache.sshd.server.ExitCallback; -import java.io.*; - /** * TODO Add javadoc * @@ -32,6 +30,7 @@ */ public class EchoShellFactory implements Factory { + @Override public Command create() { return new EchoShell(); } @@ -43,35 +42,42 @@ protected static class EchoShell implements Command, Runnable { private ExitCallback callback; private Thread thread; + @Override public void setInputStream(InputStream in) { this.in = in; } + @Override public void setOutputStream(OutputStream out) { this.out = out; } + @Override public void setErrorStream(OutputStream err) { this.err = err; } + @Override public void setExitCallback(ExitCallback callback) { this.callback = callback; } + @Override public void start(Environment env) throws IOException { thread = new Thread(this, "EchoShell"); thread.start(); } + @Override public void destroy() { thread.interrupt(); } + @Override public void run() { BufferedReader r = new BufferedReader(new InputStreamReader(in)); try { - for (;;) { + while (true) { String s = r.readLine(); if (s == null) { return; diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java index 25f85f4b41dc9..f239a82035be5 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java @@ -16,19 +16,17 @@ */ package org.apache.camel.component.ssh; +import java.net.*; +import java.util.concurrent.CountDownLatch; + import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.sshd.SshServer; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.apache.sshd.server.Command; -import org.junit.After; -import org.junit.Before; import org.junit.Test; -import java.net.ServerSocket; -import java.util.concurrent.CountDownLatch; - public class SshComponentTest extends CamelTestSupport { private SshServer sshd; @@ -42,7 +40,7 @@ public void setUp() throws Exception { sshd = SshServer.setUpDefaultServer(); sshd.setPort(port); - sshd.setKeyPairProvider(new FileKeyPairProvider(new String[] { "src/test/resources/hostkey.pem" })); + sshd.setKeyPairProvider(new FileKeyPairProvider(new String[]{"src/test/resources/hostkey.pem"})); sshd.setShellFactory(new TestEchoShellFactory()); sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator()); sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator()); @@ -64,20 +62,21 @@ public void tearDown() throws Exception { @Test public void testHelloWorld() throws Exception { MockEndpoint mock = getMockEndpoint("mock:result"); - mock.expectedMinimumMessageCount(1); - + mock.expectedMinimumMessageCount(1); + assertMockEndpointsSatisfied(); } @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { + @Override public void configure() { from("timer://foo?fixedRate=true&period=5000") - .setBody().constant("test\nexit\n") - .to("ssh://smx:smx@localhost:"+port) - .to("mock:result") - .to("log:foo?showAll=true"); + .setBody().constant("test\nexit\n") + .to("ssh://smx:smx@localhost:" + port) + .to("mock:result") + .to("log:foo?showAll=true"); } }; } diff --git a/examples/camel-example-ssh/pom.xml b/examples/camel-example-ssh/pom.xml index 0399c392d9ec1..9370c75defb12 100644 --- a/examples/camel-example-ssh/pom.xml +++ b/examples/camel-example-ssh/pom.xml @@ -16,7 +16,8 @@ License. --> - + 4.0.0 diff --git a/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml b/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml index 17cfdd486afda..b91ed60765960 100644 --- a/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml +++ b/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml @@ -23,15 +23,15 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - - - - osgi:list shell:logout - - - - - + + + + + osgi:list shell:logout + + + + + diff --git a/examples/camel-example-ssh/src/main/resources/features.xml b/examples/camel-example-ssh/src/main/resources/features.xml index 4f081d68bd223..c9058427506b4 100644 --- a/examples/camel-example-ssh/src/main/resources/features.xml +++ b/examples/camel-example-ssh/src/main/resources/features.xml @@ -17,7 +17,7 @@ --> mvn:org.apache.camel.karaf/apache-camel/${project.version}/xml/features - + camel-ssh mvn:org.apache.camel/camel-example-ssh/${project.version} From 7a58fe1391c945037a449cf6616e381750c28838 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 29 Dec 2011 14:03:16 -0500 Subject: [PATCH 08/32] Fixed default port configuration --- .../org/apache/camel/component/ssh/SshConfiguration.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java index 4640907342f90..1753735501cd9 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java @@ -58,7 +58,12 @@ public void configure(URI uri) { } setHost(uri.getHost()); - setPort(uri.getPort()); + + // URI.getPort returns -1 if port not defined, else use default port + int uriPort = uri.getPort(); + if (uriPort != -1) { + setPort(uriPort); + } } public String getUsername() { From 8978bd9f7349a7402b46c7752c34e12d0c7a32d7 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 29 Dec 2011 14:04:29 -0500 Subject: [PATCH 09/32] Removed debugging System.out.println --- .../main/java/org/apache/camel/component/ssh/SshProducer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java index 1165477fc45c4..95f54624d5843 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java @@ -40,8 +40,6 @@ public SshProducer(SshEndpoint endpoint) { @Override public void process(Exchange exchange) throws Exception { - System.out.println(exchange.getIn().getBody()); - ClientSession session = endpoint.createSession(); ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL); From 58e5f2c70235dc4e816b1acdf44531650a488885 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 29 Dec 2011 14:07:23 -0500 Subject: [PATCH 10/32] Created Polling Consumer for camel-ssh --- .../camel/component/ssh/SshComponent.java | 3 +- .../camel/component/ssh/SshConsumer.java | 28 ++++- .../camel/component/ssh/SshEndpoint.java | 42 +++++--- .../ssh/SshComponentConsumerTest.java | 102 ++++++++++++++++++ ...est.java => SshComponentProducerTest.java} | 2 +- 5 files changed, 156 insertions(+), 21 deletions(-) create mode 100644 components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java rename components/camel-ssh/src/test/java/org/apache/camel/component/ssh/{SshComponentTest.java => SshComponentProducerTest.java} (98%) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java index 68174506056c5..e2410e4b12829 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java @@ -31,7 +31,8 @@ public class SshComponent extends DefaultComponent { protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { SshConfiguration config = new SshConfiguration(new URI(uri)); - Endpoint endpoint = new SshEndpoint(uri, this, config); + SshEndpoint endpoint = new SshEndpoint(uri, this, config); + setProperties(endpoint.getConfiguration(), parameters); setProperties(endpoint, parameters); return endpoint; } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java index cda4897fff8e3..9b67234639a71 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java @@ -16,17 +16,18 @@ */ package org.apache.camel.component.ssh; +import java.io.*; import java.util.*; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.impl.ScheduledPollConsumer; +import org.apache.sshd.ClientChannel; +import org.apache.sshd.ClientSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SshConsumer extends ScheduledPollConsumer { - private static final transient Logger LOG = LoggerFactory.getLogger(SshConsumer.class); - private final SshEndpoint endpoint; public SshConsumer(SshEndpoint endpoint, Processor processor) { @@ -36,11 +37,30 @@ public SshConsumer(SshEndpoint endpoint, Processor processor) { @Override protected int poll() throws Exception { + ClientSession session = endpoint.createSession(); + + ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL); + + PipedOutputStream pipedIn = new PipedOutputStream(); + channel.setIn(new PipedInputStream(pipedIn)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayOutputStream err = new ByteArrayOutputStream(); + channel.setOut(out); + channel.setErr(err); + channel.open(); + + pipedIn.write(endpoint.getPollCommand()); + pipedIn.flush(); + + channel.waitFor(ClientChannel.CLOSED, 0); + + channel.close(false); + session.close(false); + Exchange exchange = endpoint.createExchange(); // create a message body - Date now = new Date(); - exchange.getIn().setBody("Hello World! The time is " + now); + exchange.getIn().setBody(out.toByteArray()); try { // send message to next processor in the route diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index f80e52144fa21..92959b63243c1 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -19,33 +19,29 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; -import org.apache.camel.impl.DefaultEndpoint; +import org.apache.camel.impl.ScheduledPollEndpoint; import org.apache.sshd.ClientSession; import org.apache.sshd.SshClient; /** - * Represents a HelloWorld endpoint. + * Represents an SSH endpoint. */ -public class SshEndpoint extends DefaultEndpoint { +public class SshEndpoint extends ScheduledPollEndpoint { - private SshConfiguration config; private SshClient client; - private int port; + private SshConfiguration configuration; + private byte[] pollCommand; public SshEndpoint() { } - public SshEndpoint(String endpointUri) { - super(endpointUri); - } - public SshEndpoint(String uri, SshComponent component) { super(uri, component); } - public SshEndpoint(String uri, SshComponent component, SshConfiguration config) { + public SshEndpoint(String uri, SshComponent component, SshConfiguration configuration) { super(uri, component); - this.config = config; + this.configuration = configuration; } @Override @@ -64,8 +60,8 @@ public boolean isSingleton() { } ClientSession createSession() throws Exception { - ClientSession session = client.connect(config.getHost(), config.getPort()).await().getSession(); - session.authPassword(config.getUsername(), config.getPassword()).await().isSuccess(); + ClientSession session = client.connect(configuration.getHost(), configuration.getPort()).await().getSession(); + session.authPassword(configuration.getUsername(), configuration.getPassword()).await().isSuccess(); return session; } @@ -88,7 +84,23 @@ protected void doStop() throws Exception { super.doStop(); } - public void setPort(int port) { - this.port = port; + public byte[] getPollCommand() { + return pollCommand; + } + + public void setPollCommand(byte[] pollCommand) { + this.pollCommand = pollCommand; + } + + public SshConfiguration getConfiguration() { + if (configuration == null) { + configuration = new SshConfiguration(); + } + return configuration; } + + public void setConfiguration(SshConfiguration configuration) { + this.configuration = configuration; + } + } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java new file mode 100644 index 0000000000000..f77c5b9896309 --- /dev/null +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java @@ -0,0 +1,102 @@ +/** + * 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.ssh; + +import java.net.*; +import java.util.concurrent.CountDownLatch; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.sshd.SshServer; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; +import org.apache.sshd.server.Command; +import org.junit.Test; + +public class SshComponentConsumerTest extends CamelTestSupport { + + private SshServer sshd; + private int port; + + @Override + public void setUp() throws Exception { + ServerSocket s = new ServerSocket(0); + port = s.getLocalPort(); + s.close(); + + sshd = SshServer.setUpDefaultServer(); + sshd.setPort(port); + sshd.setKeyPairProvider(new FileKeyPairProvider(new String[]{"src/test/resources/hostkey.pem"})); + sshd.setShellFactory(new TestEchoShellFactory()); + sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator()); + sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator()); + sshd.start(); + + super.setUp(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + + if (sshd != null) { + sshd.stop(true); + Thread.sleep(50); + } + } + + @Test + public void testHelloWorld() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() { + from("ssh://smx:smx@localhost:" + port + "?useFixedDelay=true&delay=5000&pollCommand=test%0Dexit%0D") + .to("mock:result") + .to("log:foo?showAll=true"); + } + }; + } + + public static class TestEchoShellFactory extends EchoShellFactory { + @Override + public Command create() { + return new TestEchoShell(); + } + + public static class TestEchoShell extends EchoShell { + + public static CountDownLatch latch = new CountDownLatch(1); + + @Override + public void destroy() { + if (latch != null) { + latch.countDown(); + } + super.destroy(); + } + } + } + +} diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java similarity index 98% rename from components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java rename to components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index f239a82035be5..eeed599f0f2c5 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -27,7 +27,7 @@ import org.apache.sshd.server.Command; import org.junit.Test; -public class SshComponentTest extends CamelTestSupport { +public class SshComponentProducerTest extends CamelTestSupport { private SshServer sshd; private int port; From 4e4381254499719a5673477e1a717fb7a2dca6aa Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 29 Dec 2011 14:27:06 -0500 Subject: [PATCH 11/32] Updated to use AvailablePortFinder in unit tests --- .../camel/component/ssh/SshComponentConsumerTest.java | 5 ++--- .../camel/component/ssh/SshComponentProducerTest.java | 6 ++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java index f77c5b9896309..5f53fb1129613 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java @@ -21,6 +21,7 @@ import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.AvailablePortFinder; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.sshd.SshServer; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; @@ -34,9 +35,7 @@ public class SshComponentConsumerTest extends CamelTestSupport { @Override public void setUp() throws Exception { - ServerSocket s = new ServerSocket(0); - port = s.getLocalPort(); - s.close(); + port = AvailablePortFinder.getNextAvailable(22000); sshd = SshServer.setUpDefaultServer(); sshd.setPort(port); diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index eeed599f0f2c5..fac4c2708106a 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -16,11 +16,11 @@ */ package org.apache.camel.component.ssh; -import java.net.*; import java.util.concurrent.CountDownLatch; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.AvailablePortFinder; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.sshd.SshServer; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; @@ -34,9 +34,7 @@ public class SshComponentProducerTest extends CamelTestSupport { @Override public void setUp() throws Exception { - ServerSocket s = new ServerSocket(0); - port = s.getLocalPort(); - s.close(); + port = AvailablePortFinder.getNextAvailable(22000); sshd = SshServer.setUpDefaultServer(); sshd.setPort(port); From cea1d9120dfb219394174be57532f194992f6230 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 29 Dec 2011 14:48:00 -0500 Subject: [PATCH 12/32] Updated camel-example-ssh to use Polling SSH component --- .../resources/META-INF/spring/camelContext.xml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml b/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml index b91ed60765960..80f85ffbf4bdb 100644 --- a/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml +++ b/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml @@ -23,9 +23,19 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - - + + + + + + + + + osgi:list shell:logout From cf8dbed0e6367e7fb3b680e6d7c15e66d6bf48d7 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 29 Dec 2011 16:44:43 -0500 Subject: [PATCH 13/32] Changed to use CHANNEL_EXEC (versus CHANNEL_SHELL) as that better matches usage scenario (i.e. send a command and get a reply) --- .../camel/component/ssh/SshComponent.java | 1 - .../camel/component/ssh/SshConsumer.java | 24 +++++++++-------- .../camel/component/ssh/SshEndpoint.java | 8 +++--- .../camel/component/ssh/SshProducer.java | 26 +++++++------------ .../ssh/SshComponentConsumerTest.java | 11 +++----- .../ssh/SshComponentProducerTest.java | 6 ++--- .../META-INF/spring/camelContext.xml | 6 ++--- 7 files changed, 35 insertions(+), 47 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java index e2410e4b12829..21625c423b18c 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java @@ -26,7 +26,6 @@ * Represents the component that manages {@link SshEndpoint}. */ public class SshComponent extends DefaultComponent { - @Override protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { SshConfiguration config = new SshConfiguration(new URI(uri)); diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java index 9b67234639a71..84f57fc66b3ec 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java @@ -17,15 +17,12 @@ package org.apache.camel.component.ssh; import java.io.*; -import java.util.*; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.impl.ScheduledPollConsumer; import org.apache.sshd.ClientChannel; import org.apache.sshd.ClientSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class SshConsumer extends ScheduledPollConsumer { private final SshEndpoint endpoint; @@ -39,22 +36,27 @@ public SshConsumer(SshEndpoint endpoint, Processor processor) { protected int poll() throws Exception { ClientSession session = endpoint.createSession(); - ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL); + ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, endpoint.getPollCommand()); + + // TODO: do I need to put command into Channel IN for CHANNEL_EXEC? + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Writer w = new OutputStreamWriter(baos); + w.append(endpoint.getPollCommand()); + w.close(); + ByteArrayInputStream in = new ByteArrayInputStream(baos.toByteArray()); + channel.setIn(in); - PipedOutputStream pipedIn = new PipedOutputStream(); - channel.setIn(new PipedInputStream(pipedIn)); ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayOutputStream err = new ByteArrayOutputStream(); channel.setOut(out); + + ByteArrayOutputStream err = new ByteArrayOutputStream(); channel.setErr(err); - channel.open(); - pipedIn.write(endpoint.getPollCommand()); - pipedIn.flush(); + channel.open().await(); channel.waitFor(ClientChannel.CLOSED, 0); - channel.close(false); + session.close(false); Exchange exchange = endpoint.createExchange(); diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index 92959b63243c1..1f00772cdde56 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -27,10 +27,9 @@ * Represents an SSH endpoint. */ public class SshEndpoint extends ScheduledPollEndpoint { - private SshClient client; private SshConfiguration configuration; - private byte[] pollCommand; + private String pollCommand; public SshEndpoint() { } @@ -84,11 +83,11 @@ protected void doStop() throws Exception { super.doStop(); } - public byte[] getPollCommand() { + public String getPollCommand() { return pollCommand; } - public void setPollCommand(byte[] pollCommand) { + public void setPollCommand(String pollCommand) { this.pollCommand = pollCommand; } @@ -102,5 +101,4 @@ public SshConfiguration getConfiguration() { public void setConfiguration(SshConfiguration configuration) { this.configuration = configuration; } - } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java index 95f54624d5843..99b6ff267d9c4 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java @@ -22,15 +22,8 @@ import org.apache.camel.impl.DefaultProducer; import org.apache.sshd.ClientChannel; import org.apache.sshd.ClientSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -/** - * The HelloWorld producer. - */ public class SshProducer extends DefaultProducer { - private static final transient Logger LOG = LoggerFactory.getLogger(SshProducer.class); - private SshEndpoint endpoint; public SshProducer(SshEndpoint endpoint) { @@ -42,25 +35,26 @@ public SshProducer(SshEndpoint endpoint) { public void process(Exchange exchange) throws Exception { ClientSession session = endpoint.createSession(); - ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL); + String command = exchange.getIn().getBody(String.class); + ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, command); + + // TODO: do I need to put command into Channel IN for CHANNEL_EXEC? + ByteArrayInputStream in = new ByteArrayInputStream(exchange.getIn().getBody(byte[].class)); + channel.setIn(in); - PipedOutputStream pipedIn = new PipedOutputStream(); - channel.setIn(new PipedInputStream(pipedIn)); ByteArrayOutputStream out = new ByteArrayOutputStream(); - ByteArrayOutputStream err = new ByteArrayOutputStream(); channel.setOut(out); + + ByteArrayOutputStream err = new ByteArrayOutputStream(); channel.setErr(err); - channel.open(); - pipedIn.write(exchange.getIn().getBody(byte[].class)); - pipedIn.flush(); + channel.open().await(); channel.waitFor(ClientChannel.CLOSED, 0); - channel.close(false); + session.close(false); exchange.getOut().setBody(out.toByteArray()); } - } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java index 5f53fb1129613..688a3e7265c0e 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java @@ -16,7 +16,6 @@ */ package org.apache.camel.component.ssh; -import java.net.*; import java.util.concurrent.CountDownLatch; import org.apache.camel.builder.RouteBuilder; @@ -29,7 +28,6 @@ import org.junit.Test; public class SshComponentConsumerTest extends CamelTestSupport { - private SshServer sshd; private int port; @@ -59,7 +57,7 @@ public void tearDown() throws Exception { } @Test - public void testHelloWorld() throws Exception { + public void testPollingConsumer() throws Exception { MockEndpoint mock = getMockEndpoint("mock:result"); mock.expectedMinimumMessageCount(1); @@ -71,9 +69,9 @@ protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() { - from("ssh://smx:smx@localhost:" + port + "?useFixedDelay=true&delay=5000&pollCommand=test%0Dexit%0D") - .to("mock:result") - .to("log:foo?showAll=true"); + from("ssh://smx:smx@localhost:" + port + "?useFixedDelay=true&delay=5000&pollCommand=test%0D") + .to("mock:result") + .to("log:foo?showAll=true"); } }; } @@ -97,5 +95,4 @@ public void destroy() { } } } - } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index fac4c2708106a..ed323912d00f8 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -28,7 +28,6 @@ import org.junit.Test; public class SshComponentProducerTest extends CamelTestSupport { - private SshServer sshd; private int port; @@ -58,7 +57,7 @@ public void tearDown() throws Exception { } @Test - public void testHelloWorld() throws Exception { + public void testProducer() throws Exception { MockEndpoint mock = getMockEndpoint("mock:result"); mock.expectedMinimumMessageCount(1); @@ -71,7 +70,7 @@ protected RouteBuilder createRouteBuilder() throws Exception { @Override public void configure() { from("timer://foo?fixedRate=true&period=5000") - .setBody().constant("test\nexit\n") + .setBody().constant("test\n") .to("ssh://smx:smx@localhost:" + port) .to("mock:result") .to("log:foo?showAll=true"); @@ -98,5 +97,4 @@ public void destroy() { } } } - } diff --git a/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml b/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml index 80f85ffbf4bdb..fd75c686cd6f1 100644 --- a/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml +++ b/examples/camel-example-ssh/src/main/resources/META-INF/spring/camelContext.xml @@ -30,14 +30,14 @@ --> - + - + - osgi:list shell:logout + features:list From 7f84d118bfe11b0943f3e07bed6bca9c988ce807 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 30 Dec 2011 14:24:52 -0500 Subject: [PATCH 14/32] Upgraded to sshd-core:0.6.0 and mina-core:2.0.2 --- components/camel-ssh/pom.xml | 4 ++-- platforms/karaf/features/src/main/resources/features.xml | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/components/camel-ssh/pom.xml b/components/camel-ssh/pom.xml index db0849187359c..d41ce1e5d72f0 100644 --- a/components/camel-ssh/pom.xml +++ b/components/camel-ssh/pom.xml @@ -46,12 +46,12 @@ org.apache.mina mina-core - 2.0.1 + 2.0.2 org.apache.sshd sshd-core - 0.5.0 + 0.6.0 diff --git a/platforms/karaf/features/src/main/resources/features.xml b/platforms/karaf/features/src/main/resources/features.xml index 6176d8ad1dc5a..bc2fcdc396f6f 100644 --- a/platforms/karaf/features/src/main/resources/features.xml +++ b/platforms/karaf/features/src/main/resources/features.xml @@ -651,10 +651,11 @@ camel-core mvn:org.apache.camel/camel-sql/${project.version} - - camel-core - mvn:org.apache.mina/mina-core/2.0.1 - mvn:org.apache.camel/camel-ssh/${pom.version} + + camel-core + mvn:org.apache.mina/mina-core/2.0.2 + mvn:org.apache.sshd/sshd-core/0.6.0 + mvn:org.apache.camel/camel-ssh/${project.version} camel-core From be288f376fe06269e88fc10f96eac864c232caed Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 30 Dec 2011 14:26:20 -0500 Subject: [PATCH 15/32] Fixed configuring Polling consumer --- .../java/org/apache/camel/component/ssh/SshEndpoint.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index 1f00772cdde56..d2aafe99bb6a1 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -50,7 +50,11 @@ public Producer createProducer() throws Exception { @Override public Consumer createConsumer(Processor processor) throws Exception { - return new SshConsumer(this, processor); + SshConsumer consumer = new SshConsumer(this, processor); + + configureConsumer(consumer); + + return consumer; } @Override From cf2f033b35385088db7c9a4becd7b3bb7dc3ef19 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 30 Dec 2011 14:27:22 -0500 Subject: [PATCH 16/32] Consolidated SSH code into SshEndpoint --- .../camel/component/ssh/SshConsumer.java | 30 ++--------- .../camel/component/ssh/SshEndpoint.java | 52 +++++++++++++++---- .../camel/component/ssh/SshProducer.java | 23 +------- 3 files changed, 47 insertions(+), 58 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java index 84f57fc66b3ec..3fa84e14bfbba 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java @@ -34,35 +34,11 @@ public SshConsumer(SshEndpoint endpoint, Processor processor) { @Override protected int poll() throws Exception { - ClientSession session = endpoint.createSession(); - - ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, endpoint.getPollCommand()); - - // TODO: do I need to put command into Channel IN for CHANNEL_EXEC? - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Writer w = new OutputStreamWriter(baos); - w.append(endpoint.getPollCommand()); - w.close(); - ByteArrayInputStream in = new ByteArrayInputStream(baos.toByteArray()); - channel.setIn(in); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - channel.setOut(out); - - ByteArrayOutputStream err = new ByteArrayOutputStream(); - channel.setErr(err); - - channel.open().await(); - - channel.waitFor(ClientChannel.CLOSED, 0); - channel.close(false); - - session.close(false); + String command = endpoint.getPollCommand(); + byte[] result = endpoint.sendExecCommand(command); Exchange exchange = endpoint.createExchange(); - - // create a message body - exchange.getIn().setBody(out.toByteArray()); + exchange.getIn().setBody(result); try { // send message to next processor in the route diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index d2aafe99bb6a1..d4e4bf9f025f9 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -16,19 +16,27 @@ */ package org.apache.camel.component.ssh; +import java.io.*; + import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.impl.ScheduledPollEndpoint; +import org.apache.sshd.ClientChannel; import org.apache.sshd.ClientSession; import org.apache.sshd.SshClient; +import org.apache.sshd.client.future.OpenFuture; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Represents an SSH endpoint. */ public class SshEndpoint extends ScheduledPollEndpoint { + protected final transient Logger log = LoggerFactory.getLogger(getClass()); + private SshClient client; - private SshConfiguration configuration; + private SshConfiguration sshConfiguration; private String pollCommand; public SshEndpoint() { @@ -40,7 +48,7 @@ public SshEndpoint(String uri, SshComponent component) { public SshEndpoint(String uri, SshComponent component, SshConfiguration configuration) { super(uri, component); - this.configuration = configuration; + this.sshConfiguration = configuration; } @Override @@ -62,11 +70,35 @@ public boolean isSingleton() { return false; } - ClientSession createSession() throws Exception { - ClientSession session = client.connect(configuration.getHost(), configuration.getPort()).await().getSession(); - session.authPassword(configuration.getUsername(), configuration.getPassword()).await().isSuccess(); + public byte[] sendExecCommand(String command) throws Exception { + byte[] result = null; + + ClientSession session = client.connect(sshConfiguration.getHost(), sshConfiguration.getPort()).await().getSession(); + session.authPassword(sshConfiguration.getUsername(), sshConfiguration.getPassword()).await().isSuccess(); + + ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, command); + + ByteArrayInputStream in = new ByteArrayInputStream(new byte[]{0}); + channel.setIn(in); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + channel.setOut(out); + + ByteArrayOutputStream err = new ByteArrayOutputStream(); + channel.setErr(err); + + OpenFuture openFuture = channel.open().await(); + if (openFuture.isOpened()) { + int ret = channel.waitFor(ClientChannel.CLOSED, 0); + log.info("ret = " + ret); + + //session.close(false); + //session.waitFor(ClientSession.CLOSED, 0); + + result = out.toByteArray(); + } - return session; + return result; } @Override @@ -96,13 +128,13 @@ public void setPollCommand(String pollCommand) { } public SshConfiguration getConfiguration() { - if (configuration == null) { - configuration = new SshConfiguration(); + if (sshConfiguration == null) { + sshConfiguration = new SshConfiguration(); } - return configuration; + return sshConfiguration; } public void setConfiguration(SshConfiguration configuration) { - this.configuration = configuration; + this.sshConfiguration = configuration; } } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java index 99b6ff267d9c4..2c79088025255 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java @@ -33,28 +33,9 @@ public SshProducer(SshEndpoint endpoint) { @Override public void process(Exchange exchange) throws Exception { - ClientSession session = endpoint.createSession(); - String command = exchange.getIn().getBody(String.class); - ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, command); - - // TODO: do I need to put command into Channel IN for CHANNEL_EXEC? - ByteArrayInputStream in = new ByteArrayInputStream(exchange.getIn().getBody(byte[].class)); - channel.setIn(in); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - channel.setOut(out); - - ByteArrayOutputStream err = new ByteArrayOutputStream(); - channel.setErr(err); - - channel.open().await(); - - channel.waitFor(ClientChannel.CLOSED, 0); - channel.close(false); - - session.close(false); + byte[] result = endpoint.sendExecCommand(command); - exchange.getOut().setBody(out.toByteArray()); + exchange.getOut().setBody(result); } } From 39af09cd6042824b32745ed69f0892b30d8a36dc Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 30 Dec 2011 16:21:54 -0500 Subject: [PATCH 17/32] minor cleanup --- components/camel-ssh/pom.xml | 1 - .../main/java/org/apache/camel/component/ssh/SshConsumer.java | 4 ---- .../main/java/org/apache/camel/component/ssh/SshProducer.java | 4 ---- 3 files changed, 9 deletions(-) diff --git a/components/camel-ssh/pom.xml b/components/camel-ssh/pom.xml index d41ce1e5d72f0..e52a273ae1471 100644 --- a/components/camel-ssh/pom.xml +++ b/components/camel-ssh/pom.xml @@ -68,7 +68,6 @@ test - org.slf4j diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java index 3fa84e14bfbba..36dbc59a4e532 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConsumer.java @@ -16,13 +16,9 @@ */ package org.apache.camel.component.ssh; -import java.io.*; - import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.impl.ScheduledPollConsumer; -import org.apache.sshd.ClientChannel; -import org.apache.sshd.ClientSession; public class SshConsumer extends ScheduledPollConsumer { private final SshEndpoint endpoint; diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java index 2c79088025255..9dbfb536da3b2 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java @@ -16,12 +16,8 @@ */ package org.apache.camel.component.ssh; -import java.io.*; - import org.apache.camel.Exchange; import org.apache.camel.impl.DefaultProducer; -import org.apache.sshd.ClientChannel; -import org.apache.sshd.ClientSession; public class SshProducer extends DefaultProducer { private SshEndpoint endpoint; From 6bf1499ea26f7a76131e8aa52f54103b42deaea8 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 30 Dec 2011 17:39:00 -0500 Subject: [PATCH 18/32] Updated Camel-ssh unit tests to work (and test) correctly using CHANNEL_EXEC style ssh --- ...llFactory.java => EchoCommandFactory.java} | 31 ++++++++----------- .../ssh/SshComponentConsumerTest.java | 16 ++++++---- .../ssh/SshComponentProducerTest.java | 16 ++++++---- 3 files changed, 33 insertions(+), 30 deletions(-) rename components/camel-ssh/src/test/java/org/apache/camel/component/ssh/{EchoShellFactory.java => EchoCommandFactory.java} (75%) diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoCommandFactory.java similarity index 75% rename from components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java rename to components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoCommandFactory.java index b9436fe3a9226..5873365651855 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoShellFactory.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/EchoCommandFactory.java @@ -18,8 +18,8 @@ import java.io.*; -import org.apache.sshd.common.Factory; import org.apache.sshd.server.Command; +import org.apache.sshd.server.CommandFactory; import org.apache.sshd.server.Environment; import org.apache.sshd.server.ExitCallback; @@ -28,20 +28,25 @@ * * @author Apache MINA SSHD Project */ -public class EchoShellFactory implements Factory { +public class EchoCommandFactory implements CommandFactory { @Override - public Command create() { - return new EchoShell(); + public Command createCommand(String command) { + return new EchoCommand(command); } - protected static class EchoShell implements Command, Runnable { + protected static class EchoCommand implements Command, Runnable { + private String command; private InputStream in; private OutputStream out; private OutputStream err; private ExitCallback callback; private Thread thread; + public EchoCommand(String command) { + this.command = command; + } + @Override public void setInputStream(InputStream in) { this.in = in; @@ -64,7 +69,7 @@ public void setExitCallback(ExitCallback callback) { @Override public void start(Environment env) throws IOException { - thread = new Thread(this, "EchoShell"); + thread = new Thread(this, "EchoCommand"); thread.start(); } @@ -75,19 +80,9 @@ public void destroy() { @Override public void run() { - BufferedReader r = new BufferedReader(new InputStreamReader(in)); try { - while (true) { - String s = r.readLine(); - if (s == null) { - return; - } - out.write((s + "\n").getBytes()); - out.flush(); - if ("exit".equals(s)) { - return; - } - } + out.write(command.getBytes()); + out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java index 688a3e7265c0e..6219e05bab73e 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java @@ -38,7 +38,7 @@ public void setUp() throws Exception { sshd = SshServer.setUpDefaultServer(); sshd.setPort(port); sshd.setKeyPairProvider(new FileKeyPairProvider(new String[]{"src/test/resources/hostkey.pem"})); - sshd.setShellFactory(new TestEchoShellFactory()); + sshd.setCommandFactory(new TestEchoCommandFactory()); sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator()); sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator()); sshd.start(); @@ -60,6 +60,7 @@ public void tearDown() throws Exception { public void testPollingConsumer() throws Exception { MockEndpoint mock = getMockEndpoint("mock:result"); mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived(new Object[]{"test\r"}); assertMockEndpointsSatisfied(); } @@ -76,16 +77,19 @@ public void configure() { }; } - public static class TestEchoShellFactory extends EchoShellFactory { + public static class TestEchoCommandFactory extends EchoCommandFactory { @Override - public Command create() { - return new TestEchoShell(); + public Command createCommand(String command) { + return new TestEchoCommand(command); } - public static class TestEchoShell extends EchoShell { - + public static class TestEchoCommand extends EchoCommand { public static CountDownLatch latch = new CountDownLatch(1); + public TestEchoCommand(String command) { + super(command); + } + @Override public void destroy() { if (latch != null) { diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index ed323912d00f8..cd57f0bfbaa7c 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -38,7 +38,7 @@ public void setUp() throws Exception { sshd = SshServer.setUpDefaultServer(); sshd.setPort(port); sshd.setKeyPairProvider(new FileKeyPairProvider(new String[]{"src/test/resources/hostkey.pem"})); - sshd.setShellFactory(new TestEchoShellFactory()); + sshd.setCommandFactory(new TestEchoCommandFactory()); sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator()); sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator()); sshd.start(); @@ -60,6 +60,7 @@ public void tearDown() throws Exception { public void testProducer() throws Exception { MockEndpoint mock = getMockEndpoint("mock:result"); mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived(new Object[]{"test\n"}); assertMockEndpointsSatisfied(); } @@ -78,16 +79,19 @@ public void configure() { }; } - public static class TestEchoShellFactory extends EchoShellFactory { + public static class TestEchoCommandFactory extends EchoCommandFactory { @Override - public Command create() { - return new TestEchoShell(); + public Command createCommand(String command) { + return new TestEchoCommand(command); } - public static class TestEchoShell extends EchoShell { - + public static class TestEchoCommand extends EchoCommand { public static CountDownLatch latch = new CountDownLatch(1); + public TestEchoCommand(String command) { + super(command); + } + @Override public void destroy() { if (latch != null) { From 2f036bbda9c712761a1f1af88d9945ef1c0c5c02 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Wed, 4 Jan 2012 12:53:56 -0500 Subject: [PATCH 19/32] Added reconnect test --- .../ssh/SshComponentProducerTest.java | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index cd57f0bfbaa7c..833f244304479 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -58,9 +58,37 @@ public void tearDown() throws Exception { @Test public void testProducer() throws Exception { + final String msg = "test\n"; + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived(new Object[]{msg}); + + template.sendBody("direct:ssh", msg); + + assertMockEndpointsSatisfied(); + } + + @Test + public void testReconnect() throws Exception { + final String msg = "test\n"; + MockEndpoint mock = getMockEndpoint("mock:result"); mock.expectedMinimumMessageCount(1); - mock.expectedBodiesReceived(new Object[]{"test\n"}); + mock.expectedBodiesReceived(new Object[]{msg}); + + template.sendBody("direct:ssh", msg); + + assertMockEndpointsSatisfied(); + + sshd.stop(); + sshd.start(); + + mock.reset(); + mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived(new Object[]{msg}); + + template.sendBody("direct:ssh", msg); assertMockEndpointsSatisfied(); } @@ -70,11 +98,10 @@ protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() { - from("timer://foo?fixedRate=true&period=5000") - .setBody().constant("test\n") - .to("ssh://smx:smx@localhost:" + port) - .to("mock:result") - .to("log:foo?showAll=true"); + from("direct:ssh") + .to("ssh://smx:smx@localhost:" + port) + .to("mock:result") + .to("log:foo?showAll=true"); } }; } From 2e9c6949989c4cdd845ed46cc349b9c063551777 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Wed, 4 Jan 2012 16:18:56 -0500 Subject: [PATCH 20/32] Added SSH Key support using configuration approach similar to JmsComponent --- .../camel/component/ssh/SshComponent.java | 80 ++++++++++++++++- .../camel/component/ssh/SshConfiguration.java | 39 ++++++++- .../camel/component/ssh/SshEndpoint.java | 86 ++++++++++++++++--- .../ssh/SshComponentProducerTest.java | 36 +++++++- 4 files changed, 222 insertions(+), 19 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java index 21625c423b18c..6254abfe20026 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java @@ -21,18 +21,94 @@ import org.apache.camel.Endpoint; import org.apache.camel.impl.DefaultComponent; +import org.apache.sshd.common.KeyPairProvider; /** * Represents the component that manages {@link SshEndpoint}. */ public class SshComponent extends DefaultComponent { + private SshConfiguration configuration; + @Override protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { - SshConfiguration config = new SshConfiguration(new URI(uri)); + SshConfiguration newConfig; + + if (configuration == null) { + newConfig = new SshConfiguration(new URI(uri)); + } else { + newConfig = configuration.copy(); + } - SshEndpoint endpoint = new SshEndpoint(uri, this, config); + SshEndpoint endpoint = new SshEndpoint(uri, this, newConfig); setProperties(endpoint.getConfiguration(), parameters); setProperties(endpoint, parameters); return endpoint; } + + public SshConfiguration getConfiguration() { + if (configuration == null) { + configuration = new SshConfiguration(); + } + return configuration; + } + + public void setConfiguration(SshConfiguration configuration) { + this.configuration = configuration; + } + + public String getHost() { + return getConfiguration().getHost(); + } + + public void setHost(String host) { + getConfiguration().setHost(host); + } + + public int getPort() { + return getConfiguration().getPort(); + } + + public void setPort(int port) { + getConfiguration().setPort(port); + } + + public String getUsername() { + return getConfiguration().getUsername(); + } + + public void setUsername(String username) { + getConfiguration().setUsername(username); + } + + public String getPassword() { + return getConfiguration().getPassword(); + } + + public void setPassword(String password) { + getConfiguration().setPassword(password); + } + + public String getPollCommand() { + return getConfiguration().getPollCommand(); + } + + public void setPollCommand(String pollCommand) { + getConfiguration().setPollCommand(pollCommand); + } + + public KeyPairProvider getKeyPairProvider() { + return getConfiguration().getKeyPairProvider(); + } + + public void setKeyPairProvider(KeyPairProvider keyPairProvider) { + getConfiguration().setKeyPairProvider(keyPairProvider); + } + + public String getKeyType() { + return getConfiguration().getKeyType(); + } + + public void setKeyType(String keyType) { + getConfiguration().setKeyType(keyType); + } } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java index 1753735501cd9..21f5f98699fcb 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java @@ -18,15 +18,20 @@ import java.net.*; +import org.apache.camel.RuntimeCamelException; import org.apache.camel.util.ObjectHelper; +import org.apache.sshd.common.KeyPairProvider; -public class SshConfiguration { +public class SshConfiguration implements Cloneable { public static final int DEFAULT_SSH_PORT = 22; private String username; private String host; private int port; private String password; + private String pollCommand; + private KeyPairProvider keyPairProvider; + private String keyType; public SshConfiguration() { } @@ -66,6 +71,14 @@ public void configure(URI uri) { } } + public SshConfiguration copy() { + try { + return (SshConfiguration) clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeCamelException(e); + } + } + public String getUsername() { return username; } @@ -97,4 +110,28 @@ public String getPassword() { public void setPassword(String password) { this.password = password; } + + public String getPollCommand() { + return pollCommand; + } + + public void setPollCommand(String pollCommand) { + this.pollCommand = pollCommand; + } + + public KeyPairProvider getKeyPairProvider() { + return keyPairProvider; + } + + public void setKeyPairProvider(KeyPairProvider keyPairProvider) { + this.keyPairProvider = keyPairProvider; + } + + public String getKeyType() { + return keyType; + } + + public void setKeyType(String keyType) { + this.keyType = keyType; + } } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index d4e4bf9f025f9..332912b79500b 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -17,6 +17,7 @@ package org.apache.camel.component.ssh; import java.io.*; +import java.security.KeyPair; import org.apache.camel.Consumer; import org.apache.camel.Processor; @@ -25,7 +26,10 @@ import org.apache.sshd.ClientChannel; import org.apache.sshd.ClientSession; import org.apache.sshd.SshClient; +import org.apache.sshd.client.future.AuthFuture; import org.apache.sshd.client.future.OpenFuture; +import org.apache.sshd.common.KeyPairProvider; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +41,6 @@ public class SshEndpoint extends ScheduledPollEndpoint { private SshClient client; private SshConfiguration sshConfiguration; - private String pollCommand; public SshEndpoint() { } @@ -73,8 +76,22 @@ public boolean isSingleton() { public byte[] sendExecCommand(String command) throws Exception { byte[] result = null; - ClientSession session = client.connect(sshConfiguration.getHost(), sshConfiguration.getPort()).await().getSession(); - session.authPassword(sshConfiguration.getUsername(), sshConfiguration.getPassword()).await().isSuccess(); + ClientSession session = client.connect(getHost(), getPort()).await().getSession(); + + AuthFuture authResult; + + KeyPairProvider keyPairProvider = getKeyPairProvider(); + if (keyPairProvider != null) { + KeyPair pair = keyPairProvider.loadKey(getKeyType()); + authResult = session.authPublicKey(getUsername(), pair).await(); + } else { + authResult = session.authPassword(getUsername(), getPassword()).await(); + } + + if (authResult.isFailure()) { + log.error("Failed to authenticate"); + throw new Exception("Failed to successfully authenticate"); + } ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, command); @@ -119,22 +136,67 @@ protected void doStop() throws Exception { super.doStop(); } + public SshConfiguration getConfiguration() { + return sshConfiguration; + } + + public void setConfiguration(SshConfiguration configuration) { + this.sshConfiguration = configuration; + } + + public String getHost() { + return getConfiguration().getHost(); + } + + public void setHost(String host) { + getConfiguration().setHost(host); + } + + public int getPort() { + return getConfiguration().getPort(); + } + + public void setPort(int port) { + getConfiguration().setPort(port); + } + + public String getUsername() { + return getConfiguration().getUsername(); + } + + public void setUsername(String username) { + getConfiguration().setUsername(username); + } + + public String getPassword() { + return getConfiguration().getPassword(); + } + + public void setPassword(String password) { + getConfiguration().setPassword(password); + } + public String getPollCommand() { - return pollCommand; + return getConfiguration().getPollCommand(); } public void setPollCommand(String pollCommand) { - this.pollCommand = pollCommand; + getConfiguration().setPollCommand(pollCommand); } - public SshConfiguration getConfiguration() { - if (sshConfiguration == null) { - sshConfiguration = new SshConfiguration(); - } - return sshConfiguration; + public KeyPairProvider getKeyPairProvider() { + return getConfiguration().getKeyPairProvider(); } - public void setConfiguration(SshConfiguration configuration) { - this.sshConfiguration = configuration; + public void setKeyPairProvider(KeyPairProvider keyPairProvider) { + getConfiguration().setKeyPairProvider(keyPairProvider); + } + + public String getKeyType() { + return getConfiguration().getKeyType(); + } + + public void setKeyType(String keyType) { + getConfiguration().setKeyType(keyType); } } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index 833f244304479..cad15235d15f4 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -23,6 +23,7 @@ import org.apache.camel.test.AvailablePortFinder; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.sshd.SshServer; +import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.apache.sshd.server.Command; import org.junit.Test; @@ -60,7 +61,7 @@ public void tearDown() throws Exception { public void testProducer() throws Exception { final String msg = "test\n"; - MockEndpoint mock = getMockEndpoint("mock:result"); + MockEndpoint mock = getMockEndpoint("mock:password"); mock.expectedMinimumMessageCount(1); mock.expectedBodiesReceived(new Object[]{msg}); @@ -73,7 +74,7 @@ public void testProducer() throws Exception { public void testReconnect() throws Exception { final String msg = "test\n"; - MockEndpoint mock = getMockEndpoint("mock:result"); + MockEndpoint mock = getMockEndpoint("mock:password"); mock.expectedMinimumMessageCount(1); mock.expectedBodiesReceived(new Object[]{msg}); @@ -93,6 +94,19 @@ public void testReconnect() throws Exception { assertMockEndpointsSatisfied(); } + @Test + public void testRsa() throws Exception { + final String msg = "test\n"; + + MockEndpoint mock = getMockEndpoint("mock:rsa"); + mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived(new Object[]{msg}); + + template.sendBody("direct:ssh-rsa", msg); + + assertMockEndpointsSatisfied(); + } + @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @@ -100,8 +114,22 @@ protected RouteBuilder createRouteBuilder() throws Exception { public void configure() { from("direct:ssh") .to("ssh://smx:smx@localhost:" + port) - .to("mock:result") - .to("log:foo?showAll=true"); + .to("mock:password") + .to("log:password?showAll=true"); + + SshComponent sshComponent = new SshComponent(); + sshComponent.setHost("localhost"); + sshComponent.setPort(port); + sshComponent.setUsername("smx"); + sshComponent.setKeyPairProvider(new FileKeyPairProvider(new String[]{"src/test/resources/hostkey.pem"})); + sshComponent.setKeyType(KeyPairProvider.SSH_RSA); + + getContext().addComponent("ssh-rsa", sshComponent); + + from("direct:ssh-rsa") + .to("ssh-rsa:test") + .to("mock:rsa") + .to("log:rsa?showAll=true"); } }; } From c9d44b99a1342d940ab0e230e90a16d1b5351f6b Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 5 Jan 2012 12:07:54 -0500 Subject: [PATCH 21/32] Propagate Message headers in Producer --- .../apache/camel/component/ssh/SshProducer.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java index 9dbfb536da3b2..90f102bc5cd74 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java @@ -17,6 +17,7 @@ package org.apache.camel.component.ssh; import org.apache.camel.Exchange; +import org.apache.camel.Message; import org.apache.camel.impl.DefaultProducer; public class SshProducer extends DefaultProducer { @@ -29,9 +30,16 @@ public SshProducer(SshEndpoint endpoint) { @Override public void process(Exchange exchange) throws Exception { - String command = exchange.getIn().getBody(String.class); + final Message in = exchange.getIn(); + final Message out = exchange.getOut(); + + String command = in.getBody(String.class); byte[] result = endpoint.sendExecCommand(command); - exchange.getOut().setBody(result); + out.setBody(result); + + // propagate headers and attachments + out.getHeaders().putAll(in.getHeaders()); + out.setAttachments(in.getAttachments()); } -} +} \ No newline at end of file From 4554ef72e8d0b038f88d359d72bd448d540561b3 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Thu, 5 Jan 2012 17:07:15 -0500 Subject: [PATCH 22/32] Added connection timeout parameter and unit test --- .../camel/component/ssh/SshComponent.java | 8 ++++ .../camel/component/ssh/SshConfiguration.java | 19 ++++---- .../camel/component/ssh/SshEndpoint.java | 44 +++++++++++++++---- .../camel/component/ssh/SshProducer.java | 10 ++++- .../ssh/SshComponentProducerTest.java | 31 +++++++++++-- 5 files changed, 90 insertions(+), 22 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java index 6254abfe20026..ed8b66af4c555 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java @@ -111,4 +111,12 @@ public String getKeyType() { public void setKeyType(String keyType) { getConfiguration().setKeyType(keyType); } + + public long getTimeout() { + return getConfiguration().getTimeout(); + } + + public void setTimeout(long timeout) { + getConfiguration().setTimeout(timeout); + } } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java index 21f5f98699fcb..bea394f83632a 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java @@ -22,16 +22,17 @@ import org.apache.camel.util.ObjectHelper; import org.apache.sshd.common.KeyPairProvider; -public class SshConfiguration implements Cloneable { +public class SshConfiguration implements Cloneable { public static final int DEFAULT_SSH_PORT = 22; private String username; private String host; - private int port; + private int port = DEFAULT_SSH_PORT; private String password; private String pollCommand; private KeyPairProvider keyPairProvider; private String keyType; + private long timeout = 30000; public SshConfiguration() { } @@ -40,13 +41,7 @@ public SshConfiguration(URI uri) { configure(uri); } - protected void setDefaultPort() { - setPort(DEFAULT_SSH_PORT); - } - public void configure(URI uri) { - setDefaultPort(); - // UserInfo can contain both username and password as: user:pwd@sshserver // see: http://en.wikipedia.org/wiki/URI_scheme String username = uri.getUserInfo(); @@ -134,4 +129,12 @@ public String getKeyType() { public void setKeyType(String keyType) { this.keyType = keyType; } + + public long getTimeout() { + return timeout; + } + + public void setTimeout(long timeout) { + this.timeout = timeout; + } } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index 332912b79500b..758b5b3137e23 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -27,9 +27,9 @@ import org.apache.sshd.ClientSession; import org.apache.sshd.SshClient; import org.apache.sshd.client.future.AuthFuture; +import org.apache.sshd.client.future.ConnectFuture; import org.apache.sshd.client.future.OpenFuture; import org.apache.sshd.common.KeyPairProvider; -import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -76,20 +76,36 @@ public boolean isSingleton() { public byte[] sendExecCommand(String command) throws Exception { byte[] result = null; - ClientSession session = client.connect(getHost(), getPort()).await().getSession(); + final ConnectFuture connectFuture = client.connect(getHost(), getPort()); + + connectFuture.await(getTimeout()); + + if (!connectFuture.isDone() || !connectFuture.isConnected()) { + final String msg = "Failed to connect to " + getHost() + ":" + getPort() + " within timeout " + getTimeout() + "ms"; + log.debug(msg); + throw new Exception(msg); + } + + log.debug("Connected to " + getHost() + ":" + getPort()); + + ClientSession session = connectFuture.getSession(); AuthFuture authResult; KeyPairProvider keyPairProvider = getKeyPairProvider(); if (keyPairProvider != null) { + log.debug("Attempting to authenticate username " + getUsername() + " using Key..."); KeyPair pair = keyPairProvider.loadKey(getKeyType()); - authResult = session.authPublicKey(getUsername(), pair).await(); + authResult = session.authPublicKey(getUsername(), pair); } else { - authResult = session.authPassword(getUsername(), getPassword()).await(); + log.debug("Attempting to authenticate username " + getUsername() + " using Password..."); + authResult = session.authPassword(getUsername(), getPassword()); } - if (authResult.isFailure()) { - log.error("Failed to authenticate"); + authResult.await(getTimeout()); + + if (!authResult.isDone() || authResult.isFailure()) { + log.debug("Failed to successfully authenticate"); throw new Exception("Failed to successfully authenticate"); } @@ -104,10 +120,12 @@ public byte[] sendExecCommand(String command) throws Exception { ByteArrayOutputStream err = new ByteArrayOutputStream(); channel.setErr(err); - OpenFuture openFuture = channel.open().await(); + OpenFuture openFuture = channel.open(); + + openFuture.await(getTimeout()); + if (openFuture.isOpened()) { - int ret = channel.waitFor(ClientChannel.CLOSED, 0); - log.info("ret = " + ret); + channel.waitFor(ClientChannel.CLOSED, 0); //session.close(false); //session.waitFor(ClientSession.CLOSED, 0); @@ -199,4 +217,12 @@ public String getKeyType() { public void setKeyType(String keyType) { getConfiguration().setKeyType(keyType); } + + public long getTimeout() { + return getConfiguration().getTimeout(); + } + + public void setTimeout(long timeout) { + getConfiguration().setTimeout(timeout); + } } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java index 90f102bc5cd74..2edc73a04a1b4 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshProducer.java @@ -16,6 +16,7 @@ */ package org.apache.camel.component.ssh; +import org.apache.camel.CamelExchangeException; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.impl.DefaultProducer; @@ -34,9 +35,14 @@ public void process(Exchange exchange) throws Exception { final Message out = exchange.getOut(); String command = in.getBody(String.class); - byte[] result = endpoint.sendExecCommand(command); - out.setBody(result); + try { + byte[] result = endpoint.sendExecCommand(command); + + out.setBody(result); + } catch (Exception e) { + throw new CamelExchangeException(e.getMessage(), exchange, e); + } // propagate headers and attachments out.getHeaders().putAll(in.getHeaders()); diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index cad15235d15f4..7f702521a4ed8 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -107,15 +107,40 @@ public void testRsa() throws Exception { assertMockEndpointsSatisfied(); } + @Test + public void testConnectionTimeout() throws Exception { + final String msg = "test\n"; + + MockEndpoint mock = getMockEndpoint("mock:password"); + mock.expectedMinimumMessageCount(0); + + MockEndpoint mockError = getMockEndpoint("mock:error"); + mockError.expectedMinimumMessageCount(1); + + sshd.stop(); + sshd = null; + + template.sendBody("direct:ssh", msg); + + Thread.sleep(4000); + + assertMockEndpointsSatisfied(); + } + @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() { + onException(Exception.class) + .handled(true) + .to("mock:error") + .to("log:error?showAll=true"); + from("direct:ssh") - .to("ssh://smx:smx@localhost:" + port) - .to("mock:password") - .to("log:password?showAll=true"); + .to("ssh://smx:smx@localhost:" + port + "?timeout=3000") + .to("mock:password") + .to("log:password?showAll=true"); SshComponent sshComponent = new SshComponent(); sshComponent.setHost("localhost"); From 8d23710a5c26afcf02b3bf7bc21e24d355cda43b Mon Sep 17 00:00:00 2001 From: Jason Whaley Date: Fri, 6 Jan 2012 10:19:36 -0500 Subject: [PATCH 23/32] added support for retries and reconnection delays --- .../camel/component/ssh/SshConfiguration.java | 18 +++++++ .../camel/component/ssh/SshEndpoint.java | 53 +++++++++++++------ .../ssh/SshComponentProducerTest.java | 34 +++++++++++- 3 files changed, 89 insertions(+), 16 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java index bea394f83632a..2efc269f0797d 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java @@ -33,6 +33,8 @@ public class SshConfiguration implements Cloneable { private KeyPairProvider keyPairProvider; private String keyType; private long timeout = 30000; + private int maximumReconnectAttempts; + private long reconnectDelay = 1000; public SshConfiguration() { } @@ -137,4 +139,20 @@ public long getTimeout() { public void setTimeout(long timeout) { this.timeout = timeout; } + + public int getMaximumReconnectAttempts() { + return maximumReconnectAttempts; + } + + public void setMaximumReconnectAttempts(int maximumReconnectAttempts) { + this.maximumReconnectAttempts = (maximumReconnectAttempts < 0) ? 0 : maximumReconnectAttempts; + } + + public long getReconnectDelay() { + return reconnectDelay; + } + + public void setReconnectDelay(long reconnectDelay) { + this.reconnectDelay = (reconnectDelay < 0) ? 0 : reconnectDelay; + } } diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index 758b5b3137e23..7b62d8baa52b1 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -76,14 +76,20 @@ public boolean isSingleton() { public byte[] sendExecCommand(String command) throws Exception { byte[] result = null; - final ConnectFuture connectFuture = client.connect(getHost(), getPort()); - + ConnectFuture connectFuture = client.connect(getHost(), getPort()); + int numberOfConnectRetriesRemaining = getConfiguration().getMaximumReconnectAttempts(); connectFuture.await(getTimeout()); - - if (!connectFuture.isDone() || !connectFuture.isConnected()) { - final String msg = "Failed to connect to " + getHost() + ":" + getPort() + " within timeout " + getTimeout() + "ms"; - log.debug(msg); - throw new Exception(msg); + while (!connectFuture.isDone() || !connectFuture.isConnected()) { + if (numberOfConnectRetriesRemaining == 0) { + final String msg = "Failed to connect to " + getHost() + ":" + getPort() + " within timeout " + getTimeout() + "ms"; + log.debug(msg); + throw new Exception(msg); + } + log.info("Connection attempt failed. Retrying"); + numberOfConnectRetriesRemaining--; + Thread.sleep(getReconnectDelay()); + connectFuture = client.connect(getHost(), getPort()); + connectFuture.await(getTimeout()); } log.debug("Connected to " + getHost() + ":" + getPort()); @@ -102,11 +108,16 @@ public byte[] sendExecCommand(String command) throws Exception { authResult = session.authPassword(getUsername(), getPassword()); } - authResult.await(getTimeout()); - if (!authResult.isDone() || authResult.isFailure()) { - log.debug("Failed to successfully authenticate"); - throw new Exception("Failed to successfully authenticate"); + int numberOfAuthRetriesRemaining = getConfiguration().getMaximumReconnectAttempts(); + authResult.await(getTimeout()); + while (!authResult.isDone() || authResult.isFailure()) { + if (numberOfAuthRetriesRemaining == 0) { + log.debug("Failed to successfully authenticate"); + throw new Exception("Failed to successfully authenticate"); + } + authResult.await(getTimeout()); + numberOfAuthRetriesRemaining--; } ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, command); @@ -126,10 +137,6 @@ public byte[] sendExecCommand(String command) throws Exception { if (openFuture.isOpened()) { channel.waitFor(ClientChannel.CLOSED, 0); - - //session.close(false); - //session.waitFor(ClientSession.CLOSED, 0); - result = out.toByteArray(); } @@ -225,4 +232,20 @@ public long getTimeout() { public void setTimeout(long timeout) { getConfiguration().setTimeout(timeout); } + + public int getMaximumReconnectAttempts() { + return getConfiguration().getMaximumReconnectAttempts(); + } + + public void setMaximumReconnectAttempts(int maximumReconnectAttempts) { + getConfiguration().setMaximumReconnectAttempts(maximumReconnectAttempts); + } + + public long getReconnectDelay() { + return getConfiguration().getReconnectDelay(); + } + + public void setReconnectDelay(long reconnectDelay) { + getConfiguration().setReconnectDelay(reconnectDelay); + } } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index 7f702521a4ed8..3020a39da6269 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -127,6 +127,38 @@ public void testConnectionTimeout() throws Exception { assertMockEndpointsSatisfied(); } + + @Test + public void testRetry() throws Exception { + final String msg = "test\n"; + + MockEndpoint mock = getMockEndpoint("mock:password"); + mock.expectedMinimumMessageCount(1); + + MockEndpoint mockError = getMockEndpoint("mock:error"); + mockError.expectedMinimumMessageCount(0); + + new Thread(new Runnable() { + @Override + public void run() { + try { + sshd.stop(true); + Thread.sleep(1000); + sshd.start(); + log.info("sshd started"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }).start(); + + template.sendBody("direct:ssh", msg); + + Thread.sleep(4000); + + assertMockEndpointsSatisfied(); + } + @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @@ -138,7 +170,7 @@ public void configure() { .to("log:error?showAll=true"); from("direct:ssh") - .to("ssh://smx:smx@localhost:" + port + "?timeout=3000") + .to("ssh://smx:smx@localhost:" + port + "?timeout=5000&maximumReconnectAttempts=3") .to("mock:password") .to("log:password?showAll=true"); From 7d3b34a1b87ed1224dff9af1e546d4e1998c1b7b Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 6 Jan 2012 12:59:44 -0500 Subject: [PATCH 24/32] minor code cleanup --- .../org/apache/camel/component/ssh/SshEndpoint.java | 13 ++++++++----- .../component/ssh/SshComponentProducerTest.java | 9 ++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index 7b62d8baa52b1..f443de15f36d7 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -77,22 +77,25 @@ public byte[] sendExecCommand(String command) throws Exception { byte[] result = null; ConnectFuture connectFuture = client.connect(getHost(), getPort()); - int numberOfConnectRetriesRemaining = getConfiguration().getMaximumReconnectAttempts(); + + // Wait getTimeout milliseconds for connect operation to complete connectFuture.await(getTimeout()); + + int numberOfConnectRetriesRemaining = getConfiguration().getMaximumReconnectAttempts(); while (!connectFuture.isDone() || !connectFuture.isConnected()) { if (numberOfConnectRetriesRemaining == 0) { final String msg = "Failed to connect to " + getHost() + ":" + getPort() + " within timeout " + getTimeout() + "ms"; log.debug(msg); throw new Exception(msg); } - log.info("Connection attempt failed. Retrying"); + log.info("Connection attempt failed. Retrying"); numberOfConnectRetriesRemaining--; Thread.sleep(getReconnectDelay()); connectFuture = client.connect(getHost(), getPort()); connectFuture.await(getTimeout()); } - log.debug("Connected to " + getHost() + ":" + getPort()); + log.debug("Connected to {}:{}", getHost(), getPort()); ClientSession session = connectFuture.getSession(); @@ -100,11 +103,11 @@ public byte[] sendExecCommand(String command) throws Exception { KeyPairProvider keyPairProvider = getKeyPairProvider(); if (keyPairProvider != null) { - log.debug("Attempting to authenticate username " + getUsername() + " using Key..."); + log.debug("Attempting to authenticate username '{}' using Key...", getUsername()); KeyPair pair = keyPairProvider.loadKey(getKeyType()); authResult = session.authPublicKey(getUsername(), pair); } else { - log.debug("Attempting to authenticate username " + getUsername() + " using Password..."); + log.debug("Attempting to authenticate username '{}' using Password...", getUsername()); authResult = session.authPassword(getUsername(), getPassword()); } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index 3020a39da6269..ce07ffca54294 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -63,7 +63,7 @@ public void testProducer() throws Exception { MockEndpoint mock = getMockEndpoint("mock:password"); mock.expectedMinimumMessageCount(1); - mock.expectedBodiesReceived(new Object[]{msg}); + mock.expectedBodiesReceived(msg); template.sendBody("direct:ssh", msg); @@ -76,7 +76,7 @@ public void testReconnect() throws Exception { MockEndpoint mock = getMockEndpoint("mock:password"); mock.expectedMinimumMessageCount(1); - mock.expectedBodiesReceived(new Object[]{msg}); + mock.expectedBodiesReceived(msg); template.sendBody("direct:ssh", msg); @@ -87,7 +87,7 @@ public void testReconnect() throws Exception { mock.reset(); mock.expectedMinimumMessageCount(1); - mock.expectedBodiesReceived(new Object[]{msg}); + mock.expectedBodiesReceived(msg); template.sendBody("direct:ssh", msg); @@ -100,7 +100,7 @@ public void testRsa() throws Exception { MockEndpoint mock = getMockEndpoint("mock:rsa"); mock.expectedMinimumMessageCount(1); - mock.expectedBodiesReceived(new Object[]{msg}); + mock.expectedBodiesReceived(msg); template.sendBody("direct:ssh-rsa", msg); @@ -127,7 +127,6 @@ public void testConnectionTimeout() throws Exception { assertMockEndpointsSatisfied(); } - @Test public void testRetry() throws Exception { final String msg = "test\n"; From 6968b4d85370f935348b422414d9449ab1a1bc83 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 6 Jan 2012 13:00:26 -0500 Subject: [PATCH 25/32] added maximumReconnectAttempts and reconnectDelay parameters for component configuration --- .../apache/camel/component/ssh/SshComponent.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java index ed8b66af4c555..d66ebef7389f2 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java @@ -119,4 +119,20 @@ public long getTimeout() { public void setTimeout(long timeout) { getConfiguration().setTimeout(timeout); } + + public int getMaximumReconnectAttempts() { + return getConfiguration().getMaximumReconnectAttempts(); + } + + public void setMaximumReconnectAttempts(int maximumReconnectAttempts) { + getConfiguration().setMaximumReconnectAttempts(maximumReconnectAttempts); + } + + public long getReconnectDelay() { + return getConfiguration().getReconnectDelay(); + } + + public void setReconnectDelay(long reconnectDelay) { + getConfiguration().setReconnectDelay(reconnectDelay); + } } From 9d39e40c6728d093c1b7804045a973ac459258c4 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 6 Jan 2012 13:44:51 -0500 Subject: [PATCH 26/32] more cleanup --- .../camel/component/ssh/SshEndpoint.java | 24 +++++++++---------- .../ssh/SshComponentProducerTest.java | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java index f443de15f36d7..255477b28a6de 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshEndpoint.java @@ -76,12 +76,16 @@ public boolean isSingleton() { public byte[] sendExecCommand(String command) throws Exception { byte[] result = null; + if (getConfiguration() == null) { + throw new IllegalStateException("configuration must be set"); + } + ConnectFuture connectFuture = client.connect(getHost(), getPort()); // Wait getTimeout milliseconds for connect operation to complete connectFuture.await(getTimeout()); - int numberOfConnectRetriesRemaining = getConfiguration().getMaximumReconnectAttempts(); + int numberOfConnectRetriesRemaining = getMaximumReconnectAttempts(); while (!connectFuture.isDone() || !connectFuture.isConnected()) { if (numberOfConnectRetriesRemaining == 0) { final String msg = "Failed to connect to " + getHost() + ":" + getPort() + " within timeout " + getTimeout() + "ms"; @@ -97,11 +101,10 @@ public byte[] sendExecCommand(String command) throws Exception { log.debug("Connected to {}:{}", getHost(), getPort()); - ClientSession session = connectFuture.getSession(); - AuthFuture authResult; + ClientSession session = connectFuture.getSession(); - KeyPairProvider keyPairProvider = getKeyPairProvider(); + final KeyPairProvider keyPairProvider = getKeyPairProvider(); if (keyPairProvider != null) { log.debug("Attempting to authenticate username '{}' using Key...", getUsername()); KeyPair pair = keyPairProvider.loadKey(getKeyType()); @@ -111,16 +114,11 @@ public byte[] sendExecCommand(String command) throws Exception { authResult = session.authPassword(getUsername(), getPassword()); } - - int numberOfAuthRetriesRemaining = getConfiguration().getMaximumReconnectAttempts(); authResult.await(getTimeout()); - while (!authResult.isDone() || authResult.isFailure()) { - if (numberOfAuthRetriesRemaining == 0) { - log.debug("Failed to successfully authenticate"); - throw new Exception("Failed to successfully authenticate"); - } - authResult.await(getTimeout()); - numberOfAuthRetriesRemaining--; + + if (!authResult.isDone() || authResult.isFailure()) { + log.debug("Failed to successfully authenticate"); + throw new Exception("Failed to successfully authenticate"); } ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, command); diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index ce07ffca54294..f9d211c746c2e 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -169,7 +169,7 @@ public void configure() { .to("log:error?showAll=true"); from("direct:ssh") - .to("ssh://smx:smx@localhost:" + port + "?timeout=5000&maximumReconnectAttempts=3") + .to("ssh://smx:smx@localhost:" + port + "?timeout=3000&maximumReconnectAttempts=3") .to("mock:password") .to("log:password?showAll=true"); From 49554b8d75b831c4fc210b19135c70f3f7e67959 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 6 Jan 2012 16:04:40 -0500 Subject: [PATCH 27/32] Refactored unit tests and added Redelivery test --- .../ssh/SshComponentConsumerTest.java | 58 +------------ .../ssh/SshComponentErrorHandlingTest.java | 84 ++++++++++++++++++ .../ssh/SshComponentProducerTest.java | 87 +------------------ .../ssh/SshComponentTestSupport.java | 52 +++++++++++ .../component/ssh/TestEchoCommandFactory.java | 45 ++++++++++ 5 files changed, 184 insertions(+), 142 deletions(-) create mode 100644 components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentErrorHandlingTest.java create mode 100644 components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTestSupport.java create mode 100644 components/camel-ssh/src/test/java/org/apache/camel/component/ssh/TestEchoCommandFactory.java diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java index 6219e05bab73e..c772eb93e9b16 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java @@ -16,51 +16,20 @@ */ package org.apache.camel.component.ssh; -import java.util.concurrent.CountDownLatch; - import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.AvailablePortFinder; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.sshd.SshServer; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; -import org.apache.sshd.server.Command; import org.junit.Test; -public class SshComponentConsumerTest extends CamelTestSupport { - private SshServer sshd; - private int port; - - @Override - public void setUp() throws Exception { - port = AvailablePortFinder.getNextAvailable(22000); - - sshd = SshServer.setUpDefaultServer(); - sshd.setPort(port); - sshd.setKeyPairProvider(new FileKeyPairProvider(new String[]{"src/test/resources/hostkey.pem"})); - sshd.setCommandFactory(new TestEchoCommandFactory()); - sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator()); - sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator()); - sshd.start(); - - super.setUp(); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - - if (sshd != null) { - sshd.stop(true); - Thread.sleep(50); - } - } - +public class SshComponentConsumerTest extends SshComponentTestSupport { @Test public void testPollingConsumer() throws Exception { MockEndpoint mock = getMockEndpoint("mock:result"); mock.expectedMinimumMessageCount(1); - mock.expectedBodiesReceived(new Object[]{"test\r"}); + mock.expectedBodiesReceived("test\r"); assertMockEndpointsSatisfied(); } @@ -76,27 +45,4 @@ public void configure() { } }; } - - public static class TestEchoCommandFactory extends EchoCommandFactory { - @Override - public Command createCommand(String command) { - return new TestEchoCommand(command); - } - - public static class TestEchoCommand extends EchoCommand { - public static CountDownLatch latch = new CountDownLatch(1); - - public TestEchoCommand(String command) { - super(command); - } - - @Override - public void destroy() { - if (latch != null) { - latch.countDown(); - } - super.destroy(); - } - } - } } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentErrorHandlingTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentErrorHandlingTest.java new file mode 100644 index 0000000000000..3852215c725a0 --- /dev/null +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentErrorHandlingTest.java @@ -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.ssh; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.AvailablePortFinder; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.sshd.SshServer; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; +import org.junit.Test; + +public class SshComponentErrorHandlingTest extends SshComponentTestSupport { + @Test + public void testRedelivery() throws Exception { + final String msg = "test\n"; + + MockEndpoint mockError = getMockEndpoint("mock:error"); + mockError.expectedMinimumMessageCount(0); + + MockEndpoint mock = getMockEndpoint("mock:success"); + mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived(msg); + mock.expectedHeaderReceived(Exchange.REDELIVERED, true); + + sshd.stop(); + + template.sendBody("direct:redeliver", msg); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() { + errorHandler(deadLetterChannel("mock:error") + .maximumRedeliveries(3) + .redeliveryDelay(0L) // speedup unit test by not waiting between redeliveries + .onRedelivery(new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + final Message in = exchange.getIn(); + final int count = in.getHeader(Exchange.REDELIVERY_COUNTER, Integer.class); + final int maxCount = in.getHeader(Exchange.REDELIVERY_MAX_COUNTER, Integer.class); + + log.info("Redelivery count = {}", count); + + // Restart the sshd server before the last redelivery attempt + if (count >= (maxCount - 1)) { + if (sshd != null) { + sshd.start(); + log.info("Restarting SSHD"); + } + } + } + })); + + from("direct:redeliver") + .tracing() + .to("ssh://smx:smx@localhost:" + port) + .to("mock:success"); + } + }; + } +} diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index f9d211c746c2e..3fe2041ff1263 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -16,8 +16,6 @@ */ package org.apache.camel.component.ssh; -import java.util.concurrent.CountDownLatch; - import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.AvailablePortFinder; @@ -25,38 +23,9 @@ import org.apache.sshd.SshServer; import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; -import org.apache.sshd.server.Command; import org.junit.Test; -public class SshComponentProducerTest extends CamelTestSupport { - private SshServer sshd; - private int port; - - @Override - public void setUp() throws Exception { - port = AvailablePortFinder.getNextAvailable(22000); - - sshd = SshServer.setUpDefaultServer(); - sshd.setPort(port); - sshd.setKeyPairProvider(new FileKeyPairProvider(new String[]{"src/test/resources/hostkey.pem"})); - sshd.setCommandFactory(new TestEchoCommandFactory()); - sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator()); - sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator()); - sshd.start(); - - super.setUp(); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - - if (sshd != null) { - sshd.stop(true); - Thread.sleep(50); - } - } - +public class SshComponentProducerTest extends SshComponentTestSupport { @Test public void testProducer() throws Exception { final String msg = "test\n"; @@ -127,37 +96,6 @@ public void testConnectionTimeout() throws Exception { assertMockEndpointsSatisfied(); } - @Test - public void testRetry() throws Exception { - final String msg = "test\n"; - - MockEndpoint mock = getMockEndpoint("mock:password"); - mock.expectedMinimumMessageCount(1); - - MockEndpoint mockError = getMockEndpoint("mock:error"); - mockError.expectedMinimumMessageCount(0); - - new Thread(new Runnable() { - @Override - public void run() { - try { - sshd.stop(true); - Thread.sleep(1000); - sshd.start(); - log.info("sshd started"); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - }).start(); - - template.sendBody("direct:ssh", msg); - - Thread.sleep(4000); - - assertMockEndpointsSatisfied(); - } - @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @@ -189,27 +127,4 @@ public void configure() { } }; } - - public static class TestEchoCommandFactory extends EchoCommandFactory { - @Override - public Command createCommand(String command) { - return new TestEchoCommand(command); - } - - public static class TestEchoCommand extends EchoCommand { - public static CountDownLatch latch = new CountDownLatch(1); - - public TestEchoCommand(String command) { - super(command); - } - - @Override - public void destroy() { - if (latch != null) { - latch.countDown(); - } - super.destroy(); - } - } - } } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTestSupport.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTestSupport.java new file mode 100644 index 0000000000000..3a2eb1ddcdd3d --- /dev/null +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTestSupport.java @@ -0,0 +1,52 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.ssh; + +import org.apache.camel.test.AvailablePortFinder; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.sshd.SshServer; +import org.apache.sshd.common.keyprovider.FileKeyPairProvider; + +public class SshComponentTestSupport extends CamelTestSupport { + protected SshServer sshd; + protected int port; + + @Override + public void setUp() throws Exception { + port = AvailablePortFinder.getNextAvailable(22000); + + sshd = SshServer.setUpDefaultServer(); + sshd.setPort(port); + sshd.setKeyPairProvider(new FileKeyPairProvider(new String[]{"src/test/resources/hostkey.pem"})); + sshd.setCommandFactory(new TestEchoCommandFactory()); + sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator()); + sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator()); + sshd.start(); + + super.setUp(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + + if (sshd != null) { + sshd.stop(true); + Thread.sleep(50); + } + } +} diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/TestEchoCommandFactory.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/TestEchoCommandFactory.java new file mode 100644 index 0000000000000..f412502fcb1ea --- /dev/null +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/TestEchoCommandFactory.java @@ -0,0 +1,45 @@ +/** + * 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.ssh; + +import java.util.concurrent.CountDownLatch; + +import org.apache.sshd.server.Command; + +public class TestEchoCommandFactory extends EchoCommandFactory { + @Override + public Command createCommand(String command) { + return new TestEchoCommand(command); + } + + public static class TestEchoCommand extends EchoCommand { + public static CountDownLatch latch = new CountDownLatch(1); + + public TestEchoCommand(String command) { + super(command); + } + + @Override + public void destroy() { + if (latch != null) { + latch.countDown(); + } + super.destroy(); + } + } +} \ No newline at end of file From b0a82acb39adb60173c260c3828eb01e30717f7d Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 6 Jan 2012 16:12:39 -0500 Subject: [PATCH 28/32] Reduced logging in unit tests to reduce noise --- .../component/ssh/SshComponentConsumerTest.java | 3 +-- .../component/ssh/SshComponentProducerTest.java | 13 ++++--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java index c772eb93e9b16..c1c4527bb026a 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java @@ -40,8 +40,7 @@ protected RouteBuilder createRouteBuilder() throws Exception { @Override public void configure() { from("ssh://smx:smx@localhost:" + port + "?useFixedDelay=true&delay=5000&pollCommand=test%0D") - .to("mock:result") - .to("log:foo?showAll=true"); + .to("mock:result"); } }; } diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index 3fe2041ff1263..ff3b0845875e3 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -91,8 +91,6 @@ public void testConnectionTimeout() throws Exception { template.sendBody("direct:ssh", msg); - Thread.sleep(4000); - assertMockEndpointsSatisfied(); } @@ -103,13 +101,11 @@ protected RouteBuilder createRouteBuilder() throws Exception { public void configure() { onException(Exception.class) .handled(true) - .to("mock:error") - .to("log:error?showAll=true"); + .to("mock:error"); from("direct:ssh") - .to("ssh://smx:smx@localhost:" + port + "?timeout=3000&maximumReconnectAttempts=3") - .to("mock:password") - .to("log:password?showAll=true"); + .to("ssh://smx:smx@localhost:" + port + "?timeout=3000") + .to("mock:password"); SshComponent sshComponent = new SshComponent(); sshComponent.setHost("localhost"); @@ -122,8 +118,7 @@ public void configure() { from("direct:ssh-rsa") .to("ssh-rsa:test") - .to("mock:rsa") - .to("log:rsa?showAll=true"); + .to("mock:rsa"); } }; } From a73b8e4371fcd1ea430d49c65a097792bbc8e884 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 6 Jan 2012 16:27:40 -0500 Subject: [PATCH 29/32] Cleanup imports --- .../apache/camel/component/ssh/SshComponentConsumerTest.java | 4 ---- .../camel/component/ssh/SshComponentErrorHandlingTest.java | 4 ---- .../apache/camel/component/ssh/SshComponentProducerTest.java | 3 --- 3 files changed, 11 deletions(-) diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java index c1c4527bb026a..7d7525e54f5ae 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentConsumerTest.java @@ -18,10 +18,6 @@ import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; -import org.apache.camel.test.AvailablePortFinder; -import org.apache.camel.test.junit4.CamelTestSupport; -import org.apache.sshd.SshServer; -import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.junit.Test; public class SshComponentConsumerTest extends SshComponentTestSupport { diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentErrorHandlingTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentErrorHandlingTest.java index 3852215c725a0..cd51c6752786e 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentErrorHandlingTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentErrorHandlingTest.java @@ -21,10 +21,6 @@ import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; -import org.apache.camel.test.AvailablePortFinder; -import org.apache.camel.test.junit4.CamelTestSupport; -import org.apache.sshd.SshServer; -import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.junit.Test; public class SshComponentErrorHandlingTest extends SshComponentTestSupport { diff --git a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java index ff3b0845875e3..1da5a1befe764 100644 --- a/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java +++ b/components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentProducerTest.java @@ -18,9 +18,6 @@ import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; -import org.apache.camel.test.AvailablePortFinder; -import org.apache.camel.test.junit4.CamelTestSupport; -import org.apache.sshd.SshServer; import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.junit.Test; From 962f3b428d23388b7c256400075be1323f4bb169 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 6 Jan 2012 16:29:03 -0500 Subject: [PATCH 30/32] Removed maximumReconnectAttempts and reconnectDelay as Camel ErrorHandler provides better retry logic --- .../camel/component/ssh/SshComponent.java | 18 +-------- .../camel/component/ssh/SshConfiguration.java | 18 --------- .../camel/component/ssh/SshEndpoint.java | 37 ++++--------------- 3 files changed, 8 insertions(+), 65 deletions(-) diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java index d66ebef7389f2..7d36d2906b355 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshComponent.java @@ -41,7 +41,7 @@ protected Endpoint createEndpoint(String uri, String remaining, Map Date: Fri, 6 Jan 2012 17:26:48 -0500 Subject: [PATCH 31/32] added package.html --- .../apache/camel/component/ssh/package.html | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 components/camel-ssh/src/main/java/org/apache/camel/component/ssh/package.html diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/package.html b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/package.html new file mode 100644 index 0000000000000..f24393f50eb5b --- /dev/null +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/package.html @@ -0,0 +1,25 @@ + + + + + + +Defines the SSH Component + + + From e1cfdfa7a332dc82f858c72ba0388bb59d6c0142 Mon Sep 17 00:00:00 2001 From: Scott Cranton Date: Fri, 27 Jan 2012 16:54:43 -0500 Subject: [PATCH 32/32] updated doc --- components/camel-ssh/ReadMe.txt | 11 ----- .../camel/component/ssh/SshConfiguration.java | 49 +++++++++++++++++++ examples/camel-example-ssh/README.txt | 4 +- 3 files changed, 51 insertions(+), 13 deletions(-) delete mode 100644 components/camel-ssh/ReadMe.txt diff --git a/components/camel-ssh/ReadMe.txt b/components/camel-ssh/ReadMe.txt deleted file mode 100644 index 3cc57d1e8468c..0000000000000 --- a/components/camel-ssh/ReadMe.txt +++ /dev/null @@ -1,11 +0,0 @@ -Camel Component Project -==================== -This Project is a template of the Camel component. -When you create the component project, you need to move the META-INF/services/org/apache/camel/component/${name} -file to META-INF/services/org/apache/camel/component/foo where "foo" is the URI scheme for your component and any - related endpoints created on the fly. - -For more help see the Apache Camel documentation - - http://camel.apache.org/writing-components.html - diff --git a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java index bea394f83632a..28ef07f2cf771 100644 --- a/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java +++ b/components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java @@ -78,6 +78,11 @@ public String getUsername() { return username; } + /** + * Sets the username to use in logging into the remote SSH server. + * + * @param username String representing login username. + */ public void setUsername(String username) { this.username = username; } @@ -86,6 +91,11 @@ public String getHost() { return host; } + /** + * Sets the hostname of the remote SSH server. + * + * @param host String representing hostname of SSH server. + */ public void setHost(String host) { this.host = host; } @@ -94,6 +104,11 @@ public int getPort() { return port; } + /** + * Sets the port number for the remote SSH server. + * + * @param port int representing port number on remote host. Defaults to 22. + */ public void setPort(int port) { this.port = port; } @@ -102,6 +117,12 @@ public String getPassword() { return password; } + /** + * Sets the password to use in connecting to remote SSH server. + * Requires keyPairProvider to be set to null. + * + * @param password String representing password for username at remote host. + */ public void setPassword(String password) { this.password = password; } @@ -110,6 +131,12 @@ public String getPollCommand() { return pollCommand; } + /** + * Sets the command string to send to the remote SSH server during every poll cycle. + * Only works with camel-ssh component being used as a consumer, i.e. from("ssh://...") + * + * @param pollCommand String representing the command to send. + */ public void setPollCommand(String pollCommand) { this.pollCommand = pollCommand; } @@ -118,6 +145,14 @@ public KeyPairProvider getKeyPairProvider() { return keyPairProvider; } + /** + * Sets the KeyPairProvider reference to use when connecting using Certificates to the remote SSH Server. + * + * @param keyPairProvider KeyPairProvider reference to use in authenticating. If set to 'null', + * then will attempt to connect using username/password settings. + * + * @see KeyPairProvider + */ public void setKeyPairProvider(KeyPairProvider keyPairProvider) { this.keyPairProvider = keyPairProvider; } @@ -126,6 +161,14 @@ public String getKeyType() { return keyType; } + /** + * Sets the key type to pass to the KeyPairProvider as part of authentication. + * KeyPairProvider.loadKey(...) will be passed this value. + * + * @param keyType String defining the type of KeyPair to use for authentication. + * + * @see KeyPairProvider + */ public void setKeyType(String keyType) { this.keyType = keyType; } @@ -134,6 +177,12 @@ public long getTimeout() { return timeout; } + /** + * Sets the timeout in milliseconds to wait in establishing the remote SSH server connection. + * Defaults to 30000 milliseconds. + * + * @param timeout long millisconeds to wait. + */ public void setTimeout(long timeout) { this.timeout = timeout; } diff --git a/examples/camel-example-ssh/README.txt b/examples/camel-example-ssh/README.txt index ddec65458751e..26e0c61153d0c 100644 --- a/examples/camel-example-ssh/README.txt +++ b/examples/camel-example-ssh/README.txt @@ -1,4 +1,4 @@ -OSGi Example +SSH Example ===================== This example shows how use SSH with Camel. It can be run using Maven. @@ -28,7 +28,7 @@ You will need to compile and install this example first: If using Apache Karaf / Apache ServiceMix you can install this example from the shell - > features:addurl mvn:org.apache.camel/camel-example-ssh/2.10-SNAPSHOT/xml/features + > features:addurl mvn:org.apache.camel/camel-example-ssh//xml/features > features:install camel-example-ssh If you hit any problems please let us know on the Camel Forums