/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package org.netbeans.modules.scala.debugger.actions;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import org.netbeans.api.debugger.ActionsManager;
import org.netbeans.api.debugger.Breakpoint;
import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.api.debugger.jpda.FieldBreakpoint;
import org.netbeans.api.debugger.jpda.JPDABreakpoint;
import org.netbeans.api.debugger.jpda.LineBreakpoint;
import org.netbeans.api.debugger.jpda.MethodBreakpoint;
import org.netbeans.modules.scala.debugger.EditorContextBridge;
import org.netbeans.modules.scala.debugger.breakpoints.FieldBreakpointPanel;
import org.netbeans.modules.scala.debugger.breakpoints.MethodBreakpointPanel;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;
/**
*
* @author Martin Entlicher
*/
public class ToggleMethodFieldBreakpointAction extends AbstractAction {//implements PropertyChangeListener {
private static final String[] BREAKPOINT_ANNOTATION_TYPES = new String[] {
"Breakpoint_broken",
"Breakpoint",
"CondBreakpoint_broken",
"CondBreakpoint",
"DisabledBreakpoint",
"DisabledCondBreakpoint",
"ClassBreakpoint",
"DisabledClassBreakpoint",
"DisabledFieldBreakpoint",
"DisabledMethodBreakpoint",
"FieldBreakpoint",
"MethodBreakpoint",
};
private Object action;
private RequestProcessor postponedToggleRP;
public ToggleMethodFieldBreakpointAction () {
//EditorContextBridge.addPropertyChangeListener (this);
setEnabled (true);
putValue("default-action", true);
putValue("supported-annotation-types", BREAKPOINT_ANNOTATION_TYPES);
putValue("default-action-excluded-annotation-types", BREAKPOINT_ANNOTATION_TYPES);
}
public Object getAction () {
return action;
}
public Object getValue(String key) {
if (key == Action.NAME) {
return NbBundle.getMessage (ToggleMethodFieldBreakpointAction.class, "CTL_ToggleMethodFieldBreakpointAction");
}
Object value = super.getValue(key);
if (key == Action.SMALL_ICON) {
if (value instanceof String) {
value = new ImageIcon (Utilities.loadImage (value+".gif"));// Utils.getIcon ((String) value);
}
}
return value;
}
/*
public void propertyChange (PropertyChangeEvent evt) {
String url = EditorContextBridge.getCurrentURL();
if (url.length() == 0) {
setEnabled(false);
return ;
}
FileObject fo;
try {
fo = URLMapper.findFileObject(new URL(url));
} catch (MalformedURLException muex) {
fo = null;
}
setEnabled (
(fo != null && "text/x-java".equals(fo.getMIMEType())) && // NOI18N
(EditorContextBridge.getCurrentFieldName() != null ||
EditorContextBridge.getCurrentMethodDeclaration() != null)
//(EditorContextBridge.getCurrentURL ().endsWith (".java"))
);
/*
if ( debugger != null &&
debugger.getState () == debugger.STATE_DISCONNECTED
)
destroy ();
*//*
}
*/
public void actionPerformed (ActionEvent evt) {
if (!submitFieldOrMethodBreakpoint()) {
// Do the toggle BP action directly in this AWT so that it gets the correct current line number.
DebuggerManager.getDebuggerManager().getActionsManager().doAction(ActionsManager.ACTION_TOGGLE_BREAKPOINT);
}
}
private boolean submitFieldOrMethodBreakpoint() {
// 1) get class name & element info
final String[] className = new String[] { null };
java.awt.IllegalComponentStateException cex;
final String[] fieldName = new String[] { null };
java.awt.IllegalComponentStateException fex;
final String methodName;
final String methodSignature;
java.awt.IllegalComponentStateException mex;
try {
className[0] = EditorContextBridge.getContext().getCurrentClassName();
cex = null;
} catch (java.awt.IllegalComponentStateException icsex) {
cex = icsex;
}
try {
fieldName[0] = EditorContextBridge.getContext().getCurrentFieldName();
fex = null;
} catch (java.awt.IllegalComponentStateException icsex) {
fex = icsex;
}
if (fex != null || fieldName[0] == null || fieldName[0].length() == 0) {
fieldName[0] = null;
String[] methodInfo;
try {
methodInfo = EditorContextBridge.getContext().getCurrentMethodDeclaration();
mex = null;
} catch (java.awt.IllegalComponentStateException icsex) {
mex = icsex;
methodInfo = null;
}
if (methodInfo != null) {
methodName = methodInfo[0];
methodSignature = methodInfo[1];
if (methodInfo[2] != null) {
className[0] = methodInfo[2];
}
} else if (mex == null) {
return false;
} else {
methodName = null;
methodSignature = null;
}
} else {
mex = null;
methodName = null;
methodSignature = null;
}
if (cex != null || fex != null || mex != null) {
final int ln = EditorContextBridge.getContext().getCurrentLineNumber ();
final String url = EditorContextBridge.getContext().getCurrentURL ();
final java.awt.IllegalComponentStateException[] exs = new java.awt.IllegalComponentStateException[]
{ cex, fex, mex };
synchronized (this) {
if (postponedToggleRP == null) {
postponedToggleRP = new RequestProcessor("Postponed ToggleMethodFieldBreakpointAction", 1);
}
}
postponedToggleRP.post(new Runnable() {
public void run() {
// Re-try to submit the field or method breakpoint again
String cn = (exs[0] != null) ? exs[0].getMessage() : className[0];
String fn = (exs[1] != null) ? exs[1].getMessage() : fieldName[0];
String mn = (exs[2] != null) ? exs[2].getMessage() : methodName;
String ms = (exs[2] != null) ? exs[2].getLocalizedMessage() : methodSignature;
if (fn != null && fn.length() == 0) fn = null;
if (submitFieldOrMethodBreakpoint(cn, fn, mn, ms, url, ln)) {
// We've submitted a field or method breakpoint, so delete the line one:
LineBreakpoint lb = ToggleBreakpointActionProvider.findBreakpoint (
url, ln
);
if (lb != null) {
DebuggerManager.getDebuggerManager().removeBreakpoint (lb);
}
}
}
});
return false;
} else {
int ln = EditorContextBridge.getContext().getCurrentLineNumber ();
String url = EditorContextBridge.getContext().getCurrentURL ();
return submitFieldOrMethodBreakpoint(className[0], fieldName[0],
methodName, methodSignature,
url, ln);
}
/*
// 1) get class name & element info
String className;
String fieldName;
try {
className = EditorContextBridge.getCurrentClassName();
fieldName = EditorContextBridge.getCurrentFieldName();
} catch (java.awt.IllegalComponentStateException icsex) {
final int ln = EditorContextBridge.getCurrentLineNumber ();
final String url = EditorContextBridge.getCurrentURL ();
return false;
}
String methodName = null;
String methodSignature = null;
if (fieldName == null || fieldName.length() == 0) {
fieldName = null;
String[] methodInfo = EditorContextBridge.getCurrentMethodDeclaration();
if (methodInfo != null) {
methodName = methodInfo[0];
methodSignature = methodInfo[1];
} else {
return false;
}
}
return submitFieldOrMethodBreakpoint(className[0], fieldName[0], methodName, methodSignature);
*/
}
private boolean submitFieldOrMethodBreakpoint(String className, String fieldName,
String methodName, String methodSignature,
String url, int line) {
// 2) find and remove existing line breakpoint
JPDABreakpoint b;
if (fieldName != null) {
b = findBreakpoint (className, fieldName);
} else if (methodName != null) {
b = findBreakpoint (className, methodName, methodSignature);
} else {
return false;
}
if (b == null) {
b = ToggleBreakpointActionProvider.findBreakpoint(url, line);
}
DebuggerManager d = DebuggerManager.getDebuggerManager();
if (b != null) {
d.removeBreakpoint (b);
return true;
}
// 3) create a new breakpoint
if (fieldName != null) {
b = FieldBreakpoint.create(className, fieldName, FieldBreakpoint.TYPE_MODIFICATION | FieldBreakpoint.TYPE_ACCESS);
b.setPrintText(NbBundle.getMessage(FieldBreakpointPanel.class, "CTL_Field_Breakpoint_Print_Text"));
} else {
b = MethodBreakpoint.create(className, methodName);
((MethodBreakpoint) b).setMethodSignature(methodSignature);
b.setPrintText(NbBundle.getMessage(MethodBreakpointPanel.class, "CTL_Method_Breakpoint_Print_Text"));
}
d.addBreakpoint(b);
return true;
}
static JPDABreakpoint getCurrentFieldMethodBreakpoint() {
String className = EditorContextBridge.getContext().getCurrentClassName();
String fieldName = EditorContextBridge.getContext().getCurrentFieldName();
String methodName = null;
String methodSignature = null;
if (fieldName == null || fieldName.length() == 0) {
fieldName = null;
String[] methodInfo = EditorContextBridge.getContext().getCurrentMethodDeclaration();
if (methodInfo != null) {
methodName = methodInfo[0];
methodSignature = methodInfo[1];
} else {
return null;
}
}
// 2) find and remove existing line breakpoint
JPDABreakpoint b;
if (fieldName != null) {
b = findBreakpoint (className, fieldName);
} else {
b = findBreakpoint (className, methodName, methodSignature);
}
return b;
}
private static FieldBreakpoint findBreakpoint(String className, String fieldName) {
Breakpoint[] breakpoints = DebuggerManager.getDebuggerManager().getBreakpoints();
for (int i = 0; i < breakpoints.length; i++) {
if (!(breakpoints[i] instanceof FieldBreakpoint)) {
continue;
}
FieldBreakpoint fb = (FieldBreakpoint) breakpoints[i];
if (!fb.getClassName().equals(className)) continue;
if (!fb.getFieldName().equals(fieldName)) continue;
return fb;
}
return null;
}
private static MethodBreakpoint findBreakpoint(String className, String methodName, String methodSignature) {
Breakpoint[] breakpoints = DebuggerManager.getDebuggerManager().getBreakpoints();
for (int i = 0; i < breakpoints.length; i++) {
if (!(breakpoints[i] instanceof MethodBreakpoint)) {
continue;
}
MethodBreakpoint mb = (MethodBreakpoint) breakpoints[i];
String[] classFilters = mb.getClassFilters();
int j;
for (j = 0; j < classFilters.length; j++) {
if (match(className, classFilters[j])) {
break;
}
}
if (j < classFilters.length) {
if (!mb.getMethodName().equals(methodName)) continue;
String signature = mb.getMethodSignature();
if (signature == null || egualMethodSignatures(signature, methodSignature)) {
return mb;
}
}
}
return null;
}
// Compares whether the two signatures have the same arguments. We ignore return value.
private static boolean egualMethodSignatures(String s1, String s2) {
int i = s1.lastIndexOf(")");
if (i > 0) s1 = s1.substring(0, i);
i = s2.lastIndexOf(")");
if (i > 0) s2 = s2.substring(0, i);
return s1.equals(s2);
}
private static boolean match (String name, String pattern) {
if (pattern.startsWith ("*"))
return name.endsWith (pattern.substring (1));
else
if (pattern.endsWith ("*"))
return name.startsWith (
pattern.substring (0, pattern.length () - 1)
);
return name.equals (pattern);
}
}