blob: 17460f3c571d3527027e6873a59b27b6d36cf022 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2006 IBM Corporation.
* 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 Implementation
*
*****************************************************************************/
package org.eclipse.ptp.remotetools.internal.ssh;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.ptp.remotetools.core.IRemoteCopyTools;
import org.eclipse.ptp.remotetools.core.IRemoteExecutionManager;
import org.eclipse.ptp.remotetools.core.IRemoteExecutionTools;
import org.eclipse.ptp.remotetools.core.IRemoteFileTools;
import org.eclipse.ptp.remotetools.core.IRemoteOperation;
import org.eclipse.ptp.remotetools.core.IRemotePathTools;
import org.eclipse.ptp.remotetools.core.IRemotePortForwardingTools;
import org.eclipse.ptp.remotetools.core.IRemoteStatusTools;
import org.eclipse.ptp.remotetools.core.IRemoteTunnel;
import org.eclipse.ptp.remotetools.core.messages.Messages;
import org.eclipse.ptp.remotetools.exception.CancelException;
import org.eclipse.ptp.remotetools.exception.LocalPortBoundException;
import org.eclipse.ptp.remotetools.exception.RemoteConnectionException;
import org.eclipse.ptp.remotetools.internal.common.RemoteTunnel;
/**
* @author Richard Maciel
*/
public class ExecutionManager implements IRemoteExecutionManager {
/**
* Tunnels created by this manager.
*/
Set<IRemoteTunnel> tunnels = new HashSet<IRemoteTunnel>();
/**
* Remote executions created by this manager.
*/
Set<IRemoteOperation> executions = new HashSet<IRemoteOperation>();
/**
* Connection created the execution manager.
*/
protected final Connection connection;
/**
* The instance that provides execution facility methods.
*/
protected IRemoteExecutionTools executionTools = null;
/**
* The instance that provides file manipulation facility methods.
*/
protected IRemoteFileTools fileTools = null;
/**
* The instance that provides file transfer facility methods.
*/
protected IRemoteCopyTools copyTools = null;
/**
* The instance that provides the path converter tool.
*/
protected IRemotePathTools pathTools = null;
/**
* The instance that provides the status tool.
*/
protected IRemoteStatusTools statusTools = null;
/**
* The instance that provides the port forwarding.
*/
protected IRemotePortForwardingTools portForwardingTools = null;
/**
* Automatic-generated port attribute
*/
private static final int minPort = 10000;
private static final int maxPort = 65000;
private static int autoActualPort = minPort;
/**
* Cancel flag. If true, no more operations are allowed on the this
* execution manager.
*/
private boolean cancelFlag = false;
/**
* Method that updates and return a new port number
*/
private synchronized static int getNewPortNumber() {
if (autoActualPort == maxPort)
autoActualPort = minPort;
return autoActualPort++;
}
/**
* Class constructor. This method initializes control data and allocs a
* control terminal.
*
* @throws RemoteCommandException
* The manager could not be created.
*
*/
protected ExecutionManager(Connection connection) throws RemoteConnectionException {
this.connection = connection;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.remotetools.IRemoteExecutionManager#cancel()
*/
public synchronized void cancel() {
/*
* Cancel all operations. Each operation implements its own logic how to
* cancel. This simply broadcasts the cancel to all running operations.
*/
for (IRemoteOperation execution : new ArrayList<IRemoteOperation>(executions)) {
execution.cancel();
}
cancelFlag = true;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.remotetools.core.IRemoteExecutionManager#resetCancel()
*/
public synchronized void resetCancel() {
cancelFlag = false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.remotetools.core.IRemoteExecutionManager#close()
*/
public synchronized void close() {
/*
* Mark manager as canceled and interrupt ongoing operations.
*/
cancel();
/*
* Close all tunnels.
*/
for (IRemoteTunnel tunnel : new ArrayList<IRemoteTunnel>(tunnels)) {
try {
// releaseTunnel() already removes the entry from the list.
releaseTunnel(tunnel);
} catch (RemoteConnectionException e) {
}
}
connection.getForwardingPool().disconnect(this);
/*
* Close all channels for remote executions.
*/
for (IRemoteOperation execution : new ArrayList<IRemoteOperation>(executions)) {
execution.close();
}
}
/**
* Get the connection used by the execution manager.
*/
protected Connection getConnection() {
return connection;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.remotetools.core.IRemoteExecutionManager#getExecutionTools
* ()
*/
public IRemoteExecutionTools getExecutionTools() throws RemoteConnectionException {
if (executionTools == null) {
executionTools = new ExecutionTools(this);
}
return executionTools;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.remotetools.core.IRemoteExecutionManager#getRemoteFileTools
* ()
*/
public IRemoteFileTools getRemoteFileTools() throws RemoteConnectionException {
if (fileTools == null) {
fileTools = new FileTools(this);
}
return fileTools;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.remotetools.core.IRemoteExecutionManager#getRemoteCopyTools
* ()
*/
public IRemoteCopyTools getRemoteCopyTools() throws RemoteConnectionException {
if (copyTools == null) {
copyTools = new CopyTools(this);
}
return copyTools;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.remotetools.core.IRemoteExecutionManager#getRemotePathTools
* ()
*/
public IRemotePathTools getRemotePathTools() {
if (pathTools == null) {
pathTools = new PathTools(this);
}
return pathTools;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.remotetools.core.IRemoteExecutionManager#getRemoteStatusTools
* ()
*/
public IRemoteStatusTools getRemoteStatusTools() throws RemoteConnectionException {
if (statusTools == null) {
statusTools = new StatusTools(this);
}
return statusTools;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.remotetools.core.IRemoteExecutionManager#createTunnel
* (int, java.lang.String, int)
*/
public synchronized IRemoteTunnel createTunnel(int localPort, String addressOnRemoteHost, int portOnRemoteHost)
throws RemoteConnectionException, LocalPortBoundException, CancelException {
test();
testCancel();
RemoteTunnel tunnel = connection.createTunnel(localPort, addressOnRemoteHost, portOnRemoteHost);
tunnels.add(tunnel);
return tunnel;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ptp.remotetools.core.IRemoteExecutionManager#createTunnel
* (java.lang.String, int)
*/
public synchronized IRemoteTunnel createTunnel(String addressOnRemoteHost, int portOnRemoteHost)
throws RemoteConnectionException, LocalPortBoundException, CancelException {
// Generate a local port automatically, before calling the createTunnel
// method passing it as parameter.
test();
testCancel();
int storedPort = getNewPortNumber();
int newGeneratedPort = storedPort;
while (true) {
try {
IRemoteTunnel tunnel = createTunnel(newGeneratedPort, addressOnRemoteHost, portOnRemoteHost);
return tunnel;
} catch (LocalPortBoundException e) {
// If the new port generated is equal the port we stored before
// the loop, all ports are probably busy
// so, generate an exception.
newGeneratedPort = getNewPortNumber();
if (newGeneratedPort == storedPort)
throw new LocalPortBoundException(Messages.ExecutionManager_CreateTunnel_AllLocalPortsBusy);
}
}
}
public synchronized void releaseTunnel(IRemoteTunnel tunnel) throws RemoteConnectionException {
try {
test();
connection.releaseTunnel((RemoteTunnel) tunnel);
} finally {
tunnels.remove(tunnel);
}
}
protected synchronized void registerOperation(IRemoteOperation operation) {
executions.add(operation);
}
protected synchronized void unregisterOperation(IRemoteOperation operation) {
executions.remove(operation);
}
/**
* Throw an exception if the manager cannot execute commands.
*
* @throws RemoteConnectionException
* The connection was lost.
* @throws CancelException
* The manager is canceled.
*/
protected void test() throws RemoteConnectionException {
connection.test();
}
protected void testCancel() throws CancelException {
if (cancelFlag) {
throw new CancelException();
}
}
public IRemotePortForwardingTools getPortForwardingTools() throws RemoteConnectionException {
if (portForwardingTools == null) {
portForwardingTools = new PortForwardingTools(this);
}
return portForwardingTools;
}
}