| /******************************************************************************* |
| * Copyright (c) 2007 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ptp.remotetools.internal.ssh; |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| |
| import org.eclipse.ptp.remotetools.exception.PortForwardingException; |
| import org.eclipse.ptp.remotetools.exception.RemoteConnectionException; |
| |
| import com.jcraft.jsch.JSchException; |
| |
| /** |
| * Keeps references to all active port forwardings of a connection. This |
| * forwardings are shared by all execution managers, since it is a ressource |
| * that applies only to the connection. |
| * |
| * @author dfferber |
| * |
| */ |
| public class RemotePortForwardingPool { |
| /** |
| * Remote port to local forwarding that are active on the Connection. |
| */ |
| private final HashMap<Integer, RemotePortForwarding> remotePortForwardings = new HashMap<Integer, RemotePortForwarding>();; |
| |
| /** |
| * Connection |
| */ |
| private final Connection connection; |
| |
| public RemotePortForwardingPool(Connection connection) { |
| assert connection != null; |
| |
| this.connection = connection; |
| } |
| |
| public RemotePortForwarding createRemotePortForwarding(ExecutionManager owner, int remotePort, String localAddress, |
| int localPort) throws RemoteConnectionException, PortForwardingException { |
| assert (remotePort > 0); |
| assert (localPort > 0); |
| assert (owner != null); |
| assert (connection.getSession() != null); |
| |
| synchronized (remotePortForwardings) { |
| /* |
| * Test if the forwarding is not already active. |
| */ |
| Integer remotePortInteger = new Integer(remotePort); |
| RemotePortForwarding remotePortForwarding = remotePortForwardings.get(remotePortInteger); |
| if (remotePortForwarding != null) { |
| throw new PortForwardingException(PortForwardingException.REMOTE_PORT_ALREADY_FORWARDED); |
| } |
| |
| /* |
| * Create a port forwarding in Jsch. |
| */ |
| try { |
| this.connection.getSession().setPortForwardingR(remotePort, localAddress, localPort); |
| } catch (JSchException e) { |
| throw new PortForwardingException(PortForwardingException.REMOTE_FORWARDING_FAILED, e); |
| } |
| |
| /* |
| * Create new forwarding instance and add it to the table. |
| */ |
| remotePortForwarding = new RemotePortForwarding(owner, localPort, localAddress, remotePort); |
| remotePortForwardings.put(remotePortInteger, remotePortForwarding); |
| |
| return remotePortForwarding; |
| } |
| } |
| |
| public void releaseRemotePortForwarding(RemotePortForwarding remoteForwarding, ExecutionManager owner) |
| throws RemoteConnectionException, PortForwardingException { |
| assert remoteForwarding != null; |
| assert (connection.getSession() != null); |
| |
| synchronized (remotePortForwardings) { |
| /* |
| * Assure the port forwarding that is still active. |
| */ |
| if (!remoteForwarding.isActive()) { |
| throw new PortForwardingException(PortForwardingException.REMOTE_FORWARDING_NOT_ATIVE); |
| } |
| |
| /* |
| * If a execution manager is given as owner, then assure the port |
| * forwarding belongs to it. |
| */ |
| if (owner != null) { |
| if (remoteForwarding.owner != owner) { |
| throw new PortForwardingException(PortForwardingException.REMOTE_FORWARDING_NOT_ATIVE); |
| } |
| } |
| |
| Integer remotePortInteger = new Integer(remoteForwarding.remotePort); |
| assert remotePortForwardings.containsKey(remotePortInteger); |
| |
| turnOffRemotePortForwarding(remoteForwarding); |
| remotePortForwardings.remove(remotePortInteger); |
| } |
| } |
| |
| public RemotePortForwarding getRemotePortForwarding(int remotePort) throws RemoteConnectionException, PortForwardingException { |
| assert remotePort > 0; |
| assert (connection.getSession() != null); |
| |
| synchronized (remotePortForwardings) { |
| Integer remotePortInteger = new Integer(remotePort); |
| return remotePortForwardings.get(remotePortInteger); |
| } |
| |
| } |
| |
| public void disconnect() { |
| Iterator<RemotePortForwarding> iterator = remotePortForwardings.values().iterator(); |
| while (iterator.hasNext()) { |
| RemotePortForwarding forwarding = iterator.next(); |
| turnOffRemotePortForwarding(forwarding); |
| iterator.remove(); |
| } |
| } |
| |
| public void disconnect(ExecutionManager executionManager) { |
| Iterator<RemotePortForwarding> iterator = remotePortForwardings.values().iterator(); |
| while (iterator.hasNext()) { |
| RemotePortForwarding forwarding = iterator.next(); |
| if (forwarding.owner == executionManager) { |
| turnOffRemotePortForwarding(forwarding); |
| iterator.remove(); |
| } |
| } |
| } |
| |
| /** |
| * Auxiliary method used by other methods to turn off a port forwarding. |
| * |
| * @param forwarding |
| * The port remote forwarding to be turned off. |
| */ |
| private void turnOffRemotePortForwarding(RemotePortForwarding forwarding) { |
| forwarding.releaseOwner(); |
| try { |
| connection.getSession().delPortForwardingR(forwarding.remotePort); |
| } catch (JSchException e) { |
| // No possible exceptions are known. |
| assert false; |
| } |
| } |
| |
| } |