blob: 8959ae2a702083bdb603cd8f8d2c7172cbb86d28 [file] [log] [blame]
package org.eclipse.dltk.core.internal.rse;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.environment.EnvironmentManager;
import org.eclipse.dltk.core.environment.IEnvironment;
import org.eclipse.dltk.core.environment.IEnvironmentProvider;
import org.eclipse.dltk.core.internal.rse.perfomance.RSEPerfomanceStatistics;
import org.eclipse.rse.core.IRSESystemType;
import org.eclipse.rse.core.RSECorePlugin;
import org.eclipse.rse.core.model.IHost;
import org.eclipse.rse.core.model.SystemStartHere;
import org.eclipse.rse.subsystems.files.core.model.RemoteFileUtility;
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileSubSystem;
public class RSEEnvironmentProvider implements IEnvironmentProvider {
/**
* @since 2.0
*/
public static final String ID = "org.eclipse.dltk.rse.RSEEnvironmentProvider"; //$NON-NLS-1$
public static final String RSE_SCHEME = "rse"; //$NON-NLS-1$
public static final String RSE_ENVIRONMENT_PREFIX = DLTKRSEPlugin.NAMESPACE
+ ".rseEnvironment."; //$NON-NLS-1$
public RSEEnvironmentProvider() {
}
@Override
public String getProviderName() {
return Messages.RSEEnvironmentProvider_providerName;
}
@Override
public IEnvironment getEnvironment(String envId) {
return getEnvironment(envId, true);
}
/**
* @since 2.0
*/
public IEnvironment getEnvironment(String envId, boolean lazy) {
if (envId.startsWith(RSE_ENVIRONMENT_PREFIX)) {
String name = envId.substring(RSE_ENVIRONMENT_PREFIX.length());
IHost connection = getRSEConnection(name);
if (connection != null) {
IRemoteFileSubSystem fs = RemoteFileUtility
.getFileSubSystem(connection);
if (fs != null)
return new RSEEnvironment(fs);
} else if (lazy) {
return new RSELazyEnvironment(envId, this);
}
}
return null;
}
private IHost getRSEConnection(String name) {
if (isReady(false)) {
IHost[] connections = SystemStartHere.getConnections();
for (int i = 0; i < connections.length; i++) {
IHost connection = connections[i];
if (name.equals(connection.getAliasName())) {
return connection;
}
}
}
return null;
}
private final Object lock = new Object();
private boolean waitTimeoutReached = false;
private static final int MAX_WAIT_COUNT = 20;
private static final int WAIT_INTERVAL = 500;
private boolean initialized = false;
private InitThread initThread = null;
private static final long RSE_INIT_THREAD_TIMEOUT = 60 * 1000;
private static final boolean DEBUG = false;
private static class WatchdogThread extends Job {
private final Thread thread;
public WatchdogThread(Thread thread) {
super(RSEEnvironmentProvider.class.getSimpleName()
+ "-WatchdogThread"); //$NON-NLS-1$
this.thread = thread;
setSystem(true);
}
@Override
public IStatus run(IProgressMonitor monitor) {
if (thread.isAlive()) {
if (DEBUG)
System.out.println("InitThread.interrupt()"); //$NON-NLS-1$
thread.interrupt();
} else {
if (DEBUG)
System.out.println("InitThread is already terminated"); //$NON-NLS-1$
}
return Status.OK_STATUS;
}
}
private class InitThread extends Thread {
@Override
public void run() {
final WatchdogThread watchdog = new WatchdogThread(this);
watchdog.schedule(RSE_INIT_THREAD_TIMEOUT);
try {
if (DEBUG)
System.out.println(Thread.currentThread().getName()
+ " started"); //$NON-NLS-1$
RSECorePlugin.waitForInitCompletion();
if (DEBUG)
System.out.println(Thread.currentThread().getName()
+ " finished"); //$NON-NLS-1$
watchdog.cancel();
} catch (InterruptedException e) {
if (DLTKCore.DEBUG || DEBUG) {
e.printStackTrace();
}
} finally {
synchronized (lock) {
initialized = true;
initThread = null;
lock.notifyAll();
}
}
for (IEnvironment environment : getEnvironments()) {
fireAdded(environment);
}
}
}
private final Set<String> firedEnvironmentIds = new HashSet<>();
/**
* @since 2.0
*/
public void fireAdded(IEnvironment environment) {
final boolean added;
synchronized (firedEnvironmentIds) {
added = firedEnvironmentIds.add(environment.getId());
}
if (added) {
if (DEBUG) {
System.out.println("added " + environment.getId()); //$NON-NLS-1$
}
EnvironmentManager.environmentAdded(environment);
}
}
@Override
public boolean isInitialized() {
return isReady(false);
}
private boolean isReady() {
return isReady(true);
}
private boolean isReady(boolean allowWait) {
synchronized (lock) {
if (initialized) {
if (RSECorePlugin.getDefault() == null) { // Shutdown process
return false;
}
return true;
}
boolean newThread = false;
if (initThread == null) {
newThread = true;
initThread = new InitThread();
initThread.setName(getClass().getSimpleName() + "-InitThread"); //$NON-NLS-1$
initThread.setDaemon(true);
initThread.start();
if (DEBUG)
System.out.println("start initThread"); //$NON-NLS-1$
}
if (allowWait) {
if (DEBUG)
System.out.println("wait initThread"); //$NON-NLS-1$
try {
lock.wait(newThread ? 250 : 100);
} catch (InterruptedException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
if (initialized) {
return true;
}
}
}
return false;
}
private boolean isSupportedConnection(IHost connection) {
final IRSESystemType systemType = connection.getSystemType();
if (systemType == null || systemType.isWindows()
|| systemType.isLocal()) {
return false;
}
return true;
}
@Override
public IEnvironment[] getEnvironments() {
if (isReady()) {
final IHost[] connections = SystemStartHere.getConnections();
if (connections != null && connections.length != 0) {
final List<IEnvironment> environments = new ArrayList<>(
connections.length);
for (int i = 0; i < connections.length; i++) {
final IHost connection = connections[i];
if (isSupportedConnection(connection)) {
final IRemoteFileSubSystem fs = RemoteFileUtility
.getFileSubSystem(connection);
if (fs != null)
environments.add(new RSEEnvironment(fs));
}
}
return environments.toArray(new IEnvironment[environments
.size()]);
}
}
return new IEnvironment[0];
}
@Override
public void waitInitialized() {
try {
int waitCount = 0;
while (!isReady(false)) {
synchronized (lock) {
if (waitTimeoutReached) {
break;
}
if (++waitCount > MAX_WAIT_COUNT) {
waitTimeoutReached = true;
if (DEBUG)
System.out.println(Thread.currentThread().getName()
+ " - waitInitialized - timeout reached"); //$NON-NLS-1$
break;
}
lock.wait(WAIT_INTERVAL);
}
}
} catch (InterruptedException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
@Override
public IEnvironment getProjectEnvironment(IProject project) {
if (RSEPerfomanceStatistics.PERFOMANCE_TRACING) {
RSEPerfomanceStatistics
.inc(RSEPerfomanceStatistics.HAS_PROJECT_EXECUTIONS);
}
final long start = System.currentTimeMillis();
try {
if (project.isAccessible()) {
try {
final URI uri = project.getDescription().getLocationURI();
if (uri != null
&& RSE_SCHEME.equalsIgnoreCase(uri.getScheme())
&& isReady()) {
final IHost[] connections = SystemStartHere
.getConnections();
if (connections != null) {
final String projectHost = uri.getHost();
for (int i = 0; i < connections.length; i++) {
final IHost connection = connections[i];
if (isSupportedConnection(connection)
&& projectHost
.equalsIgnoreCase(connection
.getHostName())) {
final IRemoteFileSubSystem fs = RemoteFileUtility
.getFileSubSystem(connection);
if (fs != null)
return new RSEEnvironment(fs);
}
}
}
}
} catch (CoreException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
return null;
} finally {
if (RSEPerfomanceStatistics.PERFOMANCE_TRACING) {
final long end = System.currentTimeMillis();
RSEPerfomanceStatistics.inc(
RSEPerfomanceStatistics.HAS_POJECT_EXECUTIONS_TIME,
(end - start));
}
}
}
@Override
public IEnvironment getEnvironment(URI locationURI) {
if (RSE_SCHEME.equalsIgnoreCase(locationURI.getScheme()) && isReady()) {
final IHost[] connections = SystemStartHere.getConnections();
if (connections != null) {
final String projectHost = locationURI.getHost();
for (int i = 0; i < connections.length; i++) {
final IHost connection = connections[i];
if (isSupportedConnection(connection)
&& projectHost.equalsIgnoreCase(connection
.getHostName())) {
final IRemoteFileSubSystem fs = RemoteFileUtility
.getFileSubSystem(connection);
if (fs != null)
return new RSEEnvironment(fs);
}
}
}
}
return null;
}
}