blob: dd505620ea56a645c7263b37e1cd3fab1859cdce [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* 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 com.intellij.debugger.ui.impl.watch;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.SuspendManager;
import com.intellij.debugger.engine.SuspendManagerUtil;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.ThreadGroupReferenceProxyImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.ui.tree.ThreadDescriptor;
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
import com.intellij.icons.AllIcons;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.ThreadReference;
import javax.swing.*;
public class ThreadDescriptorImpl extends NodeDescriptorImpl implements ThreadDescriptor{
private final ThreadReferenceProxyImpl myThread;
private String myName = null;
private boolean myIsExpandable = true;
private boolean myIsSuspended = false;
private boolean myIsCurrent;
private boolean myIsFrozen;
private boolean myIsAtBreakpoint;
private SuspendContextImpl mySuspendContext;
public ThreadDescriptorImpl(ThreadReferenceProxyImpl thread) {
myThread = thread;
}
public String getName() {
return myName;
}
protected String calcRepresentation(EvaluationContextImpl context, DescriptorLabelListener labelListener) throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
ThreadReferenceProxyImpl thread = getThreadReference();
try {
myName = thread.name();
ThreadGroupReferenceProxyImpl gr = getThreadReference().threadGroupProxy();
final String grname = (gr != null)? gr.name() : null;
final String threadStatusText = DebuggerUtilsEx.getThreadStatusText(getThreadReference().status());
//noinspection HardCodedStringLiteral
if (grname != null && !"SYSTEM".equalsIgnoreCase(grname)) {
return DebuggerBundle.message("label.thread.node.in.group", myName, thread.uniqueID(), threadStatusText, grname);
}
return DebuggerBundle.message("label.thread.node", myName, thread.uniqueID(), threadStatusText);
}
catch (ObjectCollectedException e) {
return myName != null ? DebuggerBundle.message("label.thread.node.thread.collected", myName) : "";
}
}
public ThreadReferenceProxyImpl getThreadReference() {
return myThread;
}
public boolean isCurrent() {
return myIsCurrent;
}
public boolean isFrozen() {
return myIsFrozen;
}
public boolean isExpandable() {
return myIsExpandable;
}
public void setContext(EvaluationContextImpl context) {
final ThreadReferenceProxyImpl thread = getThreadReference();
final SuspendManager suspendManager = context != null? context.getDebugProcess().getSuspendManager() : null;
final SuspendContextImpl suspendContext = context != null? context.getSuspendContext() : null;
try {
myIsSuspended = suspendManager != null? suspendManager.isSuspended(thread) : thread.isSuspended();
}
catch (ObjectCollectedException e) {
myIsSuspended = false;
}
myIsExpandable = calcExpandable(myIsSuspended);
mySuspendContext = SuspendManagerUtil.getSuspendContextForThread(suspendContext, thread);
myIsAtBreakpoint = suspendManager != null? SuspendManagerUtil.findContextByThread(suspendManager, thread) != null : thread.getThreadReference().isAtBreakpoint();
myIsCurrent = suspendContext != null? suspendContext.getThread() == thread : false;
myIsFrozen = suspendManager != null? suspendManager.isFrozen(thread) : myIsSuspended;
}
private boolean calcExpandable(final boolean isSuspended) {
if (!isSuspended) {
return false;
}
final int status = getThreadReference().status();
if (status == ThreadReference.THREAD_STATUS_UNKNOWN ||
status == ThreadReference.THREAD_STATUS_NOT_STARTED ||
status == ThreadReference.THREAD_STATUS_ZOMBIE) {
return false;
}
return true;
/*
// [jeka] with lots of threads calling threadProxy.frameCount() in advance while setting context can be costly....
// see IDEADEV-2020
try {
return threadProxy.frameCount() > 0;
}
catch (EvaluateException e) {
//LOG.assertTrue(false);
// if we pause during evaluation of this method the exception is thrown
// private static void longMethod(){
// try {
// Thread.sleep(100000);
// } catch (InterruptedException e) {
// e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
// }
// }
return false;
}
*/
}
public SuspendContextImpl getSuspendContext() {
return mySuspendContext;
}
public boolean isAtBreakpoint() {
return myIsAtBreakpoint;
}
public boolean isSuspended() {
return myIsSuspended;
}
public Icon getIcon() {
if(isCurrent()) {
return AllIcons.Debugger.ThreadCurrent;
}
if(isFrozen()) {
return AllIcons.Debugger.ThreadFrozen;
}
if(isAtBreakpoint()) {
return AllIcons.Debugger.ThreadAtBreakpoint;
}
if(isSuspended()) {
return AllIcons.Debugger.ThreadSuspended;
}
return AllIcons.Debugger.ThreadRunning;
}
}