/**
* Copyright (c) 2013 by EA (Electronic Arts), Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.debug.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.python.pydev.core.log.Log;
import org.python.pydev.shared_core.string.StringUtils;
import org.python.pydev.shared_ui.utils.RunInUiThread;
/**
* Handles any exception raised while evaluating the conditional breakpoint
*
* @author hussain.bohra
* @author Fabio Zadrozny
*
*/
public class PyConditionalBreakPointManager {
private static final String DELIMETER = "\t";
private static final int ERROR_CODE = 1;
private static final String PYTHON_TRACEBACK = "Traceback (most recent call last):";
private static final String SHELL_TEXT = "Conditional Breakpoint";
private static final String PID = "Error";
private static final String ERROR_MESSAGE = "An exception has occurred when evaluating a conditional breakpoint:\n\n";
private static final String TITLE = "Error in executing conditional breakpoint";
private static PyConditionalBreakPointManager pyConditionalBreakPointManager;
/**
* Singleton: private constructor.
*/
private PyConditionalBreakPointManager() {
}
public static synchronized PyConditionalBreakPointManager getInstance() {
if (pyConditionalBreakPointManager == null) {
pyConditionalBreakPointManager = new PyConditionalBreakPointManager();
}
return pyConditionalBreakPointManager;
}
/**
* Represents Python stacktrace
*
* @author hussain.bohra
*
*/
@SuppressWarnings("unused")
static class ExceptionStackTrace {
private AbstractDebugTarget target;
private String filename;
private int lineNo;
private String methodName;
private String methodObj;
public ExceptionStackTrace(AbstractDebugTarget target, String filename, int lineNo,
String methodName, String methodObj) {
this.target = target;
this.filename = filename;
this.lineNo = lineNo;
this.methodName = methodName;
this.methodObj = methodObj;
}
@Override
public String toString() {
return StringUtils.join("", "tFile ", filename, "\n line ", lineNo, ", in", methodName, ", ", methodObj);
}
}
/**
* Display an error dialog and traceback raised while evaluating the
* conditional breakpoint.
*
* @param payload
* would contain exception_type + "\t" + stacktrace_xml
*/
public void handleBreakpointException(final AbstractDebugTarget target,
final String payload) {
if (payload.indexOf(DELIMETER) > 0) {
// exceptionDetailList = ["exceptionType", "<frame>traceback</frame>"]
final String[] exceptionDetailList = payload.split(DELIMETER);
RunInUiThread.async(new Runnable() {
@Override
public void run() {
// adding exception detail with error message
String errorMessage = ERROR_MESSAGE + "\n" + exceptionDetailList[0];
List<ExceptionStackTrace> exceptionStackTraceList = new ArrayList<ExceptionStackTrace>();
Shell shell = new Shell(Display.getCurrent());
shell.setText(SHELL_TEXT);
MultiStatus multiStatusInfo = new MultiStatus(PID, ERROR_CODE, errorMessage, null);
multiStatusInfo.add(new Status(IStatus.ERROR, PID, ERROR_CODE, PYTHON_TRACEBACK, null));
try {
// Parse traceback xml
exceptionStackTraceList = XMLUtils.getExceptionStackTrace(target, exceptionDetailList[1]);
} catch (Exception e) {
Log.log(e);
}
if (exceptionStackTraceList != null) {
// Adding traceback details to multiStatusInfo
for (ExceptionStackTrace exceptionStackTrace : exceptionStackTraceList) {
multiStatusInfo.add(new Status(IStatus.ERROR, PID, ERROR_CODE, exceptionStackTrace
.toString(),
null));
}
}
ErrorDialog.openError(shell, TITLE, null, multiStatusInfo);
}
});
}
}
}