blob: e4687477880ce43904aff642ad4a35ddffadfad8 [file] [log] [blame]
package org.eclipse.dltk.core.internal.rse;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Platform;
import org.eclipse.dltk.utils.LazyExtensionManager;
import org.eclipse.dltk.utils.LazyExtensionManager.Descriptor;
import org.eclipse.rse.core.model.IHost;
import org.eclipse.rse.core.subsystems.ISubSystem;
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileSubSystem;
/**
* This class is designed to synchronize connections to RSE to display only one
* connection dialog per time.
*
* @author haiodo
* @since 2.0
*
*/
public class RSEConnectionQueryManager {
/**
* 5 minutes for connection to be established.
*/
private static final long CONNECTION_TIMEOUT = 1000 * 10; // ten seconds.
private static RSEConnectionQueryManager queryManager = null;
public static synchronized RSEConnectionQueryManager getInstance() {
if (queryManager == null) {
queryManager = new RSEConnectionQueryManager();
}
return queryManager;
}
private static class ConnectionRequest {
private IHost host;
private boolean finished = false;
public ConnectionRequest(IHost host, long id) {
this.host = host;
}
public synchronized boolean isFinished() {
return finished;
}
public synchronized void setFinished(boolean finished) {
this.finished = finished;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((host == null) ? 0 : host.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ConnectionRequest other = (ConnectionRequest) obj;
if (host == null) {
if (other.host != null)
return false;
} else if (!host.equals(other.host))
return false;
return true;
}
}
public interface IConnector {
void register();
boolean isDirectProcessingRequired();
void runDisplayRunnables(long connectionTimeout);
}
public void setConnectingStatus(boolean status) {
synchronized (requests) {
isConnecting = status;
}
}
public boolean isConnecting() {
synchronized (requests) {
return isConnecting;
}
}
public void markHostAsFinished(IHost host) {
synchronized (requests) {
List<ConnectionRequest> toRemove = new ArrayList<>();
for (ConnectionRequest request : requests) {
if (request.host.equals(host)) {
toRemove.add(request);
request.setFinished(true);
}
}
setConnectingStatus(false);
if (!toRemove.isEmpty()) {
requests.removeAll(toRemove);
requests.notifyAll();
}
}
}
/**
* Get host and set state to isConnecting()
*
* @return
*/
public IHost getNextHost(boolean wait) {
synchronized (requests) {
if (wait) {
while (isConnecting() || requests.isEmpty()) {
try {
requests.wait(100);
} catch (InterruptedException e) {
DLTKRSEPlugin.log(e);
}
}
}
if (!requests.isEmpty()) {
ConnectionRequest request = requests.get(0);
setConnectingStatus(true);
return request.host;
}
return null;
}
}
private LazyExtensionManager<IConnector> connectors = new LazyExtensionManager<>(
DLTKRSEPlugin.PLUGIN_ID + ".rseConnector");
private List<ConnectionRequest> requests = new ArrayList<>();
private boolean isConnecting = false;
private long currentId;
public RSEConnectionQueryManager() {
Descriptor<IConnector>[] descriptors = connectors.getDescriptors();
for (Descriptor<IConnector> descriptor : descriptors) {
IConnector connector = descriptor.get();
connector.register();
}
}
public boolean connectTo(IHost host) {
if (isConnected(host)) {
return true;
}
ConnectionRequest request = new ConnectionRequest(host, currentId++);
synchronized (requests) {
requests.add(request);
requests.notifyAll(); // Notify all connectors
}
// are in display thread.
Descriptor<IConnector>[] descriptors = connectors.getDescriptors();
for (Descriptor<IConnector> descriptor : descriptors) {
IConnector connector = descriptor.get();
if (connector.isDirectProcessingRequired()) {
connector.runDisplayRunnables(CONNECTION_TIMEOUT);
}
}
long endTime = System.currentTimeMillis() + CONNECTION_TIMEOUT;
synchronized (requests) {
while (!request.isFinished() && Platform.isRunning()) {
try {
requests.wait(100);
long currentTime = System.currentTimeMillis();
if (currentTime > endTime) {
// Just break
// markHostAsFinished(host);
break;
}
} catch (InterruptedException e) {
DLTKRSEPlugin.log(e);
}
}
}
return isConnected(host);
}
private boolean isConnected(IHost host) {
ISubSystem[] subSystems = host.getSubSystems();
for (ISubSystem subsystem : subSystems) {
if (subsystem instanceof IRemoteFileSubSystem) {
return subsystem.isConnected();
}
}
return false;
}
public boolean hasHosts() {
synchronized (requests) {
return !requests.isEmpty();
}
}
}