/** * */ package vnet.sms.common.shell.clamshellsshsrv.internal; import static org.apache.commons.lang.Validate.notEmpty; import static org.apache.commons.lang.Validate.notNull; import java.security.PublicKey; import java.util.concurrent.ScheduledExecutorService; import org.apache.sshd.SshServer; import org.apache.sshd.common.Factory; import org.apache.sshd.server.Command; import org.apache.sshd.server.PasswordAuthenticator; import org.apache.sshd.server.PublickeyAuthenticator; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; import org.apache.sshd.server.session.ServerSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import vnet.sms.common.shell.clamshellspring.ClamshellLauncher; import vnet.sms.common.shell.clamshellspring.ClamshellLauncherFactoryAware; import vnet.sms.common.shell.clamshellsshsrv.Defaults; /** * @author obergner * */ public class SshServerFactoryBean implements FactoryBean<SshServer>, ClamshellLauncherFactoryAware, InitializingBean, DisposableBean { private final Logger log = LoggerFactory .getLogger(getClass()); private String host = Defaults.DEFAULT_HOST; private int port = Defaults.DEFAULT_PORT; private String hostKeyPath = Defaults.DEFAULT_HOST_KEY_PATH; private boolean autostart = false; private Factory<Command> shellFactory; private ScheduledExecutorService scheduledExecutorService = Defaults.DEFAULT_SCHEDULED_EXECUTOR_SERVICE; private SshServer product; @Override public SshServer getObject() throws Exception { if (this.product == null) { throw new IllegalStateException( "No SshServer instance has been created yet. Did you remember to call afterPropertiesSet() when using this factory outside Spring?"); } return this.product; } @Override public Class<?> getObjectType() { return this.product != null ? this.product.getClass() : SshServer.class; } @Override public boolean isSingleton() { return true; } /** * @see vnet.sms.common.beans.factory.DisposableBean#destroy() */ @Override public void destroy() throws Exception { this.log.info("About to stop SshServer {} ...", this.product); final long before = System.currentTimeMillis(); this.product.stop(); this.log.info("Stopped SshServer {} in {} ms", this.product, System.currentTimeMillis() - before); this.product = null; } /** * @see vnet.sms.common.beans.factory.InitializingBean#afterPropertiesSet() */ @Override public void afterPropertiesSet() throws Exception { this.log.info("About to create new SshServer instance ..."); checkConfig(); final SshServer newSshServer = SshServer.setUpDefaultServer(); newSshServer.setPasswordAuthenticator(new PasswordAuthenticator() { @Override public boolean authenticate(final String username, final String password, final ServerSession session) { return (username != null) && username.equals(password); } }); this.log.debug( "Set default password authenticator on new SshServer instance {} - " + "this password authenticator will accept all login attempts where username equals password", newSshServer); newSshServer.setPublickeyAuthenticator(new PublickeyAuthenticator() { @Override public boolean authenticate(final String username, final PublicKey key, final ServerSession session) { return true; } }); this.log.debug( "Set default public key authenticator on new SshServer instance {} - " + "this password authenticator will accept all public keys", newSshServer); newSshServer.setHost(this.host); this.log.debug("Set host on new SshServer instance {} to {}", newSshServer, this.host); newSshServer.setPort(this.port); this.log.debug("Set port on new SshServer instance {} to {}", newSshServer, this.port); newSshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider( this.hostKeyPath)); this.log.debug( "New SshServer instance {} will store its host key at {}", newSshServer, this.hostKeyPath); newSshServer.setScheduledExecutorService(this.scheduledExecutorService, true); this.log.debug( "Set scheduled executor service on new SshServer instance {} to {}", newSshServer, this.scheduledExecutorService); newSshServer.setShellFactory(this.shellFactory); this.log.debug("Set shell factory on new SshServer instance {} to {}", newSshServer, this.shellFactory); if (this.autostart) { this.log.info( "Autostart is set to true - will start newly created SshServer {} ...", newSshServer); final long before = System.currentTimeMillis(); newSshServer.start(); this.log.info("Started newly created SshServer {} in {} ms", newSshServer, System.currentTimeMillis() - before); } else { this.log.info( "Autostart is set to false - will NOT start newly created SshServer {}", newSshServer); } this.product = newSshServer; this.log.info("Finished creating new SshServer instance {}", newSshServer); } private void checkConfig() throws IllegalStateException { if (this.shellFactory == null) { throw new IllegalStateException("No ShellFactory has been set"); } } /** * @param host * the host to set */ public final void setHost(final String host) { notEmpty(host, "Argument 'host' must neither be null nor empty"); this.host = host; } /** * @param port * the port to set */ public final void setPort(final int port) { this.port = port; } /** * @param hostKeyPath * the hostKeyPath to set */ public final void setHostKeyPath(final String hostKeyPath) { notEmpty(hostKeyPath, "Argument 'hostKeyPath' must neither be null nor empty"); this.hostKeyPath = hostKeyPath; } /** * @param autostart * the autostart to set */ public final void setAutostart(final boolean autostart) { this.autostart = autostart; } @Override public void setClamshellLauncherFactory( final ClamshellLauncher.Factory clamshellLauncherFactory) { notNull(clamshellLauncherFactory, "Argument 'clamshellLauncherFactory' must not be null"); this.shellFactory = new ClamshellLauncherCommand.Factory( clamshellLauncherFactory); } /** * @param scheduledExecutorService * the scheduledExecutorService to set */ public final void setScheduledExecutorService( final ScheduledExecutorService scheduledExecutorService) { notNull(scheduledExecutorService, "Argument 'scheduledExecutorService' must not be null"); this.scheduledExecutorService = scheduledExecutorService; } @Override public String toString() { return "SshServerFactoryBean@" + this.hashCode() + "[host: " + this.host + "|port: " + this.port + "|hostKeyPath: " + this.hostKeyPath + "|autostart: " + this.autostart + "|shellFactory: " + this.shellFactory + "|scheduledExecutorService: " + this.scheduledExecutorService + "|product: " + this.product + "]"; } }