mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
EA-29052 - EE: RemoteProcessSupport.acquire
This commit is contained in:
@@ -55,8 +55,7 @@ public abstract class RemoteProcessSupport<Target, EntryPoint, Parameters> {
|
||||
public static final Logger LOG = Logger.getInstance("#" + RemoteProcessSupport.class);
|
||||
|
||||
private final Class<EntryPoint> myValueClass;
|
||||
private final HashMap<Pair<Target, Parameters>, Object> myProcMap =
|
||||
new HashMap<Pair<Target, Parameters>, Object>();
|
||||
private final HashMap<Pair<Target, Parameters>, Info> myProcMap = new HashMap<Pair<Target, Parameters>, Info>();
|
||||
|
||||
static {
|
||||
RemoteServer.setupRMI();
|
||||
@@ -78,13 +77,11 @@ public abstract class RemoteProcessSupport<Target, EntryPoint, Parameters> {
|
||||
}
|
||||
|
||||
public void stopAll(boolean wait) {
|
||||
final ArrayList<ProcessHandler> allHandlers = new ArrayList<ProcessHandler>();
|
||||
ArrayList<ProcessHandler> allHandlers = new ArrayList<ProcessHandler>();
|
||||
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<Target, EntryPoint, Parameters> {
|
||||
}
|
||||
|
||||
public List<Parameters> getActiveConfigurations(@NotNull Target target) {
|
||||
final ArrayList<Parameters> result = new ArrayList<Parameters>();
|
||||
ArrayList<Parameters> result = new ArrayList<Parameters>();
|
||||
synchronized (myProcMap) {
|
||||
for (Pair<Target, Parameters> pair : myProcMap.keySet()) {
|
||||
if (pair.first == target) {
|
||||
@@ -108,11 +105,11 @@ public abstract class RemoteProcessSupport<Target, EntryPoint, Parameters> {
|
||||
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<Info> ref = Ref.create(null);
|
||||
final Pair<Target, Parameters> key = Pair.create(target, configuration);
|
||||
Ref<RunningInfo> ref = Ref.create(null);
|
||||
Pair<Target, Parameters> key = Pair.create(target, configuration);
|
||||
if (!getExistingInfo(ref, key)) {
|
||||
startProcess(target, configuration, key);
|
||||
if (ref.isNull()) {
|
||||
@@ -131,38 +128,28 @@ public abstract class RemoteProcessSupport<Target, EntryPoint, Parameters> {
|
||||
}
|
||||
}
|
||||
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<ProcessHandler> handlersToStop = new ArrayList<ProcessHandler>();
|
||||
final ArrayList<Pair<Target, Parameters>> keysToRemove = new ArrayList<Pair<Target, Parameters>>();
|
||||
ArrayList<ProcessHandler> handlers = new ArrayList<ProcessHandler>();
|
||||
synchronized (myProcMap) {
|
||||
for (Pair<Target, Parameters> 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<Target, Parameters> key) {
|
||||
final ProgramRunner runner = new DefaultProgramRunner() {
|
||||
ProgramRunner runner = new DefaultProgramRunner() {
|
||||
@NotNull
|
||||
public String getRunnerId() {
|
||||
return "MyRunner";
|
||||
@@ -172,16 +159,16 @@ public abstract class RemoteProcessSupport<Target, EntryPoint, Parameters> {
|
||||
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<Target, EntryPoint, Parameters> {
|
||||
protected abstract RunProfileState getRunProfileState(Target target, Parameters configuration, Executor executor)
|
||||
throws ExecutionException;
|
||||
|
||||
private boolean getExistingInfo(Ref<Info> ref, final Pair<Target, Parameters> key) {
|
||||
Object info;
|
||||
private boolean getExistingInfo(Ref<RunningInfo> ref, Pair<Target, Parameters> 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<Target, EntryPoint, Parameters> {
|
||||
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<EntryPoint, Exception>() {
|
||||
private EntryPoint acquire(final RunningInfo port) throws Exception {
|
||||
EntryPoint result = RemoteUtil.executeWithClassLoader(new ThrowableComputable<EntryPoint, Exception>() {
|
||||
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<Target, EntryPoint, Parameters> {
|
||||
private ProcessListener getProcessListener(final Pair<Target, Parameters> 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<Target, EntryPoint, Parameters> {
|
||||
}
|
||||
|
||||
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<Target, EntryPoint, Parameters> {
|
||||
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<Target, EntryPoint, Parameters> {
|
||||
};
|
||||
}
|
||||
|
||||
private void handleProcessTerminated(Pair<Target, Parameters> key, @Nullable String errorMessage) {
|
||||
Object o;
|
||||
final PendingInfo pendingInfo;
|
||||
private boolean dropProcessInfo(Pair<Target, Parameters> 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<Info> ref;
|
||||
final ProcessHandler handler;
|
||||
final StringBuilder stderr = new StringBuilder();
|
||||
|
||||
private PendingInfo(Ref<Info> 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<RunningInfo> ref;
|
||||
final StringBuilder stderr = new StringBuilder();
|
||||
|
||||
PendingInfo(Ref<RunningInfo> 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user