diff --git a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java index 767a0595abf6..8bb7afc4d76b 100644 --- a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java +++ b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java @@ -55,8 +55,7 @@ public abstract class RemoteProcessSupport { public static final Logger LOG = Logger.getInstance("#" + RemoteProcessSupport.class); private final Class myValueClass; - private final HashMap, Object> myProcMap = - new HashMap, Object>(); + private final HashMap, Info> myProcMap = new HashMap, Info>(); static { RemoteServer.setupRMI(); @@ -78,13 +77,11 @@ public abstract class RemoteProcessSupport { } public void stopAll(boolean wait) { - final ArrayList allHandlers = new ArrayList(); + ArrayList allHandlers = new ArrayList(); synchronized (myProcMap) { - for (Object o : myProcMap.values()) { - final ProcessHandler handler = o instanceof PendingInfo ? ((PendingInfo)o).handler : o instanceof Info ? ((Info)o).handler : null; - ContainerUtil.addIfNotNull(handler, allHandlers); + for (Info o : myProcMap.values()) { + ContainerUtil.addIfNotNull(o.handler, allHandlers); } - myProcMap.clear(); } for (ProcessHandler handler : allHandlers) { handler.destroyProcess(); @@ -97,7 +94,7 @@ public abstract class RemoteProcessSupport { } public List getActiveConfigurations(@NotNull Target target) { - final ArrayList result = new ArrayList(); + ArrayList result = new ArrayList(); synchronized (myProcMap) { for (Pair pair : myProcMap.keySet()) { if (pair.first == target) { @@ -108,11 +105,11 @@ public abstract class RemoteProcessSupport { return result; } - public EntryPoint acquire(@NotNull final Target target, @NotNull final Parameters configuration) throws Exception { + public EntryPoint acquire(@NotNull Target target, @NotNull Parameters configuration) throws Exception { ApplicationManagerEx.getApplicationEx().assertTimeConsuming(); - final Ref ref = Ref.create(null); - final Pair key = Pair.create(target, configuration); + Ref ref = Ref.create(null); + Pair key = Pair.create(target, configuration); if (!getExistingInfo(ref, key)) { startProcess(target, configuration, key); if (ref.isNull()) { @@ -131,38 +128,28 @@ public abstract class RemoteProcessSupport { } } if (ref.isNull()) throw new RuntimeException("Unable to acquire remote proxy for: " + getName(target)); - final Info info = ref.get(); + RunningInfo info = ref.get(); if (info.handler == null) throw new ExecutionException(info.name); return acquire(info); } public void release(@NotNull Target target, @Nullable Parameters configuration) { - final ArrayList handlersToStop = new ArrayList(); - final ArrayList> keysToRemove = new ArrayList>(); + ArrayList handlers = new ArrayList(); synchronized (myProcMap) { for (Pair pair : myProcMap.keySet()) { if (pair.first == target && (configuration == null || pair.second == configuration)) { - final Object o = myProcMap.get(pair); - final ProcessHandler handler = o instanceof PendingInfo ? ((PendingInfo)o).handler : o instanceof Info ? ((Info)o).handler : null; - if (handler != null) { - handlersToStop.add(handler); - keysToRemove.add(pair); - } - else { - // todo what to do??? - } + ContainerUtil.addIfNotNull(myProcMap.get(pair).handler, handlers); } } - myProcMap.keySet().removeAll(keysToRemove); } - for (ProcessHandler handler : handlersToStop) { + for (ProcessHandler handler : handlers) { handler.destroyProcess(); } fireModificationCountChanged(); } private void startProcess(Target target, Parameters configuration, Pair key) { - final ProgramRunner runner = new DefaultProgramRunner() { + ProgramRunner runner = new DefaultProgramRunner() { @NotNull public String getRunnerId() { return "MyRunner"; @@ -172,16 +159,16 @@ public abstract class RemoteProcessSupport { return true; } }; - final Executor executor = DefaultRunExecutor.getRunExecutorInstance(); - ProcessHandler processHandler; + Executor executor = DefaultRunExecutor.getRunExecutorInstance(); + ProcessHandler processHandler = null; try { - final RunProfileState state = getRunProfileState(target, configuration, executor); - final ExecutionResult result = state.execute(executor, runner); + RunProfileState state = getRunProfileState(target, configuration, executor); + ExecutionResult result = state.execute(executor, runner); //noinspection ConstantConditions processHandler = result.getProcessHandler(); } catch (Exception e) { - handleProcessTerminated(key, ExceptionUtil.getUserStackTrace(e, LOG)); + dropProcessInfo(key, ExceptionUtil.getUserStackTrace(e, LOG), processHandler); return; } processHandler.addProcessListener(getProcessListener(key)); @@ -191,13 +178,14 @@ public abstract class RemoteProcessSupport { protected abstract RunProfileState getRunProfileState(Target target, Parameters configuration, Executor executor) throws ExecutionException; - private boolean getExistingInfo(Ref ref, final Pair key) { - Object info; + private boolean getExistingInfo(Ref ref, Pair key) { + Info info; synchronized (myProcMap) { info = myProcMap.get(key); try { - while (info != null && - (!(info instanceof Info) || ((Info)info).handler.isProcessTerminating() || ((Info)info).handler.isProcessTerminated())) { + while (info != null && (!(info instanceof RunningInfo) || + info.handler.isProcessTerminating() || + info.handler.isProcessTerminated())) { myProcMap.wait(1000); ProgressManager.checkCanceled(); info = myProcMap.get(key); @@ -210,24 +198,21 @@ public abstract class RemoteProcessSupport { myProcMap.put(key, new PendingInfo(ref, null)); } } - if (info != null) { - if (info instanceof Info) { - //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (ref) { - ref.set((Info)info); - ref.notifyAll(); - } + if (info instanceof RunningInfo) { + //noinspection SynchronizationOnLocalVariableOrMethodParameter + synchronized (ref) { + ref.set((RunningInfo)info); + ref.notifyAll(); } - return true; } - return false; + return info != null; } - private EntryPoint acquire(final Info port) throws Exception { - final EntryPoint result = RemoteUtil.executeWithClassLoader(new ThrowableComputable() { + private EntryPoint acquire(final RunningInfo port) throws Exception { + EntryPoint result = RemoteUtil.executeWithClassLoader(new ThrowableComputable() { public EntryPoint compute() throws Exception { - final Registry registry = LocateRegistry.getRegistry("localhost", port.port); - final Remote remote = registry.lookup(port.name); + Registry registry = LocateRegistry.getRegistry("localhost", port.port); + Remote remote = registry.lookup(port.name); if (Remote.class.isAssignableFrom(myValueClass)) { return RemoteUtil.substituteClassLoader(narrowImpl(remote, myValueClass), myValueClass.getClassLoader()); } @@ -249,9 +234,9 @@ public abstract class RemoteProcessSupport { private ProcessListener getProcessListener(final Pair key) { return new ProcessListener() { public void startNotified(ProcessEvent event) { - final ProcessHandler processHandler = event.getProcessHandler(); + ProcessHandler processHandler = event.getProcessHandler(); processHandler.putUserData(ProcessHandler.SILENTLY_DESTROY_ON_CLOSE, Boolean.TRUE); - final Object o; + Info o; synchronized (myProcMap) { o = myProcMap.get(key); if (o instanceof PendingInfo) { @@ -261,15 +246,19 @@ public abstract class RemoteProcessSupport { } public void processTerminated(ProcessEvent event) { - handleProcessTerminated(key, null); - fireModificationCountChanged(); + if (dropProcessInfo(key, null, event.getProcessHandler())) { + fireModificationCountChanged(); + } } public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) { + if (dropProcessInfo(key, null, event.getProcessHandler())) { + fireModificationCountChanged(); + } } public void onTextAvailable(ProcessEvent event, Key outputType) { - final String text = StringUtil.notNullize(event.getText()); + String text = StringUtil.notNullize(event.getText()); if (outputType == ProcessOutputTypes.STDERR) { LOG.warn(text.trim()); } @@ -277,19 +266,19 @@ public abstract class RemoteProcessSupport { LOG.info(text.trim()); } - Info result = null; - final PendingInfo info; + RunningInfo result = null; + PendingInfo info; synchronized (myProcMap) { - final Object o = myProcMap.get(key); + Info o = myProcMap.get(key); logText(key.second, event, outputType, o); if (o instanceof PendingInfo) { info = (PendingInfo)o; if (outputType == ProcessOutputTypes.STDOUT) { - final String prefix = "Port/ID:"; + String prefix = "Port/ID:"; if (text.startsWith(prefix)) { - final String pair = text.substring(prefix.length()).trim(); - final int idx = pair.indexOf("/"); - result = new Info(info.handler, Integer.parseInt(pair.substring(0, idx)), pair.substring(idx + 1)); + String pair = text.substring(prefix.length()).trim(); + int idx = pair.indexOf("/"); + result = new RunningInfo(info.handler, Integer.parseInt(pair.substring(0, idx)), pair.substring(idx + 1)); myProcMap.put(key, result); myProcMap.notifyAll(); } @@ -319,44 +308,58 @@ public abstract class RemoteProcessSupport { }; } - private void handleProcessTerminated(Pair key, @Nullable String errorMessage) { - Object o; - final PendingInfo pendingInfo; + private boolean dropProcessInfo(Pair key, @Nullable String errorMessage, @Nullable ProcessHandler handler) { + Info info; synchronized (myProcMap) { - o = myProcMap.remove(key); - pendingInfo = o instanceof PendingInfo ? (PendingInfo)o : null; - if (pendingInfo != null && (pendingInfo.stderr.length() > 0 || pendingInfo.ref.isNull())) { - if (errorMessage != null) pendingInfo.stderr.append(errorMessage); - pendingInfo.ref.set(new Info(null, -1, pendingInfo.stderr.toString())); + info = myProcMap.get(key); + if (info != null && info.handler != null && info.handler == handler) { + myProcMap.remove(key); + myProcMap.notifyAll(); + } + else { + // different processHandler + info = null; } - myProcMap.notifyAll(); } - if (pendingInfo != null) { + if (info instanceof PendingInfo) { + PendingInfo pendingInfo = (PendingInfo)info; + if (pendingInfo.stderr.length() > 0 || pendingInfo.ref.isNull()) { + if (errorMessage != null) pendingInfo.stderr.append(errorMessage); + pendingInfo.ref.set(new RunningInfo(null, -1, pendingInfo.stderr.toString())); + } synchronized (pendingInfo.ref) { pendingInfo.ref.notifyAll(); } } - } - - private static class PendingInfo { - final Ref ref; - final ProcessHandler handler; - final StringBuilder stderr = new StringBuilder(); - - private PendingInfo(Ref ref, ProcessHandler handler) { - this.ref = ref; - this.handler = handler; - } + return info != null; } private static class Info { final ProcessHandler handler; + + Info(ProcessHandler handler) { + this.handler = handler; + } + } + + private static class PendingInfo extends Info { + final Ref ref; + final StringBuilder stderr = new StringBuilder(); + + PendingInfo(Ref ref, ProcessHandler handler) { + super(handler); + this.ref = ref; + } + + } + + private static class RunningInfo extends Info { final int port; final String name; Object entryPointHardRef; - private Info(ProcessHandler handler, int port, String name) { - this.handler = handler; + RunningInfo(ProcessHandler handler, int port, String name) { + super(handler); this.port = port; this.name = name; }