| 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; |
| } |
| |
| } |