Revert "Debugger: Image/Icon viewer based on standard image viewer"
[idea/community.git] / java / debugger / impl / src / com / intellij / debugger / engine / DebugProcessImpl.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.debugger.engine;
17
18 import com.intellij.Patches;
19 import com.intellij.debugger.*;
20 import com.intellij.debugger.actions.DebuggerAction;
21 import com.intellij.debugger.actions.DebuggerActions;
22 import com.intellij.debugger.apiAdapters.ConnectionServiceWrapper;
23 import com.intellij.debugger.engine.evaluation.*;
24 import com.intellij.debugger.engine.events.DebuggerCommandImpl;
25 import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
26 import com.intellij.debugger.engine.jdi.ThreadReferenceProxy;
27 import com.intellij.debugger.engine.requests.MethodReturnValueWatcher;
28 import com.intellij.debugger.engine.requests.RequestManagerImpl;
29 import com.intellij.debugger.impl.DebuggerContextImpl;
30 import com.intellij.debugger.impl.DebuggerSession;
31 import com.intellij.debugger.impl.DebuggerUtilsEx;
32 import com.intellij.debugger.impl.PrioritizedTask;
33 import com.intellij.debugger.jdi.StackFrameProxyImpl;
34 import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
35 import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
36 import com.intellij.debugger.settings.DebuggerSettings;
37 import com.intellij.debugger.settings.NodeRendererSettings;
38 import com.intellij.debugger.ui.breakpoints.BreakpointManager;
39 import com.intellij.debugger.ui.breakpoints.RunToCursorBreakpoint;
40 import com.intellij.debugger.ui.breakpoints.StepIntoBreakpoint;
41 import com.intellij.debugger.ui.tree.ValueDescriptor;
42 import com.intellij.debugger.ui.tree.render.*;
43 import com.intellij.execution.CantRunException;
44 import com.intellij.execution.ExecutionException;
45 import com.intellij.execution.ExecutionResult;
46 import com.intellij.execution.configurations.RemoteConnection;
47 import com.intellij.execution.process.*;
48 import com.intellij.execution.runners.ExecutionUtil;
49 import com.intellij.idea.ActionsBundle;
50 import com.intellij.openapi.Disposable;
51 import com.intellij.openapi.application.ApplicationManager;
52 import com.intellij.openapi.diagnostic.Logger;
53 import com.intellij.openapi.editor.Document;
54 import com.intellij.openapi.extensions.Extensions;
55 import com.intellij.openapi.project.Project;
56 import com.intellij.openapi.ui.Messages;
57 import com.intellij.openapi.util.Disposer;
58 import com.intellij.openapi.util.Pair;
59 import com.intellij.openapi.util.Ref;
60 import com.intellij.openapi.util.UserDataHolderBase;
61 import com.intellij.openapi.util.text.StringUtil;
62 import com.intellij.openapi.wm.ToolWindowId;
63 import com.intellij.openapi.wm.impl.status.StatusBarUtil;
64 import com.intellij.psi.PsiDocumentManager;
65 import com.intellij.psi.PsiFile;
66 import com.intellij.psi.search.GlobalSearchScope;
67 import com.intellij.ui.classFilter.ClassFilter;
68 import com.intellij.ui.classFilter.DebuggerClassFilterProvider;
69 import com.intellij.util.Alarm;
70 import com.intellij.util.EventDispatcher;
71 import com.intellij.util.StringBuilderSpinAllocator;
72 import com.intellij.util.concurrency.Semaphore;
73 import com.intellij.util.containers.ContainerUtil;
74 import com.intellij.util.containers.HashMap;
75 import com.intellij.util.ui.UIUtil;
76 import com.intellij.xdebugger.XDebugSession;
77 import com.intellij.xdebugger.impl.actions.XDebuggerActions;
78 import com.sun.jdi.*;
79 import com.sun.jdi.connect.*;
80 import com.sun.jdi.request.EventRequest;
81 import com.sun.jdi.request.EventRequestManager;
82 import com.sun.jdi.request.StepRequest;
83 import org.jetbrains.annotations.NonNls;
84 import org.jetbrains.annotations.NotNull;
85 import org.jetbrains.annotations.Nullable;
86
87 import javax.swing.*;
88 import java.io.IOException;
89 import java.net.UnknownHostException;
90 import java.util.*;
91 import java.util.concurrent.atomic.AtomicInteger;
92
93 public abstract class DebugProcessImpl extends UserDataHolderBase implements DebugProcess {
94   private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.DebugProcessImpl");
95
96   @NonNls private static final String SOCKET_ATTACHING_CONNECTOR_NAME = "com.sun.jdi.SocketAttach";
97   @NonNls private static final String SHMEM_ATTACHING_CONNECTOR_NAME = "com.sun.jdi.SharedMemoryAttach";
98   @NonNls private static final String SOCKET_LISTENING_CONNECTOR_NAME = "com.sun.jdi.SocketListen";
99   @NonNls private static final String SHMEM_LISTENING_CONNECTOR_NAME = "com.sun.jdi.SharedMemoryListen";
100
101   private final Project myProject;
102   private final RequestManagerImpl myRequestManager;
103
104   private volatile VirtualMachineProxyImpl myVirtualMachineProxy = null;
105   protected EventDispatcher<DebugProcessListener> myDebugProcessDispatcher = EventDispatcher.create(DebugProcessListener.class);
106   protected EventDispatcher<EvaluationListener> myEvaluationDispatcher = EventDispatcher.create(EvaluationListener.class);
107
108   private final List<ProcessListener> myProcessListeners = ContainerUtil.createLockFreeCopyOnWriteList();
109
110   protected static final int STATE_INITIAL   = 0;
111   protected static final int STATE_ATTACHED  = 1;
112   protected static final int STATE_DETACHING = 2;
113   protected static final int STATE_DETACHED  = 3;
114   protected final AtomicInteger myState = new AtomicInteger(STATE_INITIAL);
115
116   private ExecutionResult myExecutionResult;
117   private RemoteConnection myConnection;
118   private JavaDebugProcess myXDebugProcess;
119
120   private ConnectionServiceWrapper myConnectionService;
121   private Map<String, Connector.Argument> myArguments;
122
123   private final List<NodeRenderer> myRenderers = new ArrayList<NodeRenderer>();
124
125   // we use null key here
126   private final Map<Type, NodeRenderer> myNodeRenderersMap = new HashMap<Type, NodeRenderer>();
127
128   private final NodeRendererSettingsListener mySettingsListener = new NodeRendererSettingsListener() {
129     @Override
130     public void renderersChanged() {
131       myNodeRenderersMap.clear();
132       myRenderers.clear();
133       loadRenderers();
134     }
135   };
136
137   private final SuspendManagerImpl mySuspendManager = new SuspendManagerImpl(this);
138   protected CompoundPositionManager myPositionManager = null;
139   private volatile DebuggerManagerThreadImpl myDebuggerManagerThread;
140   private static final int LOCAL_START_TIMEOUT = 30000;
141
142   private final Semaphore myWaitFor = new Semaphore();
143   private boolean myIsFailed = false;
144   protected DebuggerSession mySession;
145   @Nullable protected MethodReturnValueWatcher myReturnValueWatcher;
146   private final Disposable myDisposable = Disposer.newDisposable();
147   private final Alarm myStatusUpdateAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, myDisposable);
148
149   protected DebugProcessImpl(Project project) {
150     myProject = project;
151     myRequestManager = new RequestManagerImpl(this);
152     NodeRendererSettings.getInstance().addListener(mySettingsListener);
153     loadRenderers();
154   }
155
156   private void loadRenderers() {
157     getManagerThread().invoke(new DebuggerCommandImpl() {
158       @Override
159       protected void action() throws Exception {
160         try {
161           final NodeRendererSettings rendererSettings = NodeRendererSettings.getInstance();
162           for (final NodeRenderer renderer : rendererSettings.getAllRenderers()) {
163             if (renderer.isEnabled()) {
164               myRenderers.add(renderer);
165             }
166           }
167         }
168         finally {
169           DebuggerInvocationUtil.swingInvokeLater(myProject, new Runnable() {
170             @Override
171             public void run() {
172               final DebuggerSession session = mySession;
173               if (session != null && session.isAttached()) {
174                 session.refresh(true);
175                 DebuggerAction.refreshViews(mySession.getXDebugSession());
176               }
177             }
178           });
179         }
180       }
181     });
182   }
183
184   @Nullable
185   public Pair<Method, Value> getLastExecutedMethod() {
186     final MethodReturnValueWatcher watcher = myReturnValueWatcher;
187     if (watcher == null) {
188       return null;
189     }
190     final Method method = watcher.getLastExecutedMethod();
191     if (method == null) {
192       return null;
193     }
194     return Pair.create(method, watcher.getLastMethodReturnValue());
195   }
196
197   public void setWatchMethodReturnValuesEnabled(boolean enabled) {
198     final MethodReturnValueWatcher watcher = myReturnValueWatcher;
199     if (watcher != null) {
200       watcher.setFeatureEnabled(enabled);
201     }
202   }
203
204   public boolean isWatchMethodReturnValuesEnabled() {
205     final MethodReturnValueWatcher watcher = myReturnValueWatcher;
206     return watcher != null && watcher.isFeatureEnabled();
207   }
208
209   public boolean canGetMethodReturnValue() {
210     return myReturnValueWatcher != null;
211   }
212
213   public NodeRenderer getAutoRenderer(ValueDescriptor descriptor) {
214     DebuggerManagerThreadImpl.assertIsManagerThread();
215     final Value value = descriptor.getValue();
216     Type type = value != null ? value.type() : null;
217
218     // in case evaluation is not possible, force default renderer
219     if (!DebuggerManagerEx.getInstanceEx(getProject()).getContext().isEvaluationPossible()) {
220       return getDefaultRenderer(type);
221     }
222
223     NodeRenderer renderer = myNodeRenderersMap.get(type);
224     if(renderer == null) {
225       for (final NodeRenderer nodeRenderer : myRenderers) {
226         if (nodeRenderer.isApplicable(type)) {
227           renderer = nodeRenderer;
228           break;
229         }
230       }
231       if (renderer == null) {
232         renderer = getDefaultRenderer(type);
233       }
234       myNodeRenderersMap.put(type, renderer);
235     }
236
237     return renderer;
238   }
239
240   public static NodeRenderer getDefaultRenderer(Value value) {
241     return getDefaultRenderer(value != null ? value.type() : null);
242   }
243
244   public static NodeRenderer getDefaultRenderer(Type type) {
245     final NodeRendererSettings settings = NodeRendererSettings.getInstance();
246
247     final PrimitiveRenderer primitiveRenderer = settings.getPrimitiveRenderer();
248     if(primitiveRenderer.isApplicable(type)) {
249       return primitiveRenderer;
250     }
251
252     final ArrayRenderer arrayRenderer = settings.getArrayRenderer();
253     if(arrayRenderer.isApplicable(type)) {
254       return arrayRenderer;
255     }
256
257     final ClassRenderer classRenderer = settings.getClassRenderer();
258     LOG.assertTrue(classRenderer.isApplicable(type), type.name());
259     return classRenderer;
260   }
261
262
263   @SuppressWarnings({"HardCodedStringLiteral"})
264   protected void commitVM(VirtualMachine vm) {
265     if (!isInInitialState()) {
266       LOG.error("State is invalid " + myState.get());
267     }
268     DebuggerManagerThreadImpl.assertIsManagerThread();
269     myPositionManager = createPositionManager();
270     if (LOG.isDebugEnabled()) {
271       LOG.debug("*******************VM attached******************");
272     }
273     checkVirtualMachineVersion(vm);
274
275     myVirtualMachineProxy = new VirtualMachineProxyImpl(this, vm);
276
277     String trace = System.getProperty("idea.debugger.trace");
278     if (trace != null) {
279       int mask = 0;
280       StringTokenizer tokenizer = new StringTokenizer(trace);
281       while (tokenizer.hasMoreTokens()) {
282         String token = tokenizer.nextToken();
283         if ("SENDS".compareToIgnoreCase(token) == 0) {
284           mask |= VirtualMachine.TRACE_SENDS;
285         }
286         else if ("RAW_SENDS".compareToIgnoreCase(token) == 0) {
287           mask |= 0x01000000;
288         }
289         else if ("RECEIVES".compareToIgnoreCase(token) == 0) {
290           mask |= VirtualMachine.TRACE_RECEIVES;
291         }
292         else if ("RAW_RECEIVES".compareToIgnoreCase(token) == 0) {
293           mask |= 0x02000000;
294         }
295         else if ("EVENTS".compareToIgnoreCase(token) == 0) {
296           mask |= VirtualMachine.TRACE_EVENTS;
297         }
298         else if ("REFTYPES".compareToIgnoreCase(token) == 0) {
299           mask |= VirtualMachine.TRACE_REFTYPES;
300         }
301         else if ("OBJREFS".compareToIgnoreCase(token) == 0) {
302           mask |= VirtualMachine.TRACE_OBJREFS;
303         }
304         else if ("ALL".compareToIgnoreCase(token) == 0) {
305           mask |= VirtualMachine.TRACE_ALL;
306         }
307       }
308
309       vm.setDebugTraceMode(mask);
310     }
311   }
312
313   private void stopConnecting() {
314     DebuggerManagerThreadImpl.assertIsManagerThread();
315
316     Map<String, Connector.Argument> arguments = myArguments;
317     try {
318       if (arguments == null) {
319         return;
320       }
321       if(myConnection.isServerMode()) {
322         ListeningConnector connector = (ListeningConnector)findConnector(SOCKET_LISTENING_CONNECTOR_NAME);
323         if (connector == null) {
324           LOG.error("Cannot find connector: " + SOCKET_LISTENING_CONNECTOR_NAME);
325         }
326         else {
327           connector.stopListening(arguments);
328         }
329       }
330       else {
331         if(myConnectionService != null) {
332           myConnectionService.close();
333         }
334       }
335     }
336     catch (IOException e) {
337       if (LOG.isDebugEnabled()) {
338         LOG.debug(e);
339       }
340     }
341     catch (IllegalConnectorArgumentsException e) {
342       if (LOG.isDebugEnabled()) {
343         LOG.debug(e);
344       }
345     }
346     catch (ExecutionException e) {
347       LOG.error(e);
348     }
349     finally {
350       closeProcess(true);
351     }
352   }
353
354   protected CompoundPositionManager createPositionManager() {
355     return new CompoundPositionManager(new PositionManagerImpl(this));
356   }
357
358   @Override
359   public void printToConsole(final String text) {
360     myExecutionResult.getProcessHandler().notifyTextAvailable(text, ProcessOutputTypes.SYSTEM);
361   }
362
363   @Override
364   public ProcessHandler getProcessHandler() {
365     return myExecutionResult.getProcessHandler();
366   }
367
368   /**
369    *
370    * @param suspendContext
371    * @param stepThread
372    * @param depth
373    * @param hint may be null
374    */
375   protected void doStep(final SuspendContextImpl suspendContext, final ThreadReferenceProxyImpl stepThread, int depth, RequestHint hint) {
376     if (stepThread == null) {
377       return;
378     }
379     try {
380       final ThreadReference stepThreadReference = stepThread.getThreadReference();
381       if (LOG.isDebugEnabled()) {
382         LOG.debug("DO_STEP: creating step request for " + stepThreadReference);
383       }
384       deleteStepRequests(stepThreadReference);
385       EventRequestManager requestManager = getVirtualMachineProxy().eventRequestManager();
386       StepRequest stepRequest = requestManager.createStepRequest(stepThreadReference, StepRequest.STEP_LINE, depth);
387       if (!(hint != null && hint.isIgnoreFilters()) /*&& depth == StepRequest.STEP_INTO*/) {
388         final List<ClassFilter> activeFilters = new ArrayList<ClassFilter>();
389         DebuggerSettings settings = DebuggerSettings.getInstance();
390         if (settings.TRACING_FILTERS_ENABLED) {
391           for (ClassFilter filter : settings.getSteppingFilters()) {
392             if (filter.isEnabled()) {
393               activeFilters.add(filter);
394             }
395           }
396         }
397         for (DebuggerClassFilterProvider provider : Extensions.getExtensions(DebuggerClassFilterProvider.EP_NAME)) {
398           for (ClassFilter filter : provider.getFilters()) {
399             if (filter.isEnabled()) {
400               activeFilters.add(filter);
401             }
402           }
403         }
404
405         if (!activeFilters.isEmpty()) {
406           final String currentClassName = getCurrentClassName(stepThread);
407           if (currentClassName == null || !DebuggerUtilsEx.isFiltered(currentClassName, activeFilters)) {
408             // add class filters
409             for (ClassFilter filter : activeFilters) {
410               stepRequest.addClassExclusionFilter(filter.getPattern());
411             }
412           }
413         }
414       }
415
416       // suspend policy to match the suspend policy of the context:
417       // if all threads were suspended, then during stepping all the threads must be suspended
418       // if only event thread were suspended, then only this particular thread must be suspended during stepping
419       stepRequest.setSuspendPolicy(suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD? EventRequest.SUSPEND_EVENT_THREAD : EventRequest.SUSPEND_ALL);
420
421       if (hint != null) {
422         //noinspection HardCodedStringLiteral
423         stepRequest.putProperty("hint", hint);
424       }
425       stepRequest.enable();
426     }
427     catch (ObjectCollectedException ignored) {
428
429     }
430   }
431
432   void deleteStepRequests(@Nullable final ThreadReference stepThread) {
433     EventRequestManager requestManager = getVirtualMachineProxy().eventRequestManager();
434     List<StepRequest> stepRequests = requestManager.stepRequests();
435     if (!stepRequests.isEmpty()) {
436       final List<StepRequest> toDelete = new ArrayList<StepRequest>(stepRequests.size());
437       for (final StepRequest request : stepRequests) {
438         ThreadReference threadReference = request.thread();
439         // [jeka] on attempt to delete a request assigned to a thread with unknown status, a JDWP error occurs
440         try {
441           if (threadReference.status() != ThreadReference.THREAD_STATUS_UNKNOWN && (stepThread == null || stepThread.equals(threadReference))) {
442             toDelete.add(request);
443           }
444         }
445         catch (IllegalThreadStateException e) {
446           LOG.info(e); // undocumented by JDI: may be thrown when querying thread status
447         }
448       }
449       requestManager.deleteEventRequests(toDelete);
450     }
451   }
452
453   @Nullable
454   private static String getCurrentClassName(ThreadReferenceProxyImpl thread) {
455     try {
456       if (thread != null && thread.frameCount() > 0) {
457         StackFrameProxyImpl stackFrame = thread.frame(0);
458         if (stackFrame != null) {
459           Location location = stackFrame.location();
460           ReferenceType referenceType = location == null ? null : location.declaringType();
461           if (referenceType != null) {
462             return referenceType.name();
463           }
464         }
465       }
466     }
467     catch (EvaluateException ignored) {
468     }
469     return null;
470   }
471
472   private VirtualMachine createVirtualMachineInt() throws ExecutionException {
473     try {
474       if (myArguments != null) {
475         throw new IOException(DebuggerBundle.message("error.debugger.already.listening"));
476       }
477
478       final String address = myConnection.getAddress();
479       if (myConnection.isServerMode()) {
480         ListeningConnector connector = (ListeningConnector)findConnector(
481           myConnection.isUseSockets() ? SOCKET_LISTENING_CONNECTOR_NAME : SHMEM_LISTENING_CONNECTOR_NAME);
482         if (connector == null) {
483           throw new CantRunException(DebuggerBundle.message("error.debug.connector.not.found", DebuggerBundle.getTransportName(myConnection)));
484         }
485         myArguments = connector.defaultArguments();
486         if (myArguments == null) {
487           throw new CantRunException(DebuggerBundle.message("error.no.debug.listen.port"));
488         }
489
490         if (address == null) {
491           throw new CantRunException(DebuggerBundle.message("error.no.debug.listen.port"));
492         }
493         // negative port number means the caller leaves to debugger to decide at which port to listen
494         //noinspection HardCodedStringLiteral
495         final Connector.Argument portArg = myConnection.isUseSockets() ? myArguments.get("port") : myArguments.get("name");
496         if (portArg != null) {
497           portArg.setValue(address);
498         }
499         //noinspection HardCodedStringLiteral
500         final Connector.Argument timeoutArg = myArguments.get("timeout");
501         if (timeoutArg != null) {
502           timeoutArg.setValue("0"); // wait forever
503         }
504         connector.startListening(myArguments);
505         myDebugProcessDispatcher.getMulticaster().connectorIsReady();
506         try {
507           return connector.accept(myArguments);
508         }
509         finally {
510           if(myArguments != null) {
511             try {
512               connector.stopListening(myArguments);
513             }
514             catch (IllegalArgumentException ignored) {
515               // ignored
516             }
517             catch (IllegalConnectorArgumentsException ignored) {
518               // ignored
519             }
520           }
521         }
522       }
523       else { // is client mode, should attach to already running process
524         AttachingConnector connector = (AttachingConnector)findConnector(
525           myConnection.isUseSockets() ? SOCKET_ATTACHING_CONNECTOR_NAME : SHMEM_ATTACHING_CONNECTOR_NAME
526         );
527
528         if (connector == null) {
529           throw new CantRunException( DebuggerBundle.message("error.debug.connector.not.found", DebuggerBundle.getTransportName(myConnection)));
530         }
531         myArguments = connector.defaultArguments();
532         if (myConnection.isUseSockets()) {
533           //noinspection HardCodedStringLiteral
534           final Connector.Argument hostnameArg = myArguments.get("hostname");
535           if (hostnameArg != null && myConnection.getHostName() != null) {
536             hostnameArg.setValue(myConnection.getHostName());
537           }
538           if (address == null) {
539             throw new CantRunException(DebuggerBundle.message("error.no.debug.attach.port"));
540           }
541           //noinspection HardCodedStringLiteral
542           final Connector.Argument portArg = myArguments.get("port");
543           if (portArg != null) {
544             portArg.setValue(address);
545           }
546         }
547         else {
548           if (address == null) {
549             throw new CantRunException(DebuggerBundle.message("error.no.shmem.address"));
550           }
551           //noinspection HardCodedStringLiteral
552           final Connector.Argument nameArg = myArguments.get("name");
553           if (nameArg != null) {
554             nameArg.setValue(address);
555           }
556         }
557         //noinspection HardCodedStringLiteral
558         final Connector.Argument timeoutArg = myArguments.get("timeout");
559         if (timeoutArg != null) {
560           timeoutArg.setValue("0"); // wait forever
561         }
562
563         myDebugProcessDispatcher.getMulticaster().connectorIsReady();
564         try {
565           return connector.attach(myArguments);
566         }
567         catch (IllegalArgumentException e) {
568           throw new CantRunException(e.getLocalizedMessage());
569         }
570       }
571     }
572     catch (IOException e) {
573       throw new ExecutionException(processIOException(e, DebuggerBundle.getAddressDisplayName(myConnection)), e);
574     }
575     catch (IllegalConnectorArgumentsException e) {
576       throw new ExecutionException(processError(e), e);
577     }
578     finally {
579       myArguments = null;
580       myConnectionService = null;
581     }
582   }
583
584   public void showStatusText(final String text) {
585     if (!myStatusUpdateAlarm.isDisposed()) {
586       myStatusUpdateAlarm.cancelAllRequests();
587       myStatusUpdateAlarm.addRequest(new Runnable() {
588         @Override
589         public void run() {
590           StatusBarUtil.setStatusBarInfo(myProject, text);
591         }
592       }, 50);
593     }
594   }
595
596   static Connector findConnector(String connectorName) throws ExecutionException {
597     VirtualMachineManager virtualMachineManager;
598     try {
599       virtualMachineManager = Bootstrap.virtualMachineManager();
600     }
601     catch (Error e) {
602       final String error = e.getClass().getName() + " : " + e.getLocalizedMessage();
603       throw new ExecutionException(DebuggerBundle.message("debugger.jdi.bootstrap.error", error));
604     }
605     List connectors;
606     if (SOCKET_ATTACHING_CONNECTOR_NAME.equals(connectorName) || SHMEM_ATTACHING_CONNECTOR_NAME.equals(connectorName)) {
607       connectors = virtualMachineManager.attachingConnectors();
608     }
609     else if (SOCKET_LISTENING_CONNECTOR_NAME.equals(connectorName) || SHMEM_LISTENING_CONNECTOR_NAME.equals(connectorName)) {
610       connectors = virtualMachineManager.listeningConnectors();
611     }
612     else {
613       return null;
614     }
615     for (Object connector1 : connectors) {
616       Connector connector = (Connector)connector1;
617       if (connectorName.equals(connector.name())) {
618         return connector;
619       }
620     }
621     return null;
622   }
623
624   private void checkVirtualMachineVersion(VirtualMachine vm) {
625     final String version = vm.version();
626     if ("1.4.0".equals(version)) {
627       SwingUtilities.invokeLater(new Runnable() {
628         @Override
629         public void run() {
630           Messages.showMessageDialog(
631             getProject(),
632             DebuggerBundle.message("warning.jdk140.unstable"), DebuggerBundle.message("title.jdk140.unstable"), Messages.getWarningIcon()
633           );
634         }
635       });
636     }
637   }
638
639   /*Event dispatching*/
640   public void addEvaluationListener(EvaluationListener evaluationListener) {
641     myEvaluationDispatcher.addListener(evaluationListener);
642   }
643
644   public void removeEvaluationListener(EvaluationListener evaluationListener) {
645     myEvaluationDispatcher.removeListener(evaluationListener);
646   }
647
648   @Override
649   public void addDebugProcessListener(DebugProcessListener listener) {
650     myDebugProcessDispatcher.addListener(listener);
651   }
652
653   @Override
654   public void removeDebugProcessListener(DebugProcessListener listener) {
655     myDebugProcessDispatcher.removeListener(listener);
656   }
657
658   public void addProcessListener(ProcessListener processListener) {
659     synchronized(myProcessListeners) {
660       if(getProcessHandler() != null) {
661         getProcessHandler().addProcessListener(processListener);
662       }
663       else {
664         myProcessListeners.add(processListener);
665       }
666     }
667   }
668
669   public void removeProcessListener(ProcessListener processListener) {
670     synchronized (myProcessListeners) {
671       if(getProcessHandler() != null) {
672         getProcessHandler().removeProcessListener(processListener);
673       }
674       else {
675         myProcessListeners.remove(processListener);
676       }
677     }
678   }
679
680   /* getters */
681   public RemoteConnection getConnection() {
682     return myConnection;
683   }
684
685   @Override
686   public ExecutionResult getExecutionResult() {
687     return myExecutionResult;
688   }
689
690   @Override
691   public Project getProject() {
692     return myProject;
693   }
694
695   public boolean canRedefineClasses() {
696     final VirtualMachineProxyImpl vm = myVirtualMachineProxy;
697     return vm != null && vm.canRedefineClasses();
698   }
699
700   public boolean canWatchFieldModification() {
701     final VirtualMachineProxyImpl vm = myVirtualMachineProxy;
702     return vm != null && vm.canWatchFieldModification();
703   }
704
705   public boolean isInInitialState() {
706     return myState.get() == STATE_INITIAL;
707   }
708
709   @Override
710   public boolean isAttached() {
711     return myState.get() == STATE_ATTACHED;
712   }
713
714   @Override
715   public boolean isDetached() {
716     return myState.get() == STATE_DETACHED;
717   }
718
719   @Override
720   public boolean isDetaching() {
721     return myState.get() == STATE_DETACHING;
722   }
723
724   @Override
725   public RequestManagerImpl getRequestsManager() {
726     return myRequestManager;
727   }
728
729   @Override
730   public VirtualMachineProxyImpl getVirtualMachineProxy() {
731     DebuggerManagerThreadImpl.assertIsManagerThread();
732     final VirtualMachineProxyImpl vm = myVirtualMachineProxy;
733     if (vm == null) {
734       throw new VMDisconnectedException();
735     }
736     return vm;
737   }
738
739   @Override
740   public void appendPositionManager(final PositionManager positionManager) {
741     DebuggerManagerThreadImpl.assertIsManagerThread();
742     myPositionManager.appendPositionManager(positionManager);
743   }
744
745   private volatile RunToCursorBreakpoint myRunToCursorBreakpoint;
746
747   public void cancelRunToCursorBreakpoint() {
748     DebuggerManagerThreadImpl.assertIsManagerThread();
749     final RunToCursorBreakpoint runToCursorBreakpoint = myRunToCursorBreakpoint;
750     if (runToCursorBreakpoint != null) {
751       myRunToCursorBreakpoint = null;
752       getRequestsManager().deleteRequest(runToCursorBreakpoint);
753       if (runToCursorBreakpoint.isRestoreBreakpoints()) {
754         final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(getProject()).getBreakpointManager();
755         breakpointManager.enableBreakpoints(this);
756       }
757     }
758   }
759
760   protected void closeProcess(boolean closedByUser) {
761     DebuggerManagerThreadImpl.assertIsManagerThread();
762
763     if (myState.compareAndSet(STATE_INITIAL, STATE_DETACHING) || myState.compareAndSet(STATE_ATTACHED, STATE_DETACHING)) {
764       try {
765         getManagerThread().close();
766       }
767       finally {
768         final VirtualMachineProxyImpl vm = myVirtualMachineProxy;
769         myVirtualMachineProxy = null;
770         myPositionManager = null;
771         myReturnValueWatcher = null;
772         myNodeRenderersMap.clear();
773         myRenderers.clear();
774         DebuggerUtils.cleanupAfterProcessFinish(this);
775         myState.set(STATE_DETACHED);
776         try {
777           myDebugProcessDispatcher.getMulticaster().processDetached(this, closedByUser);
778         }
779         finally {
780           //if (DebuggerSettings.getInstance().UNMUTE_ON_STOP) {
781           //  XDebugSession session = mySession.getXDebugSession();
782           //  if (session != null) {
783           //    session.setBreakpointMuted(false);
784           //  }
785           //}
786           if (vm != null) {
787             try {
788               vm.dispose(); // to be on the safe side ensure that VM mirror, if present, is disposed and invalidated
789             }
790             catch (Throwable ignored) {
791             }
792           }
793           myWaitFor.up();
794         }
795       }
796
797     }
798   }
799
800   private static String formatMessage(String message) {
801     final int lineLength = 90;
802     StringBuilder buf = new StringBuilder(message.length());
803     int index = 0;
804     while (index < message.length()) {
805       buf.append(message.substring(index, Math.min(index + lineLength, message.length()))).append('\n');
806       index += lineLength;
807     }
808     return buf.toString();
809   }
810
811   public static String processError(Exception e) {
812     String message;
813
814     if (e instanceof VMStartException) {
815       VMStartException e1 = (VMStartException)e;
816       message = e1.getLocalizedMessage();
817     }
818     else if (e instanceof IllegalConnectorArgumentsException) {
819       IllegalConnectorArgumentsException e1 = (IllegalConnectorArgumentsException)e;
820       final List<String> invalidArgumentNames = e1.argumentNames();
821       message = formatMessage(DebuggerBundle.message("error.invalid.argument", invalidArgumentNames.size()) + ": "+ e1.getLocalizedMessage()) + invalidArgumentNames;
822       if (LOG.isDebugEnabled()) {
823         LOG.debug(e1);
824       }
825     }
826     else if (e instanceof CantRunException) {
827       message = e.getLocalizedMessage();
828     }
829     else if (e instanceof VMDisconnectedException) {
830       message = DebuggerBundle.message("error.vm.disconnected");
831     }
832     else if (e instanceof IOException) {
833       message = processIOException((IOException)e, null);
834     }
835     else if (e instanceof ExecutionException) {
836       message = e.getLocalizedMessage();
837     }
838     else  {
839       message = DebuggerBundle.message("error.exception.while.connecting", e.getClass().getName(), e.getLocalizedMessage());
840       if (LOG.isDebugEnabled()) {
841         LOG.debug(e);
842       }
843     }
844     return message;
845   }
846
847   @NotNull
848   public static String processIOException(@NotNull IOException e, @Nullable String address) {
849     if (e instanceof UnknownHostException) {
850       return DebuggerBundle.message("error.unknown.host") + (address != null ? " (" + address + ")" : "") + ":\n" + e.getLocalizedMessage();
851     }
852
853     String message;
854     final StringBuilder buf = StringBuilderSpinAllocator.alloc();
855     try {
856       buf.append(DebuggerBundle.message("error.cannot.open.debugger.port"));
857       if (address != null) {
858         buf.append(" (").append(address).append(")");
859       }
860       buf.append(": ");
861       buf.append(e.getClass().getName()).append(" ");
862       final String localizedMessage = e.getLocalizedMessage();
863       if (!StringUtil.isEmpty(localizedMessage)) {
864         buf.append('"');
865         buf.append(localizedMessage);
866         buf.append('"');
867       }
868       if (LOG.isDebugEnabled()) {
869         LOG.debug(e);
870       }
871       message = buf.toString();
872     }
873     finally {
874       StringBuilderSpinAllocator.dispose(buf);
875     }
876     return message;
877   }
878
879   public void dispose() {
880     NodeRendererSettings.getInstance().removeListener(mySettingsListener);
881     Disposer.dispose(myDisposable);
882     myRequestManager.setFilterThread(null);
883   }
884
885   @Override
886   public DebuggerManagerThreadImpl getManagerThread() {
887     if (myDebuggerManagerThread == null) {
888       synchronized (this) {
889         if (myDebuggerManagerThread == null) {
890           myDebuggerManagerThread = new DebuggerManagerThreadImpl(myDisposable, getProject());
891         }
892       }
893     }
894     return myDebuggerManagerThread;
895   }
896
897   private static int getInvokePolicy(SuspendContext suspendContext) {
898     //return ThreadReference.INVOKE_SINGLE_THREADED;
899     return suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD ? ObjectReference.INVOKE_SINGLE_THREADED : 0;
900   }
901
902   @Override
903   public void waitFor() {
904     LOG.assertTrue(!DebuggerManagerThreadImpl.isManagerThread());
905     myWaitFor.waitFor();
906   }
907
908   @Override
909   public void waitFor(long timeout) {
910     LOG.assertTrue(!DebuggerManagerThreadImpl.isManagerThread());
911     myWaitFor.waitFor(timeout);
912   }
913
914   private abstract class InvokeCommand <E extends Value> {
915     private final List myArgs;
916
917     protected InvokeCommand(List args) {
918       if (!args.isEmpty()) {
919         myArgs = new ArrayList(args);
920       }
921       else {
922         myArgs = args;
923       }
924     }
925
926     public String toString() {
927       return "INVOKE: " + super.toString();
928     }
929
930     protected abstract E invokeMethod(int invokePolicy, final List args) throws InvocationException,
931                                                                                 ClassNotLoadedException,
932                                                                                 IncompatibleThreadStateException,
933                                                                                 InvalidTypeException;
934
935
936     E start(EvaluationContextImpl evaluationContext, Method method, boolean internalEvaluate) throws EvaluateException {
937       while (true) {
938         try {
939           return startInternal(evaluationContext, method, internalEvaluate);
940         }
941         catch (ClassNotLoadedException e) {
942           ReferenceType loadedClass = null;
943           try {
944             if (evaluationContext.isAutoLoadClasses()) {
945               loadedClass = loadClass(evaluationContext, e.className(), evaluationContext.getClassLoader());
946             }
947           }
948           catch (Exception ignored) {
949             loadedClass = null;
950           }
951           if (loadedClass == null) {
952             throw EvaluateExceptionUtil.createEvaluateException(e);
953           }
954         }
955       }
956     }
957
958     E startInternal(EvaluationContextImpl evaluationContext, Method method, boolean internalEvaluate)
959       throws EvaluateException, ClassNotLoadedException {
960       DebuggerManagerThreadImpl.assertIsManagerThread();
961       SuspendContextImpl suspendContext = evaluationContext.getSuspendContext();
962       SuspendManagerUtil.assertSuspendContext(suspendContext);
963
964       ThreadReferenceProxyImpl invokeThread = suspendContext.getThread();
965
966       if (SuspendManagerUtil.isEvaluating(getSuspendManager(), invokeThread)) {
967         throw EvaluateExceptionUtil.NESTED_EVALUATION_ERROR;
968       }
969
970       Set<SuspendContextImpl> suspendingContexts = SuspendManagerUtil.getSuspendingContexts(getSuspendManager(), invokeThread);
971       final ThreadReference invokeThreadRef = invokeThread.getThreadReference();
972
973       myEvaluationDispatcher.getMulticaster().evaluationStarted(suspendContext);
974       beforeMethodInvocation(suspendContext, method, internalEvaluate);
975
976       Object resumeData = null;
977       try {
978         for (SuspendContextImpl suspendingContext : suspendingContexts) {
979           final ThreadReferenceProxyImpl suspendContextThread = suspendingContext.getThread();
980           if (suspendContextThread != invokeThread) {
981             if (LOG.isDebugEnabled()) {
982               LOG.debug("Resuming " + invokeThread + " that is paused by " + suspendContextThread);
983             }
984             LOG.assertTrue(suspendContextThread == null || !invokeThreadRef.equals(suspendContextThread.getThreadReference()));
985             getSuspendManager().resumeThread(suspendingContext, invokeThread);
986           }
987         }
988
989         resumeData = SuspendManagerUtil.prepareForResume(suspendContext);
990         suspendContext.setIsEvaluating(evaluationContext);
991
992         getVirtualMachineProxy().clearCaches();
993
994         return invokeMethodAndFork(suspendContext);
995       }
996       catch (InvocationException e) {
997         throw EvaluateExceptionUtil.createEvaluateException(e);
998       }
999       catch (IncompatibleThreadStateException e) {
1000         throw EvaluateExceptionUtil.createEvaluateException(e);
1001       }
1002       catch (InvalidTypeException e) {
1003         throw EvaluateExceptionUtil.createEvaluateException(e);
1004       }
1005       catch (ObjectCollectedException e) {
1006         throw EvaluateExceptionUtil.createEvaluateException(e);
1007       }
1008       catch (UnsupportedOperationException e) {
1009         throw EvaluateExceptionUtil.createEvaluateException(e);
1010       }
1011       catch (InternalException e) {
1012         throw EvaluateExceptionUtil.createEvaluateException(e);
1013       }
1014       finally {
1015         suspendContext.setIsEvaluating(null);
1016         if (resumeData != null) {
1017           SuspendManagerUtil.restoreAfterResume(suspendContext, resumeData);
1018         }
1019         for (SuspendContextImpl suspendingContext : mySuspendManager.getEventContexts()) {
1020           if (suspendingContexts.contains(suspendingContext) && !suspendingContext.isEvaluating() && !suspendingContext.suspends(invokeThread)) {
1021             mySuspendManager.suspendThread(suspendingContext, invokeThread);
1022           }
1023         }
1024
1025         if (LOG.isDebugEnabled()) {
1026           LOG.debug("getVirtualMachine().clearCaches()");
1027         }
1028         getVirtualMachineProxy().clearCaches();
1029         afterMethodInvocation(suspendContext, internalEvaluate);
1030
1031         myEvaluationDispatcher.getMulticaster().evaluationFinished(suspendContext);
1032       }
1033     }
1034
1035     private E invokeMethodAndFork(final SuspendContextImpl context) throws InvocationException,
1036                                                                            ClassNotLoadedException,
1037                                                                            IncompatibleThreadStateException,
1038                                                                            InvalidTypeException {
1039       final int invokePolicy = getInvokePolicy(context);
1040       final Exception[] exception = new Exception[1];
1041       final Value[] result = new Value[1];
1042       getManagerThread().startLongProcessAndFork(new Runnable() {
1043         @Override
1044         public void run() {
1045           ThreadReferenceProxyImpl thread = context.getThread();
1046           try {
1047             try {
1048               if (LOG.isDebugEnabled()) {
1049                 final VirtualMachineProxyImpl virtualMachineProxy = getVirtualMachineProxy();
1050                 virtualMachineProxy.logThreads();
1051                 LOG.debug("Invoke in " + thread.name());
1052                 assertThreadSuspended(thread, context);
1053               }
1054               if (!Patches.IBM_JDK_DISABLE_COLLECTION_BUG) {
1055                 // ensure args are not collected
1056                 for (Object arg : myArgs) {
1057                   if (arg instanceof ObjectReference) {
1058                     ((ObjectReference)arg).disableCollection();
1059                   }
1060                 }
1061               }
1062               result[0] = invokeMethod(invokePolicy, myArgs);
1063             }
1064             finally {
1065               //  assertThreadSuspended(thread, context);
1066               if (!Patches.IBM_JDK_DISABLE_COLLECTION_BUG) {
1067                 // ensure args are not collected
1068                 for (Object arg : myArgs) {
1069                   if (arg instanceof ObjectReference) {
1070                     ((ObjectReference)arg).enableCollection();
1071                   }
1072                 }
1073               }
1074             }
1075           }
1076           catch (Exception e) {
1077             exception[0] = e;
1078           }
1079         }
1080       });
1081
1082       if (exception[0] != null) {
1083         if (exception[0] instanceof InvocationException) {
1084           throw (InvocationException)exception[0];
1085         }
1086         else if (exception[0] instanceof ClassNotLoadedException) {
1087           throw (ClassNotLoadedException)exception[0];
1088         }
1089         else if (exception[0] instanceof IncompatibleThreadStateException) {
1090           throw (IncompatibleThreadStateException)exception[0];
1091         }
1092         else if (exception[0] instanceof InvalidTypeException) {
1093           throw (InvalidTypeException)exception[0];
1094         }
1095         else if (exception[0] instanceof RuntimeException) {
1096           throw (RuntimeException)exception[0];
1097         }
1098         else {
1099           LOG.assertTrue(false);
1100         }
1101       }
1102
1103       return (E)result[0];
1104     }
1105
1106     private void assertThreadSuspended(final ThreadReferenceProxyImpl thread, final SuspendContextImpl context) {
1107       LOG.assertTrue(context.isEvaluating());
1108       try {
1109         final boolean isSuspended = thread.isSuspended();
1110         LOG.assertTrue(isSuspended, thread);
1111       }
1112       catch (ObjectCollectedException ignored) {
1113       }
1114     }
1115   }
1116
1117   @Override
1118   public Value invokeMethod(@NotNull EvaluationContext evaluationContext, @NotNull ObjectReference objRef, @NotNull Method method, final List args) throws EvaluateException {
1119     return invokeInstanceMethod(evaluationContext, objRef, method, args, 0);
1120   }
1121
1122   @Override
1123   public Value invokeInstanceMethod(@NotNull EvaluationContext evaluationContext, @NotNull final ObjectReference objRef, final Method method,
1124                                     final List args, final int invocationOptions) throws EvaluateException {
1125     final ThreadReference thread = getEvaluationThread(evaluationContext);
1126     return new InvokeCommand<Value>(args) {
1127       @Override
1128       protected Value invokeMethod(int invokePolicy, final List args) throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
1129         if (LOG.isDebugEnabled()) {
1130           LOG.debug("Invoke " + method.name());
1131         }
1132         return objRef.invokeMethod(thread, method, args, invokePolicy | invocationOptions);
1133       }
1134     }.start((EvaluationContextImpl)evaluationContext, method, false);
1135   }
1136
1137   private static ThreadReference getEvaluationThread(final EvaluationContext evaluationContext) throws EvaluateException {
1138     ThreadReferenceProxy evaluationThread = evaluationContext.getSuspendContext().getThread();
1139     if(evaluationThread == null) {
1140       throw EvaluateExceptionUtil.NULL_STACK_FRAME;
1141     }
1142     return evaluationThread.getThreadReference();
1143   }
1144
1145   @Override
1146   public Value invokeMethod(final EvaluationContext evaluationContext, final ClassType classType,
1147                             final Method method,
1148                             final List args) throws EvaluateException {
1149     return invokeMethod(evaluationContext, classType, method, args, false);
1150   }
1151
1152   public Value invokeMethod(@NotNull EvaluationContext evaluationContext,
1153                             @NotNull final ClassType classType,
1154                             @NotNull final Method method,
1155                             final List args,
1156                             boolean internalEvaluate) throws EvaluateException {
1157     final ThreadReference thread = getEvaluationThread(evaluationContext);
1158     return new InvokeCommand<Value>(args) {
1159       @Override
1160       protected Value invokeMethod(int invokePolicy, final List args) throws InvocationException,
1161                                                                              ClassNotLoadedException,
1162                                                                              IncompatibleThreadStateException,
1163                                                                              InvalidTypeException {
1164         if (LOG.isDebugEnabled()) {
1165           LOG.debug("Invoke " + method.name());
1166         }
1167         return classType.invokeMethod(thread, method, args, invokePolicy);
1168       }
1169     }.start((EvaluationContextImpl)evaluationContext, method, internalEvaluate);
1170   }
1171
1172   @Override
1173   public ArrayReference newInstance(final ArrayType arrayType,
1174                                     final int dimension)
1175     throws EvaluateException {
1176     try {
1177       return arrayType.newInstance(dimension);
1178     }
1179     catch (Exception e) {
1180       throw EvaluateExceptionUtil.createEvaluateException(e);
1181     }
1182   }
1183
1184   @Override
1185   public ObjectReference newInstance(final EvaluationContext evaluationContext, final ClassType classType,
1186                                      final Method method,
1187                                      final List args) throws EvaluateException {
1188     final ThreadReference thread = getEvaluationThread(evaluationContext);
1189     InvokeCommand<ObjectReference> invokeCommand = new InvokeCommand<ObjectReference>(args) {
1190       @Override
1191       protected ObjectReference invokeMethod(int invokePolicy, final List args) throws InvocationException,
1192                                                                                        ClassNotLoadedException,
1193                                                                                        IncompatibleThreadStateException,
1194                                                                                        InvalidTypeException {
1195         if (LOG.isDebugEnabled()) {
1196           LOG.debug("New instance " + method.name());
1197         }
1198         return classType.newInstance(thread, method, args, invokePolicy);
1199       }
1200     };
1201     return invokeCommand.start((EvaluationContextImpl)evaluationContext, method, false);
1202   }
1203
1204   public void clearCashes(int suspendPolicy) {
1205     if (!isAttached()) return;
1206     switch (suspendPolicy) {
1207       case EventRequest.SUSPEND_ALL:
1208         getVirtualMachineProxy().clearCaches();
1209         break;
1210       case EventRequest.SUSPEND_EVENT_THREAD:
1211         getVirtualMachineProxy().clearCaches();
1212         //suspendContext.getThread().clearAll();
1213         break;
1214     }
1215   }
1216
1217   protected void beforeSuspend(SuspendContextImpl suspendContext) {
1218     clearCashes(suspendContext.getSuspendPolicy());
1219   }
1220
1221   private void beforeMethodInvocation(SuspendContextImpl suspendContext, Method method, boolean internalEvaluate) {
1222     if (LOG.isDebugEnabled()) {
1223       LOG.debug(
1224         "before invocation in  thread " + suspendContext.getThread().name() + " method " + (method == null ? "null" : method.name()));
1225     }
1226
1227     if (!internalEvaluate) {
1228       if (method != null) {
1229         showStatusText(DebuggerBundle.message("progress.evaluating", DebuggerUtilsEx.methodName(method)));
1230       }
1231       else {
1232         showStatusText(DebuggerBundle.message("title.evaluating"));
1233       }
1234     }
1235   }
1236
1237   private void afterMethodInvocation(SuspendContextImpl suspendContext, boolean internalEvaluate) {
1238     if (LOG.isDebugEnabled()) {
1239       LOG.debug("after invocation in  thread " + suspendContext.getThread().name());
1240     }
1241     if (!internalEvaluate) {
1242       showStatusText("");
1243     }
1244   }
1245
1246   @Override
1247   public ReferenceType findClass(EvaluationContext evaluationContext, String className,
1248                                  ClassLoaderReference classLoader) throws EvaluateException {
1249     try {
1250       DebuggerManagerThreadImpl.assertIsManagerThread();
1251       final VirtualMachineProxyImpl vmProxy = getVirtualMachineProxy();
1252       if (vmProxy == null) {
1253         throw new VMDisconnectedException();
1254       }
1255       ReferenceType result = null;
1256       for (final ReferenceType refType : vmProxy.classesByName(className)) {
1257         if (refType.isPrepared() && isVisibleFromClassLoader(classLoader, refType)) {
1258           result = refType;
1259           break;
1260         }
1261       }
1262       final EvaluationContextImpl evalContext = (EvaluationContextImpl)evaluationContext;
1263       if (result == null && evalContext.isAutoLoadClasses()) {
1264         return loadClass(evalContext, className, classLoader);
1265       }
1266       return result;
1267     }
1268     catch (InvocationException e) {
1269       throw EvaluateExceptionUtil.createEvaluateException(e);
1270     }
1271     catch (ClassNotLoadedException e) {
1272       throw EvaluateExceptionUtil.createEvaluateException(e);
1273     }
1274     catch (IncompatibleThreadStateException e) {
1275       throw EvaluateExceptionUtil.createEvaluateException(e);
1276     }
1277     catch (InvalidTypeException e) {
1278       throw EvaluateExceptionUtil.createEvaluateException(e);
1279     }
1280   }
1281
1282   private static boolean isVisibleFromClassLoader(final ClassLoaderReference fromLoader, final ReferenceType refType) {
1283     // IMPORTANT! Even if the refType is already loaded by some parent or bootstrap loader, it may not be visible from the given loader.
1284     // For example because there were no accesses yet from this loader to this class. So the loader is not in the list of "initialing" loaders
1285     // for this refType and the refType is not visible to the loader.
1286     // Attempt to evaluate method with this refType will yield ClassNotLoadedException.
1287     // The only way to say for sure whether the class is _visible_ to the given loader, is to use the following API call
1288     return fromLoader == null || fromLoader.equals(refType.classLoader()) || fromLoader.visibleClasses().contains(refType);
1289   }
1290
1291   private static String reformatArrayName(String className) {
1292     if (className.indexOf('[') == -1) return className;
1293
1294     int dims = 0;
1295     while (className.endsWith("[]")) {
1296       className = className.substring(0, className.length() - 2);
1297       dims++;
1298     }
1299
1300     StringBuilder buffer = StringBuilderSpinAllocator.alloc();
1301     try {
1302       for (int i = 0; i < dims; i++) {
1303         buffer.append('[');
1304       }
1305       String primitiveSignature = JVMNameUtil.getPrimitiveSignature(className);
1306       if(primitiveSignature != null) {
1307         buffer.append(primitiveSignature);
1308       }
1309       else {
1310         buffer.append('L');
1311         buffer.append(className);
1312         buffer.append(';');
1313       }
1314       return buffer.toString();
1315     }
1316     finally {
1317       StringBuilderSpinAllocator.dispose(buffer);
1318     }
1319   }
1320
1321   @SuppressWarnings({"HardCodedStringLiteral", "SpellCheckingInspection"})
1322   public ReferenceType loadClass(EvaluationContextImpl evaluationContext, String qName, ClassLoaderReference classLoader)
1323     throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException, EvaluateException {
1324
1325     DebuggerManagerThreadImpl.assertIsManagerThread();
1326     qName = reformatArrayName(qName);
1327     ReferenceType refType = null;
1328     VirtualMachineProxyImpl virtualMachine = getVirtualMachineProxy();
1329     final List classClasses = virtualMachine.classesByName("java.lang.Class");
1330     if (!classClasses.isEmpty()) {
1331       ClassType classClassType = (ClassType)classClasses.get(0);
1332       final Method forNameMethod;
1333       if (classLoader != null) {
1334         //forNameMethod = classClassType.concreteMethodByName("forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
1335         forNameMethod = DebuggerUtils.findMethod(classClassType, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
1336       }
1337       else {
1338         //forNameMethod = classClassType.concreteMethodByName("forName", "(Ljava/lang/String;)Ljava/lang/Class;");
1339         forNameMethod = DebuggerUtils.findMethod(classClassType, "forName", "(Ljava/lang/String;)Ljava/lang/Class;");
1340       }
1341       final List<Mirror> args = new ArrayList<Mirror>(); // do not use unmodifiable lists because the list is modified by JPDA
1342       final StringReference qNameMirror = virtualMachine.mirrorOf(qName);
1343       args.add(qNameMirror);
1344       if (classLoader != null) {
1345         args.add(virtualMachine.mirrorOf(true));
1346         args.add(classLoader);
1347       }
1348       final Value value = invokeMethod(evaluationContext, classClassType, forNameMethod, args);
1349       if (value instanceof ClassObjectReference) {
1350         refType = ((ClassObjectReference)value).reflectedType();
1351       }
1352     }
1353     return refType;
1354   }
1355
1356   public void logThreads() {
1357     if (LOG.isDebugEnabled()) {
1358       try {
1359         Collection<ThreadReferenceProxyImpl> allThreads = getVirtualMachineProxy().allThreads();
1360         for (ThreadReferenceProxyImpl threadReferenceProxy : allThreads) {
1361           LOG.debug("Thread name=" + threadReferenceProxy.name() + " suspendCount()=" + threadReferenceProxy.getSuspendCount());
1362         }
1363       }
1364       catch (Exception e) {
1365         LOG.debug(e);
1366       }
1367     }
1368   }
1369
1370   public SuspendManager getSuspendManager() {
1371     return mySuspendManager;
1372   }
1373
1374   @Override
1375   public CompoundPositionManager getPositionManager() {
1376     return myPositionManager;
1377   }
1378   //ManagerCommands
1379
1380   @Override
1381   public void stop(boolean forceTerminate) {
1382     getManagerThread().terminateAndInvoke(createStopCommand(forceTerminate), DebuggerManagerThreadImpl.COMMAND_TIMEOUT);
1383   }
1384
1385   public StopCommand createStopCommand(boolean forceTerminate) {
1386     return new StopCommand(forceTerminate);
1387   }
1388
1389   protected class StopCommand extends DebuggerCommandImpl {
1390     private final boolean myIsTerminateTargetVM;
1391
1392     public StopCommand(boolean isTerminateTargetVM) {
1393       myIsTerminateTargetVM = isTerminateTargetVM;
1394     }
1395
1396     @Override
1397     public Priority getPriority() {
1398       return Priority.HIGH;
1399     }
1400
1401     @Override
1402     protected void action() throws Exception {
1403       if (isAttached()) {
1404         final VirtualMachineProxyImpl virtualMachineProxy = getVirtualMachineProxy();
1405         if (myIsTerminateTargetVM) {
1406           virtualMachineProxy.exit(-1);
1407         }
1408         else {
1409           // some VMs (like IBM VM 1.4.2 bundled with WebSphere) does not resume threads on dispose() like it should
1410           try {
1411             virtualMachineProxy.resume();
1412           }
1413           finally {
1414             virtualMachineProxy.dispose();
1415           }
1416         }
1417       }
1418       else {
1419         stopConnecting();
1420       }
1421     }
1422   }
1423
1424   private class StepOutCommand extends ResumeCommand {
1425     public StepOutCommand(SuspendContextImpl suspendContext) {
1426       super(suspendContext);
1427     }
1428
1429     @Override
1430     public void contextAction() {
1431       showStatusText(DebuggerBundle.message("status.step.out"));
1432       final SuspendContextImpl suspendContext = getSuspendContext();
1433       final ThreadReferenceProxyImpl thread = getContextThread();
1434       RequestHint hint = new RequestHint(thread, suspendContext, StepRequest.STEP_OUT);
1435       hint.setIgnoreFilters(mySession.shouldIgnoreSteppingFilters());
1436       applyThreadFilter(thread);
1437       final MethodReturnValueWatcher rvWatcher = myReturnValueWatcher;
1438       if (rvWatcher != null) {
1439         rvWatcher.enable(thread.getThreadReference());
1440       }
1441       doStep(suspendContext, thread, StepRequest.STEP_OUT, hint);
1442       super.contextAction();
1443     }
1444   }
1445
1446   private class StepIntoCommand extends ResumeCommand {
1447     private final boolean myForcedIgnoreFilters;
1448     private final MethodFilter mySmartStepFilter;
1449     @Nullable
1450     private final StepIntoBreakpoint myBreakpoint;
1451
1452     public StepIntoCommand(SuspendContextImpl suspendContext, boolean ignoreFilters, @Nullable final MethodFilter methodFilter) {
1453       super(suspendContext);
1454       myForcedIgnoreFilters = ignoreFilters || methodFilter != null;
1455       mySmartStepFilter = methodFilter;
1456       myBreakpoint = methodFilter instanceof BreakpointStepMethodFilter ?
1457         DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().addStepIntoBreakpoint(((BreakpointStepMethodFilter)methodFilter)) :
1458         null;
1459     }
1460
1461     @Override
1462     public void contextAction() {
1463       showStatusText(DebuggerBundle.message("status.step.into"));
1464       final SuspendContextImpl suspendContext = getSuspendContext();
1465       final ThreadReferenceProxyImpl stepThread = getContextThread();
1466       final RequestHint hint = mySmartStepFilter != null?
1467                                new RequestHint(stepThread, suspendContext, mySmartStepFilter) :
1468                                new RequestHint(stepThread, suspendContext, StepRequest.STEP_INTO);
1469       if (myForcedIgnoreFilters) {
1470         try {
1471           mySession.setIgnoreStepFiltersFlag(stepThread.frameCount());
1472         }
1473         catch (EvaluateException e) {
1474           LOG.info(e);
1475         }
1476       }
1477       hint.setIgnoreFilters(myForcedIgnoreFilters || mySession.shouldIgnoreSteppingFilters());
1478       applyThreadFilter(stepThread);
1479       if (myBreakpoint != null) {
1480         myBreakpoint.setSuspendPolicy(suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD? DebuggerSettings.SUSPEND_THREAD : DebuggerSettings.SUSPEND_ALL);
1481         myBreakpoint.createRequest(suspendContext.getDebugProcess());
1482         myRunToCursorBreakpoint = myBreakpoint;
1483       }
1484       doStep(suspendContext, stepThread, StepRequest.STEP_INTO, hint);
1485       super.contextAction();
1486     }
1487   }
1488
1489   private class StepOverCommand extends ResumeCommand {
1490     private final boolean myIsIgnoreBreakpoints;
1491
1492     public StepOverCommand(SuspendContextImpl suspendContext, boolean ignoreBreakpoints) {
1493       super(suspendContext);
1494       myIsIgnoreBreakpoints = ignoreBreakpoints;
1495     }
1496
1497     @Override
1498     public void contextAction() {
1499       showStatusText(DebuggerBundle.message("status.step.over"));
1500       final SuspendContextImpl suspendContext = getSuspendContext();
1501       final ThreadReferenceProxyImpl stepThread = getContextThread();
1502       // need this hint while stepping over for JSR45 support:
1503       // several lines of generated java code may correspond to a single line in the source file,
1504       // from which the java code was generated
1505       RequestHint hint = new RequestHint(stepThread, suspendContext, StepRequest.STEP_OVER);
1506       hint.setRestoreBreakpoints(myIsIgnoreBreakpoints);
1507       hint.setIgnoreFilters(myIsIgnoreBreakpoints || mySession.shouldIgnoreSteppingFilters());
1508
1509       applyThreadFilter(stepThread);
1510
1511       final MethodReturnValueWatcher rvWatcher = myReturnValueWatcher;
1512       if (rvWatcher != null) {
1513         rvWatcher.enable(stepThread.getThreadReference());
1514       }
1515
1516       doStep(suspendContext, stepThread, StepRequest.STEP_OVER, hint);
1517
1518       if (myIsIgnoreBreakpoints) {
1519         DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().disableBreakpoints(DebugProcessImpl.this);
1520       }
1521       super.contextAction();
1522     }
1523   }
1524
1525   private class RunToCursorCommand extends ResumeCommand {
1526     private final RunToCursorBreakpoint myRunToCursorBreakpoint;
1527     private final boolean myIgnoreBreakpoints;
1528
1529     private RunToCursorCommand(SuspendContextImpl suspendContext, Document document, int lineIndex, final boolean ignoreBreakpoints) {
1530       super(suspendContext);
1531       myIgnoreBreakpoints = ignoreBreakpoints;
1532       final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager();
1533       myRunToCursorBreakpoint = breakpointManager.addRunToCursorBreakpoint(document, lineIndex, ignoreBreakpoints);
1534     }
1535
1536     @Override
1537     public void contextAction() {
1538       showStatusText(DebuggerBundle.message("status.run.to.cursor"));
1539       cancelRunToCursorBreakpoint();
1540       if (myRunToCursorBreakpoint == null) {
1541         return;
1542       }
1543       if (myIgnoreBreakpoints) {
1544         final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager();
1545         breakpointManager.disableBreakpoints(DebugProcessImpl.this);
1546       }
1547       applyThreadFilter(getContextThread());
1548       final SuspendContextImpl context = getSuspendContext();
1549       myRunToCursorBreakpoint.setSuspendPolicy(context.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD? DebuggerSettings.SUSPEND_THREAD : DebuggerSettings.SUSPEND_ALL);
1550       DebugProcessImpl debugProcess = context.getDebugProcess();
1551       myRunToCursorBreakpoint.createRequest(debugProcess);
1552       DebugProcessImpl.this.myRunToCursorBreakpoint = myRunToCursorBreakpoint;
1553
1554       if (debugProcess.getRequestsManager().getWarning(myRunToCursorBreakpoint) == null) {
1555         super.contextAction();
1556       }
1557       else {
1558         myDebugProcessDispatcher.getMulticaster().resumed(getSuspendContext());
1559         DebuggerInvocationUtil.swingInvokeLater(myProject, new Runnable() {
1560           @Override
1561           public void run() {
1562             SourcePosition position = myRunToCursorBreakpoint.getSourcePosition();
1563             String name = position != null ? position.getFile().getName() : "<No File>";
1564             Messages.showErrorDialog(
1565               DebuggerBundle.message("error.running.to.cursor.no.executable.code", name, myRunToCursorBreakpoint.getLineIndex()+1),
1566               UIUtil.removeMnemonic(ActionsBundle.actionText(XDebuggerActions.RUN_TO_CURSOR)));
1567           }
1568         });
1569       }
1570     }
1571   }
1572
1573   public abstract class ResumeCommand extends SuspendContextCommandImpl {
1574
1575     private final ThreadReferenceProxyImpl myContextThread;
1576
1577     public ResumeCommand(SuspendContextImpl suspendContext) {
1578       super(suspendContext);
1579       final ThreadReferenceProxyImpl contextThread = getDebuggerContext().getThreadProxy();
1580       myContextThread = contextThread != null ? contextThread : (suspendContext != null? suspendContext.getThread() : null);
1581     }
1582
1583     @Override
1584     public Priority getPriority() {
1585       return Priority.HIGH;
1586     }
1587
1588     @Override
1589     public void contextAction() {
1590       showStatusText(DebuggerBundle.message("status.process.resumed"));
1591       getSuspendManager().resume(getSuspendContext());
1592       myDebugProcessDispatcher.getMulticaster().resumed(getSuspendContext());
1593     }
1594
1595     public ThreadReferenceProxyImpl getContextThread() {
1596       return myContextThread;
1597     }
1598
1599     protected void applyThreadFilter(ThreadReferenceProxy thread) {
1600       if (getSuspendContext().getSuspendPolicy() == EventRequest.SUSPEND_ALL) {
1601         // there could be explicit resume as a result of call to voteSuspend()
1602         // e.g. when breakpoint was considered invalid, in that case the filter will be applied _after_
1603         // resuming and all breakpoints in other threads will be ignored.
1604         // As resume() implicitly cleares the filter, the filter must be always applied _before_ any resume() action happens
1605         final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(getProject()).getBreakpointManager();
1606         breakpointManager.applyThreadFilter(DebugProcessImpl.this, thread.getThreadReference());
1607       }
1608     }
1609   }
1610
1611   private class PauseCommand extends DebuggerCommandImpl {
1612     public PauseCommand() {
1613     }
1614
1615     @Override
1616     public void action() {
1617       if (!isAttached() || getVirtualMachineProxy().isPausePressed()) {
1618         return;
1619       }
1620       logThreads();
1621       getVirtualMachineProxy().suspend();
1622       logThreads();
1623       SuspendContextImpl suspendContext = mySuspendManager.pushSuspendContext(EventRequest.SUSPEND_ALL, 0);
1624       myDebugProcessDispatcher.getMulticaster().paused(suspendContext);
1625     }
1626   }
1627
1628   private class ResumeThreadCommand extends SuspendContextCommandImpl {
1629     private final ThreadReferenceProxyImpl myThread;
1630
1631     public ResumeThreadCommand(SuspendContextImpl suspendContext, ThreadReferenceProxyImpl thread) {
1632       super(suspendContext);
1633       myThread = thread;
1634     }
1635
1636     @Override
1637     public void contextAction() {
1638       if (getSuspendManager().isFrozen(myThread)) {
1639         getSuspendManager().unfreezeThread(myThread);
1640         return;
1641       }
1642
1643       final Set<SuspendContextImpl> suspendingContexts = SuspendManagerUtil.getSuspendingContexts(getSuspendManager(), myThread);
1644       for (SuspendContextImpl suspendContext : suspendingContexts) {
1645         if (suspendContext.getThread() == myThread) {
1646           getManagerThread().invoke(createResumeCommand(suspendContext));
1647         }
1648         else {
1649           getSuspendManager().resumeThread(suspendContext, myThread);
1650         }
1651       }
1652     }
1653   }
1654
1655   private class FreezeThreadCommand extends DebuggerCommandImpl {
1656     private final ThreadReferenceProxyImpl myThread;
1657
1658     public FreezeThreadCommand(ThreadReferenceProxyImpl thread) {
1659       myThread = thread;
1660     }
1661
1662     @Override
1663     protected void action() throws Exception {
1664       SuspendManager suspendManager = getSuspendManager();
1665       if (!suspendManager.isFrozen(myThread)) {
1666         suspendManager.freezeThread(myThread);
1667       }
1668     }
1669   }
1670
1671   private class PopFrameCommand extends SuspendContextCommandImpl {
1672     private final StackFrameProxyImpl myStackFrame;
1673
1674     public PopFrameCommand(SuspendContextImpl context, StackFrameProxyImpl frameProxy) {
1675       super(context);
1676       myStackFrame = frameProxy;
1677     }
1678
1679     @Override
1680     public void contextAction() {
1681       final ThreadReferenceProxyImpl thread = myStackFrame.threadProxy();
1682       try {
1683         if (!getSuspendManager().isSuspended(thread)) {
1684           notifyCancelled();
1685           return;
1686         }
1687       }
1688       catch (ObjectCollectedException ignored) {
1689         notifyCancelled();
1690         return;
1691       }
1692
1693       final SuspendContextImpl suspendContext = getSuspendContext();
1694       if (!suspendContext.suspends(thread)) {
1695         suspendContext.postponeCommand(this);
1696         return;
1697       }
1698
1699       if (myStackFrame.isBottom()) {
1700         DebuggerInvocationUtil.swingInvokeLater(myProject, new Runnable() {
1701           @Override
1702           public void run() {
1703             Messages.showMessageDialog(myProject, DebuggerBundle.message("error.pop.bottom.stackframe"), ActionsBundle.actionText(DebuggerActions.POP_FRAME), Messages.getErrorIcon());
1704           }
1705         });
1706         return;
1707       }
1708
1709       try {
1710         thread.popFrames(myStackFrame);
1711       }
1712       catch (final EvaluateException e) {
1713         DebuggerInvocationUtil.swingInvokeLater(myProject, new Runnable() {
1714           @Override
1715           public void run() {
1716             Messages.showMessageDialog(myProject, DebuggerBundle.message("error.pop.stackframe", e.getLocalizedMessage()), ActionsBundle.actionText(DebuggerActions.POP_FRAME), Messages.getErrorIcon());
1717           }
1718         });
1719         LOG.info(e);
1720       }
1721       finally {
1722         getSuspendManager().popFrame(suspendContext);
1723       }
1724     }
1725   }
1726
1727   @Override
1728   @NotNull
1729   public GlobalSearchScope getSearchScope() {
1730     LOG.assertTrue(mySession != null, "Accessing debug session before its initialization");
1731     return mySession.getSearchScope();
1732   }
1733
1734   @Nullable
1735   public ExecutionResult attachVirtualMachine(final DebugEnvironment environment,
1736                                               final DebuggerSession session) throws ExecutionException {
1737     mySession = session;
1738     myWaitFor.down();
1739
1740     ApplicationManager.getApplication().assertIsDispatchThread();
1741     LOG.assertTrue(isInInitialState());
1742
1743     myConnection = environment.getRemoteConnection();
1744
1745     createVirtualMachine(environment.getSessionName(), environment.isPollConnection());
1746
1747     ExecutionResult executionResult;
1748     try {
1749       synchronized (myProcessListeners) {
1750         executionResult = environment.createExecutionResult();
1751         myExecutionResult = executionResult;
1752         if (executionResult == null) {
1753           fail();
1754           return null;
1755         }
1756         for (ProcessListener processListener : myProcessListeners) {
1757           executionResult.getProcessHandler().addProcessListener(processListener);
1758         }
1759         myProcessListeners.clear();
1760       }
1761     }
1762     catch (ExecutionException e) {
1763       fail();
1764       throw e;
1765     }
1766
1767     // writing to volatile field ensures the other threads will see the right values in non-volatile fields
1768
1769     if (ApplicationManager.getApplication().isUnitTestMode()) {
1770       return executionResult;
1771     }
1772
1773     /*
1774     final Alarm debugPortTimeout = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
1775
1776     myExecutionResult.getProcessHandler().addProcessListener(new ProcessAdapter() {
1777       public void processTerminated(ProcessEvent event) {
1778         debugPortTimeout.cancelAllRequests();
1779       }
1780
1781       public void startNotified(ProcessEvent event) {
1782         debugPortTimeout.addRequest(new Runnable() {
1783           public void run() {
1784             if(isInInitialState()) {
1785               ApplicationManager.getApplication().schedule(new Runnable() {
1786                 public void run() {
1787                   String message = DebuggerBundle.message("status.connect.failed", DebuggerBundle.getAddressDisplayName(remoteConnection), DebuggerBundle.getTransportName(remoteConnection));
1788                   Messages.showErrorDialog(myProject, message, DebuggerBundle.message("title.generic.debug.dialog"));
1789                 }
1790               });
1791             }
1792           }
1793         }, LOCAL_START_TIMEOUT);
1794       }
1795     });
1796     */
1797
1798     return executionResult;
1799   }
1800
1801   private void fail() {
1802     synchronized (this) {
1803       if (myIsFailed) {
1804         // need this in order to prevent calling stop() twice
1805         return;
1806       }
1807       myIsFailed = true;
1808     }
1809     stop(false);
1810   }
1811
1812   private void createVirtualMachine(final String sessionName, final boolean pollConnection) {
1813     final Semaphore semaphore = new Semaphore();
1814     semaphore.down();
1815
1816     final Ref<Boolean> connectorIsReady = Ref.create(false);
1817     myDebugProcessDispatcher.addListener(new DebugProcessAdapter() {
1818       @Override
1819       public void connectorIsReady() {
1820         connectorIsReady.set(true);
1821         semaphore.up();
1822         myDebugProcessDispatcher.removeListener(this);
1823       }
1824     });
1825
1826     // reload to make sure that source positions are initialized
1827     DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().reloadBreakpoints();
1828
1829     getManagerThread().schedule(new DebuggerCommandImpl() {
1830       @Override
1831       protected void action() {
1832         VirtualMachine vm = null;
1833
1834         try {
1835           final long time = System.currentTimeMillis();
1836           while (System.currentTimeMillis() - time < LOCAL_START_TIMEOUT) {
1837             try {
1838               vm = createVirtualMachineInt();
1839               break;
1840             }
1841             catch (final ExecutionException e) {
1842               if (pollConnection && !myConnection.isServerMode() && e.getCause() instanceof IOException) {
1843                 synchronized (this) {
1844                   try {
1845                     wait(500);
1846                   }
1847                   catch (InterruptedException ignored) {
1848                     break;
1849                   }
1850                 }
1851               }
1852               else {
1853                 fail();
1854                 if (myExecutionResult != null || !connectorIsReady.get()) {
1855                   // propagate exception only in case we succeeded to obtain execution result,
1856                   // otherwise if the error is induced by the fact that there is nothing to debug, and there is no need to show
1857                   // this problem to the user
1858                   SwingUtilities.invokeLater(new Runnable() {
1859                     @Override
1860                     public void run() {
1861                       ExecutionUtil.handleExecutionError(myProject, ToolWindowId.DEBUG, sessionName, e);
1862                     }
1863                   });
1864                 }
1865                 break;
1866               }
1867             }
1868           }
1869         }
1870         finally {
1871           semaphore.up();
1872         }
1873
1874         if (vm != null) {
1875           final VirtualMachine vm1 = vm;
1876           afterProcessStarted(new Runnable() {
1877             @Override
1878             public void run() {
1879               getManagerThread().schedule(new DebuggerCommandImpl() {
1880                 @Override
1881                 protected void action() throws Exception {
1882                   commitVM(vm1);
1883                 }
1884               });
1885             }
1886           });
1887         }
1888       }
1889
1890       @Override
1891       protected void commandCancelled() {
1892         try {
1893           super.commandCancelled();
1894         }
1895         finally {
1896           semaphore.up();
1897         }
1898       }
1899     });
1900
1901     semaphore.waitFor();
1902   }
1903
1904   private void afterProcessStarted(final Runnable run) {
1905     class MyProcessAdapter extends ProcessAdapter {
1906       private boolean alreadyRun = false;
1907
1908       public synchronized void run() {
1909         if(!alreadyRun) {
1910           alreadyRun = true;
1911           run.run();
1912         }
1913         removeProcessListener(this);
1914       }
1915
1916       @Override
1917       public void startNotified(ProcessEvent event) {
1918         run();
1919       }
1920     }
1921     MyProcessAdapter processListener = new MyProcessAdapter();
1922     addProcessListener(processListener);
1923     if (myExecutionResult != null) {
1924       if (myExecutionResult.getProcessHandler().isStartNotified()) {
1925         processListener.run();
1926       }
1927     }
1928   }
1929
1930   public boolean isPausePressed() {
1931     final VirtualMachineProxyImpl vm = myVirtualMachineProxy;
1932     return vm != null && vm.isPausePressed();
1933   }
1934
1935   public DebuggerCommandImpl createPauseCommand() {
1936     return new PauseCommand();
1937   }
1938
1939   public ResumeCommand createResumeCommand(SuspendContextImpl suspendContext) {
1940     return createResumeCommand(suspendContext, PrioritizedTask.Priority.HIGH);
1941   }
1942
1943   public ResumeCommand createResumeCommand(SuspendContextImpl suspendContext, final PrioritizedTask.Priority priority) {
1944     final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(getProject()).getBreakpointManager();
1945     return new ResumeCommand(suspendContext) {
1946       @Override
1947       public void contextAction() {
1948         breakpointManager.applyThreadFilter(DebugProcessImpl.this, null); // clear the filter on resume
1949         super.contextAction();
1950       }
1951
1952       @Override
1953       public Priority getPriority() {
1954         return priority;
1955       }
1956     };
1957   }
1958
1959   public ResumeCommand createStepOverCommand(SuspendContextImpl suspendContext, boolean ignoreBreakpoints) {
1960     return new StepOverCommand(suspendContext, ignoreBreakpoints);
1961   }
1962
1963   public ResumeCommand createStepOutCommand(SuspendContextImpl suspendContext) {
1964     return new StepOutCommand(suspendContext);
1965   }
1966
1967   public ResumeCommand createStepIntoCommand(SuspendContextImpl suspendContext, boolean ignoreFilters, final MethodFilter smartStepFilter) {
1968     return new StepIntoCommand(suspendContext, ignoreFilters, smartStepFilter);
1969   }
1970
1971   public ResumeCommand createRunToCursorCommand(SuspendContextImpl suspendContext, Document document, int lineIndex,
1972                                                             final boolean ignoreBreakpoints)
1973     throws EvaluateException {
1974     RunToCursorCommand runToCursorCommand = new RunToCursorCommand(suspendContext, document, lineIndex, ignoreBreakpoints);
1975     if(runToCursorCommand.myRunToCursorBreakpoint == null) {
1976       final PsiFile psiFile = PsiDocumentManager.getInstance(getProject()).getPsiFile(document);
1977       throw new EvaluateException(DebuggerBundle.message("error.running.to.cursor.no.executable.code", psiFile != null? psiFile.getName() : "<No File>", lineIndex), null);
1978     }
1979     return runToCursorCommand;
1980   }
1981
1982   public DebuggerCommandImpl createFreezeThreadCommand(ThreadReferenceProxyImpl thread) {
1983     return new FreezeThreadCommand(thread);
1984   }
1985
1986   public SuspendContextCommandImpl createResumeThreadCommand(SuspendContextImpl suspendContext, ThreadReferenceProxyImpl thread) {
1987     return new ResumeThreadCommand(suspendContext, thread);
1988   }
1989
1990   public SuspendContextCommandImpl createPopFrameCommand(DebuggerContextImpl context, StackFrameProxyImpl stackFrame) {
1991     final SuspendContextImpl contextByThread =
1992       SuspendManagerUtil.findContextByThread(context.getDebugProcess().getSuspendManager(), stackFrame.threadProxy());
1993     return new PopFrameCommand(contextByThread, stackFrame);
1994   }
1995
1996   //public void setBreakpointsMuted(final boolean muted) {
1997   //  XDebugSession session = mySession.getXDebugSession();
1998   //  if (isAttached()) {
1999   //    getManagerThread().schedule(new DebuggerCommandImpl() {
2000   //      @Override
2001   //      protected void action() throws Exception {
2002   //        // set the flag before enabling/disabling cause it affects if breakpoints will create requests
2003   //        if (myBreakpointsMuted.getAndSet(muted) != muted) {
2004   //          final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager();
2005   //          if (muted) {
2006   //            breakpointManager.disableBreakpoints(DebugProcessImpl.this);
2007   //          }
2008   //          else {
2009   //            breakpointManager.enableBreakpoints(DebugProcessImpl.this);
2010   //          }
2011   //        }
2012   //      }
2013   //    });
2014   //  }
2015   //  else {
2016   //    session.setBreakpointMuted(muted);
2017   //  }
2018   //}
2019
2020   public DebuggerContextImpl getDebuggerContext() {
2021     return mySession.getContextManager().getContext();
2022   }
2023
2024   public void setXDebugProcess(JavaDebugProcess XDebugProcess) {
2025     myXDebugProcess = XDebugProcess;
2026   }
2027
2028   @Nullable
2029   public JavaDebugProcess getXdebugProcess() {
2030     return myXDebugProcess;
2031   }
2032
2033   public boolean areBreakpointsMuted() {
2034     XDebugSession session = mySession.getXDebugSession();
2035     return session != null && session.areBreakpointsMuted();
2036   }
2037
2038   public DebuggerSession getSession() {
2039     return mySession;
2040   }
2041 }