/**
* Copyright 2010 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.base.mvel;
import org.mvel2.MVELRuntime;
import org.mvel2.debug.Debugger;
import org.mvel2.debug.Frame;
/**
* Debug Handler for MVEL dialect.
*
* Takes care of registering breakpoints and calling required methods
* to trigger eclipse debugger to keep breakpoints in sync etc.
*
* @author Ahti Kitsik
*
*/
public final class MVELDebugHandler {
private static int onBreakReturn = Debugger.CONTINUE;
public final static String DEBUG_LAUNCH_KEY="mvel.debugger";
private static Boolean debugMode = null;
public static final boolean verbose = false;
static {
MVELRuntime.setThreadDebugger(new MVELDebugger());
}
/**
* Notify remote debugger that runtime is ready to get latest breakpoint
* information
*
*/
public static void receiveBreakpoints() {
}
/**
* This is catched by the remote debugger
*
* @param frame
*/
private final static int onBreak(Frame frame) {
// We always fall back to Debugger.CONTINUE after each onBreak to avoid eternal step-over flag
//int oldReturn = onBreakReturn;
//onBreakReturn = Debugger.CONTINUE;
//return oldReturn;
if (verbose) {
System.out.println("Continuing with "+(onBreakReturn==Debugger.CONTINUE?"continue":"step-over"));
}
return onBreakReturn;
}
protected final static void registerBreakpoint(String sourceName, int lineNumber) {
if (verbose) {
System.out.println("Registering breakpoint for "+sourceName+":"+lineNumber);
}
MVELRuntime.registerBreakpoint( sourceName, lineNumber );
}
protected final static void clearAllBreakpoints() {
if (verbose) {
System.out.println("Clearing all breakpoints");
}
MVELRuntime.clearAllBreakpoints();
}
protected final static void removeBreakpoint(String sourceName, int lineNumber) {
if (verbose) {
System.out.println("Removing breakpoint from "+sourceName+":"+lineNumber);
}
MVELRuntime.removeBreakpoint( sourceName, lineNumber );
}
private static class MVELDebugger implements Debugger {
public MVELDebugger() {
}
public int onBreak(Frame frame) {
if (verbose) {
System.out.println("onBreak call for "+frame.getSourceName()+":"+frame.getLineNumber());
}
return MVELDebugHandler.onBreak(frame);
// This call is supposed to be catched by the remote debugger
}
}
protected final static void setOnBreakReturn(int value) {
onBreakReturn = value;
}
/**
* Returns current debug mode.<br/>
* Holds lazy initialized internal reference to improve performance.<br/>
* Therefore you can't change System property "mvel.debugger" after isDebugMode is called at least once.<br/>
* <br/>
* To update debug mode at runtime use {@link MVELDebugHandler#setDebugMode(boolean)}<br/>
* @return <code>true</code> if debug mode is enabled.
*/
public static boolean isDebugMode() {
if (debugMode==null) {
debugMode = Boolean.valueOf(System.getProperty(DEBUG_LAUNCH_KEY));
}
return debugMode.booleanValue();
}
/**
* Sets debug mode on/off.<br/>
* Updates local MVELDebugHandler property and System property "mvel.debugger"<br/>
* <br/>
* There's no need to ever call this method unless you write junit tests!<br/>
*
* @param b is Debug enabled?
*/
public static void setDebugMode(boolean b) {
debugMode = Boolean.valueOf( b );
System.setProperty( DEBUG_LAUNCH_KEY, debugMode.toString());
}
}