SMX4KNL-264: Switch to Apache SSHD
git-svn-id: https://svn.apache.org/repos/asf/servicemix/smx4/kernel/trunk@767285 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/assembly/pom.xml b/assembly/pom.xml
index 74af296..936d36a 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -139,8 +139,8 @@
<artifactId>org.apache.servicemix.bundles.jaxp-ri</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.servicemix.bundles</groupId>
- <artifactId>org.apache.servicemix.bundles.mina</artifactId>
+ <groupId>org.apache.mina</groupId>
+ <artifactId>mina-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
@@ -211,8 +211,8 @@
<artifactId>geronimo-annotation_1.0_spec</artifactId>
</dependency>
<dependency>
- <groupId>com.google.code.sshd</groupId>
- <artifactId>sshd</artifactId>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
diff --git a/assembly/src/main/descriptors/unix-bin.xml b/assembly/src/main/descriptors/unix-bin.xml
index 0fabe21..3dd8246 100644
--- a/assembly/src/main/descriptors/unix-bin.xml
+++ b/assembly/src/main/descriptors/unix-bin.xml
@@ -194,7 +194,6 @@
<includes>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.aopalliance</include>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.cglib</include>
- <include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.mina</include>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.jaxp-ri</include>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.oro</include>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.commons-jexl</include>
@@ -253,9 +252,18 @@
<outputDirectory>/system</outputDirectory>
<unpack>false</unpack>
<useProjectArtifact>false</useProjectArtifact>
- <outputFileNameMapping>com/google/code/sshd/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
+ <outputFileNameMapping>org/apache/sshd/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
<includes>
- <include>com.google.code.sshd:sshd</include>
+ <include>org.apache.sshd:sshd-core</include>
+ </includes>
+ </dependencySet>
+ <dependencySet>
+ <outputDirectory>/system</outputDirectory>
+ <unpack>false</unpack>
+ <useProjectArtifact>false</useProjectArtifact>
+ <outputFileNameMapping>org/apache/mina/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
+ <includes>
+ <include>org.apache.mina:mina-core</include>
</includes>
</dependencySet>
<dependencySet>
diff --git a/assembly/src/main/descriptors/windows-bin.xml b/assembly/src/main/descriptors/windows-bin.xml
index 32639cc..0901795 100644
--- a/assembly/src/main/descriptors/windows-bin.xml
+++ b/assembly/src/main/descriptors/windows-bin.xml
@@ -186,7 +186,6 @@
<includes>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.aopalliance</include>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.cglib</include>
- <include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.mina</include>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.jaxp-ri</include>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.oro</include>
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.commons-jexl</include>
@@ -245,9 +244,18 @@
<outputDirectory>/system</outputDirectory>
<unpack>false</unpack>
<useProjectArtifact>false</useProjectArtifact>
- <outputFileNameMapping>com/google/code/sshd/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
+ <outputFileNameMapping>org/apache/sshd/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
<includes>
- <include>com.google.code.sshd:sshd</include>
+ <include>org.apache.sshd:sshd-core</include>
+ </includes>
+ </dependencySet>
+ <dependencySet>
+ <outputDirectory>/system</outputDirectory>
+ <unpack>false</unpack>
+ <useProjectArtifact>false</useProjectArtifact>
+ <outputFileNameMapping>org/apache/mina/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
+ <includes>
+ <include>org.apache.mina:mina-core</include>
</includes>
</dependencySet>
<dependencySet>
diff --git a/assembly/src/main/filtered-resources/etc/startup.properties b/assembly/src/main/filtered-resources/etc/startup.properties
index 23f20c4..06519d6 100644
--- a/assembly/src/main/filtered-resources/etc/startup.properties
+++ b/assembly/src/main/filtered-resources/etc/startup.properties
@@ -42,7 +42,6 @@
org/apache/servicemix/bundles/org.apache.servicemix.bundles.jline/${jline.version}/org.apache.servicemix.bundles.jline-${jline.version}.jar=30
org/apache/servicemix/bundles/org.apache.servicemix.bundles.aopalliance/${aopalliance.version}/org.apache.servicemix.bundles.aopalliance-${aopalliance.version}.jar=30
org/apache/servicemix/bundles/org.apache.servicemix.bundles.cglib/${cglib.version}/org.apache.servicemix.bundles.cglib-${cglib.version}.jar=30
-org/apache/servicemix/bundles/org.apache.servicemix.bundles.mina/${mina.version}/org.apache.servicemix.bundles.mina-${mina.version}.jar=30
org/apache/servicemix/bundles/org.apache.servicemix.bundles.oro/${oro.version}/org.apache.servicemix.bundles.oro-${oro.version}.jar=30
org/apache/servicemix/bundles/org.apache.servicemix.bundles.commons-codec/${commons.codec.version}/org.apache.servicemix.bundles.commons-codec-${commons.codec.version}.jar=30
org/apache/servicemix/bundles/org.apache.servicemix.bundles.commons-httpclient/${commons.httpclient.version}/org.apache.servicemix.bundles.commons-httpclient-${commons.httpclient.version}.jar=30
@@ -65,7 +64,8 @@
org/apache/servicemix/kernel/gshell/org.apache.servicemix.kernel.gshell.packages/${pom.version}/org.apache.servicemix.kernel.gshell.packages-${pom.version}.jar=30
org/apache/servicemix/kernel/jaas/org.apache.servicemix.kernel.jaas.config/${pom.version}/org.apache.servicemix.kernel.jaas.config-${pom.version}.jar=30
org/apache/servicemix/kernel/jaas/org.apache.servicemix.kernel.jaas.modules/${pom.version}/org.apache.servicemix.kernel.jaas.modules-${pom.version}.jar=30
-com/google/code/sshd/sshd/${sshd.version}/sshd-${sshd.version}.jar=30
+org/apache/mina/mina-core/${mina.version}/mina-core-${mina.version}.jar=30
+org/apache/sshd/sshd-core/${sshd.version}/sshd-core-${sshd.version}.jar=30
org/osgi/jmx/${osgi.jmx.version}/jmx-${osgi.jmx.version}.jar=30
com/oracle/osgi/jmx-impl/${osgi.jmx.version}/jmx-impl-${osgi.jmx.version}.jar=30
diff --git a/client/src/main/java/org/apache/servicemix/kernel/client/Main.java b/client/src/main/java/org/apache/servicemix/kernel/client/Main.java
index f5b32ab..886acaf 100644
--- a/client/src/main/java/org/apache/servicemix/kernel/client/Main.java
+++ b/client/src/main/java/org/apache/servicemix/kernel/client/Main.java
@@ -16,9 +16,11 @@
*/
package org.apache.servicemix.kernel.client;
-import com.google.code.sshd.ClientChannel;
-import com.google.code.sshd.ClientSession;
-import com.google.code.sshd.SshClient;
+import org.apache.sshd.ClientChannel;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.SshClient;
+import org.apache.sshd.client.future.ConnectFuture;
+
import jline.ConsoleReader;
/**
@@ -70,7 +72,9 @@
try {
client = SshClient.setUpDefaultClient();
client.start();
- ClientSession session = client.connect(host, port);
+ ConnectFuture future = client.connect(host, port);
+ future.await();
+ ClientSession session = future.getSession();
session.authPassword(user, password);
ClientChannel channel = session.createChannel("shell");
channel.setIn(new ConsoleReader().getInput());
diff --git a/gshell/gshell-core/pom.xml b/gshell/gshell-core/pom.xml
index 75fb60b..19e9a27 100644
--- a/gshell/gshell-core/pom.xml
+++ b/gshell/gshell-core/pom.xml
@@ -52,8 +52,8 @@
org.apache.servicemix.kernel.version;resolution:=optional,
org.apache.servicemix.kernel.main.spi;resolution:=optional;version="1.0.0",
org.codehaus.plexus*;resolution:=optional,
- com.google.code.sshd.server.keyprovider,
- com.google.code.sshd.server.jaas,
+ org.apache.sshd.server.keyprovider,
+ org.apache.sshd.server.jaas,
org.jsecurity*;resolution:=optional,
*
</gshell.osgi.import>
@@ -157,10 +157,6 @@
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
- <artifactId>org.apache.servicemix.bundles.mina</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.commons-httpclient</artifactId>
<exclusions>
<exclusion>
@@ -192,12 +188,12 @@
<artifactId>org.apache.servicemix.bundles.oro</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.servicemix.bundles</groupId>
- <artifactId>org.apache.servicemix.bundles.mina</artifactId>
+ <groupId>org.apache.mina</groupId>
+ <artifactId>mina-core</artifactId>
</dependency>
<dependency>
- <groupId>com.google.code.sshd</groupId>
- <artifactId>sshd</artifactId>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
@@ -208,6 +204,19 @@
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.jline</artifactId>
</dependency>
+
+ <!-- jsecurity is a dependency for the ssh commands -->
+ <dependency>
+ <groupId>org.jsecurity</groupId>
+ <artifactId>jsecurity</artifactId>
+ <version>0.9.0-RC2</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
</dependencies>
<build>
@@ -266,7 +275,6 @@
<include>org.apache.geronimo.gshell.commands:gshell-file</include>
<include>org.apache.geronimo.gshell.commands:gshell-network</include>
<include>org.apache.geronimo.gshell.commands:gshell-shell</include>
- <include>org.apache.geronimo.gshell.commands:gshell-ssh</include>
<include>org.apache.geronimo.gshell.commands:gshell-text</include>
<include>org.apache.geronimo.gshell.support:gshell-ansi</include>
<include>org.apache.geronimo.gshell.support:gshell-artifact</include>
diff --git a/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/JSecurityPasswordAuthenticator.java b/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/JSecurityPasswordAuthenticator.java
new file mode 100644
index 0000000..d3bb6de
--- /dev/null
+++ b/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/JSecurityPasswordAuthenticator.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.geronimo.gshell.commands.ssh;
+
+import org.apache.sshd.server.PasswordAuthenticator;
+import org.jsecurity.SecurityUtils;
+import org.jsecurity.authc.AuthenticationException;
+import org.jsecurity.authc.UsernamePasswordToken;
+import org.jsecurity.mgt.SecurityManager;
+import org.jsecurity.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <a href="http://jsecurity.org">JSecurity</a> {@link PasswordAuthenticator}.
+ *
+ * @version $Rev: 722797 $ $Date: 2008-12-03 08:18:16 +0100 (Wed, 03 Dec 2008) $
+ */
+public class JSecurityPasswordAuthenticator
+ implements PasswordAuthenticator
+{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final SecurityManager securityManager;
+
+ public JSecurityPasswordAuthenticator(final SecurityManager securityManager) {
+ // securityManager can be null
+ this.securityManager = securityManager;
+ }
+
+ public JSecurityPasswordAuthenticator() {
+ this(null);
+ }
+
+ public Object authenticate(final String username, final String password) {
+ assert username != null;
+ assert password != null;
+
+ log.debug("Authenticating: {}/{}", username, password);
+
+ Subject currentUser;
+
+ if (securityManager != null) {
+ currentUser = securityManager.getSubject();
+ }
+ else {
+ currentUser = SecurityUtils.getSubject();
+ }
+
+ if (currentUser.isAuthenticated()) {
+ log.debug("Logging out current user: {}", currentUser.getPrincipal());
+ currentUser.logout();
+ }
+
+ try {
+ UsernamePasswordToken token = new UsernamePasswordToken(username, password);
+ currentUser.login(token);
+ Object principal = currentUser.getPrincipal();
+ log.info("User [{}] logged in successfully", principal);
+ return principal;
+ }
+ catch (AuthenticationException e) {
+ log.error("Authentication failed: " + e, e);
+ return null;
+ }
+ }
+}
diff --git a/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/ShellFactoryImpl.java b/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/ShellFactoryImpl.java
new file mode 100644
index 0000000..9795f01
--- /dev/null
+++ b/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/ShellFactoryImpl.java
@@ -0,0 +1,267 @@
+/*
+ * 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.geronimo.gshell.commands.ssh;
+
+import org.apache.sshd.server.ShellFactory;
+import jline.Completor;
+import jline.History;
+import org.apache.geronimo.gshell.command.Variables;
+import org.apache.geronimo.gshell.commandline.CommandLineExecutor;
+import org.apache.geronimo.gshell.console.Console;
+import org.apache.geronimo.gshell.console.JLineConsole;
+import org.apache.geronimo.gshell.console.completer.AggregateCompleter;
+import org.apache.geronimo.gshell.io.Closer;
+import org.apache.geronimo.gshell.io.IO;
+import org.apache.geronimo.gshell.notification.ExitNotification;
+import org.apache.geronimo.gshell.shell.ShellContext;
+import org.apache.geronimo.gshell.shell.ShellContextHolder;
+import org.apache.geronimo.gshell.registry.CommandResolver;
+import org.apache.geronimo.gshell.application.Application;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * SSHD {@link ShellFactory} which provides access to GShell.
+ *
+ * @version $Rev: 731517 $ $Date: 2009-01-05 11:25:19 +0100 (Mon, 05 Jan 2009) $
+ */
+public class ShellFactoryImpl
+ implements ShellFactory
+{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Application application;
+
+ private Console.Prompter prompter;
+
+ private CommandLineExecutor executor;
+
+ private History history;
+
+ private List<Completor> completers;
+
+ private Console.ErrorHandler errorHandler;
+
+ public Console.Prompter getPrompter() {
+ return prompter;
+ }
+
+ public void setPrompter(final Console.Prompter prompter) {
+ this.prompter = prompter;
+ }
+
+ public CommandLineExecutor getExecutor() {
+ return executor;
+ }
+
+ public void setExecutor(final CommandLineExecutor executor) {
+ this.executor = executor;
+ }
+
+ public History getHistory() {
+ return history;
+ }
+
+ public void setHistory(final History history) {
+ this.history = history;
+ }
+
+ public List<Completor> getCompleters() {
+ return completers;
+ }
+
+ public void setCompleters(final List<Completor> completers) {
+ this.completers = completers;
+ }
+
+ public Console.ErrorHandler getErrorHandler() {
+ return errorHandler;
+ }
+
+ public void setErrorHandler(final Console.ErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ public Application getApplication() {
+ return application;
+ }
+
+ public void setApplication(Application application) {
+ this.application = application;
+ }
+
+ public Shell createShell() {
+ return new ShellImpl();
+ }
+
+ public class ShellImpl
+ implements ShellFactory.Shell, org.apache.geronimo.gshell.shell.Shell, ShellContext, Runnable
+ {
+ private InputStream in;
+
+ private OutputStream out;
+
+ private OutputStream err;
+
+ private ExitCallback callback;
+
+ private IO io;
+
+ private Variables variables;
+
+ private boolean closed;
+
+ public void setInputStream(final InputStream in) {
+ this.in = in;
+ }
+
+ public void setOutputStream(final OutputStream out) {
+ this.out = out;
+ }
+
+ public void setErrorStream(final OutputStream err) {
+ this.err = err;
+ }
+
+ public void setExitCallback(ExitCallback callback) {
+ this.callback = callback;
+ }
+
+ public void start(final Map<String,String> env) throws IOException {
+ this.io = new IO(in, out, err, false);
+
+ // Create variables, inheriting the application ones
+ this.variables = new Variables(application.getVariables());
+ // Set up additional env
+ if (env != null) {
+ for (Map.Entry<String,String> entry : env.entrySet()) {
+ this.variables.set(entry.getKey(), entry.getValue());
+ }
+ }
+ this.variables.set("gshell.prompt", application.getModel().getBranding().getPrompt());
+ this.variables.set(CommandResolver.GROUP, "/");
+ this.variables.set("gshell.username", env.get("USER"));
+ this.variables.set("gshell.hostname", application.getLocalHost());
+ // HACK: Add history for the 'history' command, since its not part of the Shell intf it can't really access it
+ this.variables.set("gshell.internal.history", getHistory(), true);
+ new Thread(this).start();
+ }
+
+ public void destroy() {
+ close();
+ }
+
+ public ShellContext getContext() {
+ return this;
+ }
+
+ public Object execute(final String line) throws Exception {
+
+ return executor.execute(getContext(), line);
+ }
+
+ public Object execute(final String command, final Object[] args) throws Exception {
+ return executor.execute(getContext(), args);
+ }
+
+ public Object execute(final Object... args) throws Exception {
+ return executor.execute(getContext(), args);
+ }
+
+ public boolean isOpened() {
+ return !closed;
+ }
+
+ public void close() {
+ closed = true;
+ Closer.close(in, out, err);
+ callback.onExit(0);
+ }
+
+ public boolean isInteractive() {
+ return false;
+ }
+
+ public void run(final Object... args) throws Exception {
+ Console.Executor executor = new Console.Executor()
+ {
+ public Result execute(final String line) throws Exception {
+ assert line != null;
+ try {
+ ShellImpl.this.execute(line);
+ }
+ catch (ExitNotification n) {
+ return Result.STOP;
+ }
+ return Result.CONTINUE;
+ }
+ };
+
+ IO io = getContext().getIo();
+
+ // Setup the console runner
+ JLineConsole console = new JLineConsole(executor, io);
+ console.setPrompter(getPrompter());
+ console.setErrorHandler(getErrorHandler());
+ console.setHistory(getHistory());
+
+ if (completers != null) {
+ // Have to use aggregate here to get the completion list to update properly
+ console.addCompleter(new AggregateCompleter(completers));
+ }
+
+ console.run();
+ }
+
+ public org.apache.geronimo.gshell.shell.Shell getShell() {
+ return this;
+ }
+
+ public IO getIo() {
+ return io;
+ }
+
+ public Variables getVariables() {
+ return variables;
+ }
+
+ public void run() {
+ ShellContext ctx = ShellContextHolder.get(true);
+
+ try {
+ ShellContextHolder.set(getContext());
+ run(new Object[0]);
+ }
+ catch (Exception e) {
+ log.error("Unhandled failure: " + e, e);
+ }
+ finally {
+ ShellContextHolder.set(ctx);
+ close();
+ }
+ }
+ }
+}
diff --git a/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshAction.java b/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshAction.java
new file mode 100644
index 0000000..cafc437
--- /dev/null
+++ b/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshAction.java
@@ -0,0 +1,169 @@
+/*
+ * 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.geronimo.gshell.commands.ssh;
+
+import org.apache.sshd.ClientChannel;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.SshClient;
+import org.apache.sshd.client.future.ConnectFuture;
+import org.apache.sshd.common.util.NoCloseInputStream;
+import org.apache.sshd.common.util.NoCloseOutputStream;
+import org.apache.geronimo.gshell.clp.Argument;
+import org.apache.geronimo.gshell.clp.Option;
+import org.apache.geronimo.gshell.command.CommandAction;
+import org.apache.geronimo.gshell.command.CommandContext;
+import org.apache.geronimo.gshell.i18n.MessageSource;
+import org.apache.geronimo.gshell.io.IO;
+import org.apache.geronimo.gshell.io.PromptReader;
+import org.apache.geronimo.gshell.spring.BeanContainer;
+import org.apache.geronimo.gshell.spring.BeanContainerAware;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Connect to a SSH server.
+ *
+ * @version $Rev: 721244 $ $Date: 2008-11-27 18:19:56 +0100 (Thu, 27 Nov 2008) $
+ */
+public class SshAction
+ implements CommandAction, BeanContainerAware
+{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Option(name="-l", aliases={"--username"})
+ private String username;
+
+ @Option(name="-P", aliases={"--password"})
+ private String password;
+
+ @Argument(required=true)
+ private String hostname;
+
+ @Option(name="-p", aliases={"--port"})
+ private int port = 22;
+
+ private BeanContainer container;
+
+ private ClientSession session;
+
+ public void setBeanContainer(final BeanContainer container) {
+ assert container != null;
+ this.container = container;
+ }
+
+ /**
+ * Helper to validate that prompted username or password is not null or empty.
+ */
+ private class UsernamePasswordValidator
+ implements PromptReader.Validator
+ {
+ private String type;
+
+ private int count = 0;
+
+ private int max = 3;
+
+ public UsernamePasswordValidator(final String type) {
+ assert type != null;
+
+ this.type = type;
+ }
+
+ public boolean isValid(final String value) {
+ count++;
+
+ if (value != null && value.trim().length() > 0) {
+ return true;
+ }
+
+ if (count >= max) {
+ throw new RuntimeException("Too many attempts; failed to prompt user for " + type + " after " + max + " tries");
+ }
+
+ return false;
+ }
+ }
+
+ public Object execute(final CommandContext context) throws Exception {
+ assert context != null;
+ IO io = context.getIo();
+ MessageSource messages = context.getCommand().getMessages();
+
+ //
+ // TODO: Parse hostname for <username>@<hostname>
+ //
+
+ io.info(messages.format("info.connecting", hostname, port));
+
+ // If the username/password was not configured via cli, then prompt the user for the values
+ if (username == null || password == null) {
+ PromptReader prompter = new PromptReader(io);
+ String text;
+
+ log.debug("Prompting user for credentials");
+
+ if (username == null) {
+ text = messages.getMessage("prompt.username");
+ username = prompter.readLine(text + ": ", new UsernamePasswordValidator(text));
+ }
+
+ if (password == null) {
+ text = messages.getMessage("prompt.password");
+ password = prompter.readPassword(text + ": ", new UsernamePasswordValidator(text));
+ }
+ }
+
+ // Create the client from prototype
+ SshClient client = container.getBean(SshClient.class);
+ log.debug("Created client: {}", client);
+ client.start();;
+
+ try {
+ ConnectFuture future = client.connect(hostname, port);
+ future.await();
+ session = future.getSession();
+ try {
+ io.info(messages.getMessage("info.connected"));
+
+ session.authPassword(username, password);
+ int ret = session.waitFor(ClientSession.WAIT_AUTH | ClientSession.CLOSED | ClientSession.AUTHED, 0);
+ if ((ret & ClientSession.AUTHED) == 0) {
+ io.err.println("Authentication failed");
+ return Result.FAILURE;
+ }
+
+ ClientChannel channel = session.createChannel("shell");
+ channel.setIn(new NoCloseInputStream(io.inputStream));
+ channel.setOut(new NoCloseOutputStream(io.outputStream));
+ channel.setErr(new NoCloseOutputStream(io.errorStream));
+ channel.open();
+ channel.waitFor(ClientChannel.CLOSED, 0);
+ } finally {
+ session.close(false);
+ }
+ } finally {
+ client.stop();
+ }
+
+ io.verbose(messages.getMessage("verbose.disconnected"));
+
+ return Result.SUCCESS;
+ }
+}
diff --git a/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshServerAction.java b/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshServerAction.java
new file mode 100644
index 0000000..abfe8b8
--- /dev/null
+++ b/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/commands/ssh/SshServerAction.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.geronimo.gshell.commands.ssh;
+
+import org.apache.sshd.SshServer;
+import org.apache.geronimo.gshell.clp.Option;
+import org.apache.geronimo.gshell.command.CommandAction;
+import org.apache.geronimo.gshell.command.CommandContext;
+import org.apache.geronimo.gshell.i18n.MessageSource;
+import org.apache.geronimo.gshell.io.IO;
+import org.apache.geronimo.gshell.spring.BeanContainer;
+import org.apache.geronimo.gshell.spring.BeanContainerAware;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Start a SSH server.
+ *
+ * @version $Rev: 720411 $ $Date: 2008-11-25 05:32:43 +0100 (Tue, 25 Nov 2008) $
+ */
+public class SshServerAction
+ implements CommandAction, BeanContainerAware
+{
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Option(name="-p", aliases={ "--port" })
+ private int port=8022;
+
+ @Option(name="-b", aliases={ "--background"})
+ private boolean background;
+
+ private BeanContainer container;
+
+ public void setBeanContainer(final BeanContainer container) {
+ assert container != null;
+
+ this.container = container;
+ }
+
+ public Object execute(final CommandContext context) throws Exception {
+ assert context != null;
+ IO io = context.getIo();
+ MessageSource messages = context.getCommand().getMessages();
+
+ SshServer server = container.getBean("sshServer", SshServer.class);
+
+ log.debug("Created server: {}", server);
+
+ server.setPort(port);
+
+ server.start();
+
+ io.info(messages.format("info.listening", port));
+
+ if (!background) {
+ synchronized (this) {
+ log.debug("Waiting for server to shutdown");
+
+ wait();
+ }
+
+ server.stop();
+ }
+
+ return Result.SUCCESS;
+ }
+}
diff --git a/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/BogusPasswordAuthenticator.java b/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/BogusPasswordAuthenticator.java
index 7d1adff..34e2527 100644
--- a/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/BogusPasswordAuthenticator.java
+++ b/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/BogusPasswordAuthenticator.java
@@ -18,7 +18,7 @@
*/
package org.apache.servicemix.kernel.gshell.core.sshd;
-import com.google.code.sshd.server.PasswordAuthenticator;
+import org.apache.sshd.server.PasswordAuthenticator;
public class BogusPasswordAuthenticator implements PasswordAuthenticator {
diff --git a/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshServerFactory.java b/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshServerFactory.java
index 92214a8..fbf9041 100644
--- a/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshServerFactory.java
+++ b/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/sshd/SshServerFactory.java
@@ -18,14 +18,12 @@
*/
package org.apache.servicemix.kernel.gshell.core.sshd;
-import com.google.code.sshd.SshServer;
+import org.apache.sshd.SshServer;
public class SshServerFactory {
private SshServer server;
- private String location;
-
private boolean start;
public SshServerFactory(SshServer server) {
diff --git a/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml b/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
index 2a8df13..d68ee51 100644
--- a/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
+++ b/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
@@ -36,10 +36,10 @@
default-init-method="init"
default-destroy-method="destroy">
- <bean name="sshClient" class="com.google.code.sshd.SshClient" factory-method="setUpDefaultClient" init-method="start" destroy-method="stop">
+ <bean name="sshClient" class="org.apache.sshd.SshClient" factory-method="setUpDefaultClient" init-method="start" destroy-method="stop">
</bean>
- <bean name="sshServer" class="com.google.code.sshd.SshServer" factory-method="setUpDefaultServer" scope="prototype">
+ <bean name="sshServer" class="org.apache.sshd.SshServer" factory-method="setUpDefaultServer" scope="prototype">
<property name="port" value="${sshPort}" />
<property name="shellFactory">
<bean class="org.apache.geronimo.gshell.commands.ssh.ShellFactoryImpl">
@@ -70,10 +70,10 @@
<property name="passwordAuthenticator" ref="passwordAuthenticator" />
</bean>
- <bean name="keyPairProvider" class="com.google.code.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider">
+ <bean name="keyPairProvider" class="org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider">
<property name="path" value="${hostKey}" />
</bean>
- <bean name="passwordAuthenticator" class="com.google.code.sshd.server.jaas.JaasPasswordAuthenticator">
+ <bean name="passwordAuthenticator" class="org.apache.sshd.server.jaas.JaasPasswordAuthenticator">
<property name="domain" value="${sshRealm}" />
</bean>
diff --git a/gshell/itests/src/test/java/org/apache/servicemix/kernel/gshell/itests/CoreTest.java b/gshell/itests/src/test/java/org/apache/servicemix/kernel/gshell/itests/CoreTest.java
index 92e06c7..6f90dc2 100644
--- a/gshell/itests/src/test/java/org/apache/servicemix/kernel/gshell/itests/CoreTest.java
+++ b/gshell/itests/src/test/java/org/apache/servicemix/kernel/gshell/itests/CoreTest.java
@@ -41,10 +41,10 @@
getBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.commons-httpclient"),
getBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.commons-jexl"),
getBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.commons-vfs"),
- getBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.mina"),
+ getBundle("org.apache.mina", "mina-core"),
getBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.oro"),
getBundle("org.apache.servicemix.kernel.jaas", "org.apache.servicemix.kernel.jaas.config"),
- getBundle("com.google.code.sshd", "sshd"),
+ getBundle("org.apache.sshd", "sshd-core"),
getBundle("org.apache.servicemix.kernel.gshell", "org.apache.servicemix.kernel.gshell.core"),
getBundle("org.apache.servicemix.kernel.gshell", "org.apache.servicemix.kernel.gshell.osgi")
};
diff --git a/pom.xml b/pom.xml
index f604975..31f8796 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,7 +90,7 @@
<junit.version>3.8.2_1</junit.version>
<jline.version>0.9.94_1</jline.version>
<log4j.version>1.2.14</log4j.version>
- <mina.version>1.1.7_1</mina.version>
+ <mina.version>2.0.0-M5</mina.version>
<oro.version>2.0.8_1</oro.version>
<pax.logging.version>1.3.0</pax.logging.version>
<pax.url.version>0.3.3</pax.url.version>
@@ -98,7 +98,7 @@
<servicemix.specs.version>1.4-SNAPSHOT</servicemix.specs.version>
<spring.osgi.version>1.2.0-rc1</spring.osgi.version>
<spring.version>2.5.6</spring.version>
- <sshd.version>0.1</sshd.version>
+ <sshd.version>1.0-SNAPSHOT</sshd.version>
<woodstox.version>3.2.7_1</woodstox.version>
<osgi.jmx.version>1.0-r6125-patched</osgi.jmx.version>
@@ -421,8 +421,8 @@
<version>${spring.osgi.version}</version>
</dependency>
<dependency>
- <groupId>org.apache.servicemix.bundles</groupId>
- <artifactId>org.apache.servicemix.bundles.mina</artifactId>
+ <groupId>org.apache.mina</groupId>
+ <artifactId>mina-core</artifactId>
<version>${mina.version}</version>
</dependency>
<dependency>
@@ -508,8 +508,8 @@
<version>${commons.io.version}</version>
</dependency>
<dependency>
- <groupId>org.apache.servicemix.bundles</groupId>
- <artifactId>org.apache.servicemix.bundles.mina</artifactId>
+ <groupId>org.apache.mina</groupId>
+ <artifactId>mina-core</artifactId>
<version>${mina.version}</version>
<exclusions>
<exclusion>
@@ -731,8 +731,8 @@
<version>${easymock.version}</version>
</dependency>
<dependency>
- <groupId>com.google.code.sshd</groupId>
- <artifactId>sshd</artifactId>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
<version>${sshd.version}</version>
<exclusions>
<exclusion>