blob: e4f404e909c70fef766630f4e1efc0b09e4f0123 [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.
*/
/*
* Class ExceptionBreakpoint
* @author Jeka
*/
package com.intellij.debugger.ui.breakpoints;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.*;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizerUtil;
import com.intellij.openapi.util.Key;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.Location;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.event.ExceptionEvent;
import com.sun.jdi.event.LocatableEvent;
import com.sun.jdi.request.ExceptionRequest;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.java.debugger.breakpoints.properties.JavaExceptionBreakpointProperties;
import javax.swing.*;
public class ExceptionBreakpoint extends Breakpoint<JavaExceptionBreakpointProperties> {
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.breakpoints.ExceptionBreakpoint");
protected final static String READ_NO_CLASS_NAME = DebuggerBundle.message("error.absent.exception.breakpoint.class.name");
public static final @NonNls Key<ExceptionBreakpoint> CATEGORY = BreakpointCategory.lookup("exception_breakpoints");
public ExceptionBreakpoint(Project project, XBreakpoint<JavaExceptionBreakpointProperties> xBreakpoint) {
super(project, xBreakpoint);
}
public Key<? extends ExceptionBreakpoint> getCategory() {
return CATEGORY;
}
protected ExceptionBreakpoint(Project project, String qualifiedName, String packageName, XBreakpoint<JavaExceptionBreakpointProperties> xBreakpoint) {
super(project, xBreakpoint);
setQualifiedName(qualifiedName);
if (packageName == null) {
setPackageName(calcPackageName(qualifiedName));
}
else {
setPackageName(packageName);
}
}
private static String calcPackageName(String qualifiedName) {
if (qualifiedName == null) {
return null;
}
int dotIndex = qualifiedName.lastIndexOf('.');
return dotIndex >= 0? qualifiedName.substring(0, dotIndex) : "";
}
public String getClassName() {
return getQualifiedName();
}
public String getPackageName() {
return getProperties().myPackageName;
}
public PsiClass getPsiClass() {
return PsiDocumentManager.getInstance(myProject).commitAndRunReadAction(new Computable<PsiClass>() {
public PsiClass compute() {
return getQualifiedName() != null ? DebuggerUtils.findClass(getQualifiedName(), myProject, GlobalSearchScope.allScope(myProject)) : null;
}
});
}
public String getDisplayName() {
return DebuggerBundle.message("breakpoint.exception.breakpoint.display.name", getQualifiedName());
}
public Icon getIcon() {
if (!isEnabled()) {
final Breakpoint master = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().findMasterBreakpoint(this);
return master == null? AllIcons.Debugger.Db_disabled_exception_breakpoint : AllIcons.Debugger.Db_dep_exception_breakpoint;
}
return AllIcons.Debugger.Db_exception_breakpoint;
}
public void reload() {
}
public void createRequest(final DebugProcessImpl debugProcess) {
DebuggerManagerThreadImpl.assertIsManagerThread();
if (!shouldCreateRequest(debugProcess)) {
return;
}
SourcePosition classPosition = ApplicationManager.getApplication().runReadAction(new Computable<SourcePosition>() {
public SourcePosition compute() {
PsiClass psiClass = DebuggerUtils.findClass(getQualifiedName(), myProject, debugProcess.getSearchScope());
return psiClass != null ? SourcePosition.createFromElement(psiClass) : null;
}
});
if(classPosition == null) {
createOrWaitPrepare(debugProcess, getQualifiedName());
}
else {
createOrWaitPrepare(debugProcess, classPosition);
}
}
public void processClassPrepare(DebugProcess process, ReferenceType refType) {
DebugProcessImpl debugProcess = (DebugProcessImpl)process;
if (!isEnabled()) {
return;
}
// trying to create a request
ExceptionRequest request = debugProcess.getRequestsManager().createExceptionRequest(this, refType, isNotifyCaught(),
isNotifyUncaught());
debugProcess.getRequestsManager().enableRequest(request);
if (LOG.isDebugEnabled()) {
if (refType != null) {
LOG.debug("Created exception request for reference type " + refType.name());
}
else {
LOG.debug("Created exception request for reference type null");
}
}
}
protected ObjectReference getThisObject(SuspendContextImpl context, LocatableEvent event) throws EvaluateException {
if(event instanceof ExceptionEvent) {
return ((ExceptionEvent) event).exception();
}
return super.getThisObject(context, event); //To change body of overriden methods use Options | File Templates.
}
public String getEventMessage(LocatableEvent event) {
String exceptionName = (getQualifiedName() != null)? getQualifiedName() : "java.lang.Throwable";
String threadName = null;
if (event instanceof ExceptionEvent) {
ExceptionEvent exceptionEvent = (ExceptionEvent)event;
try {
exceptionName = exceptionEvent.exception().type().name();
threadName = exceptionEvent.thread().name();
}
catch (Exception ignore) {
}
}
final Location location = event.location();
final String locationQName = location.declaringType().name() + "." + location.method().name();
String locationFileName;
try {
locationFileName = location.sourceName();
}
catch (AbsentInformationException e) {
locationFileName = "";
}
final int locationLine = Math.max(0, location.lineNumber());
if (threadName != null) {
return DebuggerBundle.message(
"exception.breakpoint.console.message.with.thread.info",
exceptionName,
threadName,
locationQName,
locationFileName,
locationLine
);
}
else {
return DebuggerBundle.message(
"exception.breakpoint.console.message",
exceptionName,
locationQName,
locationFileName,
locationLine
);
}
}
public boolean isValid() {
return true;
}
//@SuppressWarnings({"HardCodedStringLiteral"}) public void writeExternal(Element parentNode) throws WriteExternalException {
// super.writeExternal(parentNode);
// if(getQualifiedName() != null) {
// parentNode.setAttribute("class_name", getQualifiedName());
// }
// if(getPackageName() != null) {
// parentNode.setAttribute("package_name", getPackageName());
// }
//}
public PsiElement getEvaluationElement() {
if (getClassName() == null) {
return null;
}
return JavaPsiFacade.getInstance(myProject).findClass(getClassName(), GlobalSearchScope.allScope(myProject));
}
public void readExternal(Element parentNode) throws InvalidDataException {
super.readExternal(parentNode);
//noinspection HardCodedStringLiteral
String packageName = parentNode.getAttributeValue("package_name");
setPackageName(packageName != null? packageName : calcPackageName(packageName));
try {
getProperties().NOTIFY_CAUGHT = Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "NOTIFY_CAUGHT"));
} catch (Exception ignore) {
}
try {
getProperties().NOTIFY_UNCAUGHT = Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "NOTIFY_UNCAUGHT"));
} catch (Exception ignore) {
}
//noinspection HardCodedStringLiteral
String className = parentNode.getAttributeValue("class_name");
setQualifiedName(className);
if(className == null) {
throw new InvalidDataException(READ_NO_CLASS_NAME);
}
}
private boolean isNotifyCaught() {
return getProperties().NOTIFY_CAUGHT;
}
private boolean isNotifyUncaught() {
return getProperties().NOTIFY_UNCAUGHT;
}
private String getQualifiedName() {
return getProperties().myQualifiedName;
}
void setQualifiedName(String qualifiedName) {
getProperties().myQualifiedName = qualifiedName;
}
void setPackageName(String packageName) {
getProperties().myPackageName = packageName;
}
}