blob: 7ce6a6b32c75ab64f430e732b7df42b278f649d3 [file] [log] [blame]
/*
* Copyright 2007 Sascha Weinreuter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.intellij.plugins.xsltDebugger;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import org.intellij.plugins.xsltDebugger.impl.XsltDebugProcess;
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
import org.intellij.plugins.xsltDebugger.rt.engine.OutputEventQueue;
import org.intellij.plugins.xsltDebugger.rt.engine.remote.RemoteDebuggerClient;
import org.intellij.plugins.xsltDebugger.ui.StructureTabComponent;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.rmi.ConnectException;
import java.rmi.NotBoundException;
/**
* Establishes the debugger-connection to the started XSLT-process, starts the debugger-session
* and attaches the debugger-UI.
*/
class DebuggerConnector implements Runnable {
private final Project myProject;
private final ProcessHandler myProcess;
private final int myPort;
public DebuggerConnector(Project project, ProcessHandler process, int port) {
myProject = project;
myProcess = process;
myPort = port;
}
public void run() {
final Debugger client = connect();
if (client == null) {
// client will be null if the process terminated prematurely for some reason. no need for an error message
if (!myProcess.isProcessTerminated()) {
myProcess.notifyTextAvailable("Failed to connect to debugged process. Terminating.\n", ProcessOutputTypes.SYSTEM);
myProcess.destroyProcess();
}
return;
}
final XsltDebuggerSession session = XsltDebuggerSession.create(myProject, myProcess, client);
final XsltDebugProcess dbgp = XsltDebugProcess.getInstance(myProcess);
assert dbgp != null;
dbgp.init(client);
session.addListener(new XsltDebuggerSession.Listener() {
@Override
public void debuggerSuspended() {
final OutputEventQueue queue = client.getEventQueue();
StructureTabComponent.getInstance(myProcess).getEventModel().update(queue.getEvents());
}
@Override
public void debuggerResumed() {
}
@Override
public void debuggerStopped() {
try {
final OutputEventQueue queue = client.getEventQueue();
StructureTabComponent.getInstance(myProcess).getEventModel().finalUpdate(queue.getEvents());
} catch (Exception e) {
// can fail when debugger is manually terminated
}
}
});
session.start();
}
@Nullable
private Debugger connect() {
Throwable lastException = null;
for (int i = 0; i < 10; i++) {
if (myProcess.isProcessTerminated()) return null;
try {
final Debugger realClient = EDTGuard.create(new RemoteDebuggerClient(myPort), myProcess);
myProcess.notifyTextAvailable("Connected to XSLT debugger on port " + myPort + "\n", ProcessOutputTypes.SYSTEM);
return realClient;
} catch (ConnectException e) {
lastException = e;
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
break;
}
} catch (NotBoundException e) {
lastException = e;
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
break;
}
} catch (IOException e) {
lastException = e;
break;
}
}
if (lastException != null) {
Logger.getInstance(getClass().getName()).info("Could not connect to debugger", lastException);
if (lastException.getMessage() != null) {
myProcess.notifyTextAvailable("Connection error: " + lastException.getMessage() + "\n", ProcessOutputTypes.SYSTEM);
}
}
return null;
}
}