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