/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Atsuhiko Yamanaka, JCraft,Inc. - initial API and implementation. * IBM Corporation - ongoing maintenance * Aptana Inc. *******************************************************************************/ package org.eclipse.php.internal.server.core.tunneling; import java.util.Enumeration; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jsch.core.IJSchLocation; import org.eclipse.jsch.core.IJSchService; import org.eclipse.php.internal.server.core.Activator; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; /** * A SSH Tunnel session is the actual class that interacts with jcraft JSch * sessions. A new session is be created as needed when the * {@link #getSession()} method is called. */ public class SSHTunnelSession { private static final int DEFAULT_TIMEOUT = 45000; private static java.util.Hashtable<String, SSHTunnelSession> pool = new java.util.Hashtable<String, SSHTunnelSession>(); private Session session; /** * Returns a SSHTunnelSession for the given arguments. A new session will be * created in case there is no active session with the given target and user * name. * * @param username * @param password * @param hostname * @param port * @param monitor * @return A connected SSH tunnel session. * @throws JSchException * In case a connection could not be established. */ public static SSHTunnelSession getSession(String username, String password, String hostname, int port, IProgressMonitor monitor) throws JSchException { String key = getPoolKey(username, hostname, port); try { SSHTunnelSession jschSession = (SSHTunnelSession) pool.get(key); if (jschSession != null && !jschSession.getSession().isConnected()) { pool.remove(key); jschSession = null; } if (jschSession == null) { IJSchService service = getJSchService(); IJSchLocation jlocation = service.getLocation(username, hostname, port); Session session = null; try { session = createSession(service, jlocation, password, monitor); } catch (JSchException e) { throw e; } if (session == null) { throw new JSchException(Messages.SSHTunnelSession_0 + hostname); } if (session.getTimeout() != DEFAULT_TIMEOUT) { session.setTimeout(DEFAULT_TIMEOUT); } SSHTunnelSession schSession = new SSHTunnelSession(session); pool.put(key, schSession); return schSession; } return jschSession; } catch (JSchException e) { pool.remove(key); if (e.toString().indexOf("Auth cancel") != -1) { //$NON-NLS-1$ throw new OperationCanceledException(); } throw e; } } /* * Creates a JSch session. */ private static Session createSession(IJSchService service, IJSchLocation location, String password, IProgressMonitor monitor) throws JSchException { Session session = service.createSession(location, null); session.setTimeout(DEFAULT_TIMEOUT); if (password != null) { session.setPassword(password); } service.connect(session, DEFAULT_TIMEOUT, monitor); return session; } private static IJSchService getJSchService() { return Activator.getDefault().getJSchService(); } private static String getPoolKey(String username, String hostname, int port) { return username + "@" + hostname + ":" + port; //$NON-NLS-1$ //$NON-NLS-2$ } /** * Disconnect <b>all</b> of the SSH tunnel sessions that were statically * created by this SSHTunnelSession class. */ public static void shutdown() { if (getJSch() != null && pool.size() > 0) { for (Enumeration<SSHTunnelSession> e = pool.elements(); e.hasMoreElements();) { SSHTunnelSession session = e.nextElement(); try { session.getSession().disconnect(); } catch (Exception ee) { // Ignore } } pool.clear(); } } /** * Returns a {@link JSch} from the JSch service. * * @return {@link JSch} */ public static JSch getJSch() { return getJSchService().getJSch(); } private SSHTunnelSession(Session session) { this.session = session; } /** * Returns the {@link Session} instance. * * @return {@link Session} */ public Session getSession() { return session; } /** * Dispose the connection (disconnect). */ public void dispose() { pool.remove(getPoolKey(session.getUserName(), session.getHost(), session.getPort())); if (session.isConnected()) { session.disconnect(); } } }