--- a/api.debugger.jpda/apichanges.xml Tue Feb 26 15:54:39 2013 +0100 +++ a/api.debugger.jpda/apichanges.xml Tue Feb 26 16:37:11 2013 +0100 @@ -816,6 +816,25 @@ + + + Breakpoints can deactivated. + + + + + + Two methods are added to JPDADebugger class: getBreakpointsActive() + and setBreakpointsActive(boolean). The set method fires PROP_BREAKPOINTS_ACTIVE + event.
+ These methods are used to activate/deactivate all breakpoints in the + debugger session. + Initially, the breakpoints are active in the debugger session. +
+ + +
+ --- a/api.debugger.jpda/manifest.mf Tue Feb 26 15:54:39 2013 +0100 +++ a/api.debugger.jpda/manifest.mf Tue Feb 26 16:37:11 2013 +0100 @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.api.debugger.jpda/2 OpenIDE-Module-Localizing-Bundle: org/netbeans/api/debugger/jpda/Bundle.properties -OpenIDE-Module-Specification-Version: 2.41 +OpenIDE-Module-Specification-Version: 2.42 OpenIDE-Module-Package-Dependencies: com.sun.jdi[VirtualMachineManager] --- a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDADebugger.java Tue Feb 26 15:54:39 2013 +0100 +++ a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDADebugger.java Tue Feb 26 16:37:11 2013 +0100 @@ -107,6 +107,9 @@ /** Property name constant. * @since 2.25 */ public static final String PROP_CLASSES_FIXED = "classesFixed"; // NOI18N + /** Property name constant. Fired when breakpoints are activated / deactivated. + * @since 2.42 */ + public static final String PROP_BREAKPOINTS_ACTIVE = "breakpointsActive"; // NOI18N /** Suspend property value constant. */ public static final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; @@ -488,6 +491,30 @@ } /** + * Test, if breakpoints are active. + * @return true when breakpoints are active, false + * otherwise. The default implementation returns true, to be overridden + * when needed. + * @since 2.42 + */ + public boolean getBreakpointsActive() { + return true; + } + + /** + * Set all breakpoints to be active / inactive. + * Activation or deactivation of breakpoints should not alter the enabled/disabled + * state of individual breakpoints. + * The default implementation does nothing, override + * together with {@link #getBreakpointsActive()} when needed. + * @param active true to make all breakpoints active, + * false to make all breakpoints inactive. + * @since 2.42 + */ + public void setBreakpointsActive(boolean active) { + } + + /** * Adds property change listener. * * @param l new listener. --- a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/BreakpointAnnotationProvider.java Tue Feb 26 15:54:39 2013 +0100 +++ a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/BreakpointAnnotationProvider.java Tue Feb 26 16:37:11 2013 +0100 @@ -63,14 +63,18 @@ import org.netbeans.api.debugger.Breakpoint.VALIDITY; import org.netbeans.api.debugger.DebuggerEngine; import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.DebuggerManagerAdapter; import org.netbeans.api.debugger.DebuggerManagerListener; +import org.netbeans.api.debugger.LazyDebuggerManagerListener; import org.netbeans.api.debugger.Session; import org.netbeans.api.debugger.Watch; import org.netbeans.api.debugger.jpda.ClassLoadUnloadBreakpoint; import org.netbeans.api.debugger.jpda.FieldBreakpoint; import org.netbeans.api.debugger.jpda.JPDABreakpoint; +import org.netbeans.api.debugger.jpda.JPDADebugger; import org.netbeans.api.debugger.jpda.LineBreakpoint; import org.netbeans.api.debugger.jpda.MethodBreakpoint; +import org.netbeans.spi.debugger.DebuggerServiceRegistration; import org.netbeans.spi.debugger.jpda.EditorContext; import org.openide.cookies.LineCookie; @@ -94,14 +98,18 @@ * @author Jan Jancura, Martin Entlicher */ @org.openide.util.lookup.ServiceProvider(service=org.openide.text.AnnotationProvider.class) -public class BreakpointAnnotationProvider implements AnnotationProvider, - DebuggerManagerListener { +@DebuggerServiceRegistration(types=LazyDebuggerManagerListener.class) +public class BreakpointAnnotationProvider extends DebuggerManagerAdapter + implements AnnotationProvider/*, + DebuggerManagerListener*/ { private final Map> breakpointToAnnotations = new IdentityHashMap>(); private final Set annotatedFiles = new WeakSet(); private Set dataObjectListeners; private boolean attachManagerListener = true; + private volatile JPDADebugger currentDebugger = null; + private volatile boolean breakpointsActive = true; private RequestProcessor annotationProcessor = new RequestProcessor("Annotation Refresh", 1); private RequestProcessor contextWaitingProcessor = new RequestProcessor("Annotation Refresh Context Waiting", 1); @@ -168,6 +176,7 @@ } if (attachManagerListener) { attachManagerListener = false; + setCurrentDebugger(DebuggerManager.getDebuggerManager().getCurrentEngine()); DebuggerManager.getDebuggerManager().addDebuggerListener( WeakListeners.create(DebuggerManagerListener.class, this, @@ -176,6 +185,11 @@ } @Override + public String[] getProperties() { + return new String[] { DebuggerManager.PROP_BREAKPOINTS, DebuggerManager.PROP_DEBUGGER_ENGINES }; + } + + @Override public void breakpointAdded(Breakpoint breakpoint) { if (isAnnotatable(breakpoint)) { JPDABreakpoint b = (JPDABreakpoint) breakpoint; @@ -207,6 +221,15 @@ if (propertyName == null) { return; } + if (DebuggerManager.PROP_CURRENT_ENGINE.equals(propertyName)) { + setCurrentDebugger(DebuggerManager.getDebuggerManager().getCurrentEngine()); + } + if (JPDADebugger.PROP_BREAKPOINTS_ACTIVE.equals(propertyName)) { + JPDADebugger debugger = currentDebugger; + if (debugger != null) { + setBreakpointsActive(debugger.getBreakpointsActive()); + } + } if ( (!JPDABreakpoint.PROP_ENABLED.equals (propertyName)) && (!JPDABreakpoint.PROP_VALIDITY.equals (propertyName)) && (!LineBreakpoint.PROP_CONDITION.equals (propertyName)) && @@ -238,6 +261,32 @@ annotationProcessor.post(new AnnotationRefresh(b, true, true)); } + private void setCurrentDebugger(DebuggerEngine engine) { + JPDADebugger oldDebugger = currentDebugger; + if (oldDebugger != null) { + oldDebugger.removePropertyChangeListener(JPDADebugger.PROP_BREAKPOINTS_ACTIVE, this); + } + boolean active = true; + JPDADebugger debugger = null; + if (engine != null) { + debugger = engine.lookupFirst(null, JPDADebugger.class); + if (debugger != null) { + debugger.addPropertyChangeListener(JPDADebugger.PROP_BREAKPOINTS_ACTIVE, this); + active = debugger.getBreakpointsActive(); + } + } + currentDebugger = debugger; + setBreakpointsActive(active); + } + + private void setBreakpointsActive(boolean active) { + if (breakpointsActive == active) { + return ; + } + breakpointsActive = active; + annotationProcessor.post(new AnnotationRefresh(null, true, true)); + } + private final class AnnotationRefresh implements Runnable { private JPDABreakpoint b; @@ -252,17 +301,28 @@ @Override public void run() { synchronized (breakpointToAnnotations) { - if (remove) { - removeAnnotations(b); - if (!add) { - breakpointToAnnotations.remove(b); + if (b != null) { + refreshAnnotation(b); + } else { + List bpts = new ArrayList(breakpointToAnnotations.keySet()); + for (JPDABreakpoint bp : bpts) { + refreshAnnotation(bp); } } - if (add) { - breakpointToAnnotations.put(b, new WeakSet()); - for (FileObject fo : annotatedFiles) { - addAnnotationTo(b, fo); - } + } + } + + private void refreshAnnotation(JPDABreakpoint b) { + if (remove) { + removeAnnotations(b); + if (!add) { + breakpointToAnnotations.remove(b); + } + } + if (add) { + breakpointToAnnotations.put(b, new WeakSet()); + for (FileObject fo : annotatedFiles) { + addAnnotationTo(b, fo); } } } @@ -277,7 +337,8 @@ !((JPDABreakpoint) b).isHidden(); } - private static String getAnnotationType(JPDABreakpoint b, boolean isConditional) { + private static String getAnnotationType(JPDABreakpoint b, boolean isConditional, + boolean active) { boolean isInvalid = b.getValidity() == VALIDITY.INVALID; String annotationType; if (b instanceof LineBreakpoint) { @@ -301,8 +362,10 @@ } else { throw new IllegalStateException(b.toString()); } - if (isInvalid && b.isEnabled ()) { - annotationType += "_broken"; + if (!active) { + annotationType = annotationType + "_stroke"; // NOI18N + } else if (isInvalid && b.isEnabled ()) { + annotationType += "_broken"; // NOI18N } return annotationType; } @@ -481,7 +544,7 @@ throw new IllegalStateException(b.toString()); } boolean isConditional = (condition != null) && condition.trim().length() > 0; - String annotationType = getAnnotationType(b, isConditional); + String annotationType = getAnnotationType(b, isConditional, breakpointsActive); DataObject dataObject; try { dataObject = DataObject.find(fo); @@ -526,7 +589,7 @@ } } - + /* // Not used @Override public Breakpoint[] initBreakpoints() { return new Breakpoint[] {}; } @@ -558,5 +621,5 @@ // Not used @Override public void engineRemoved(DebuggerEngine engine) {} - + */ } --- a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/Bundle.properties Tue Feb 26 15:54:39 2013 +0100 +++ a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/Bundle.properties Tue Feb 26 16:37:11 2013 +0100 @@ -65,6 +65,7 @@ TOOLTIP_DISABLED_METHOD_BREAKPOINT=Disabled Method Breakpoint TOOLTIP_CLASS_BREAKPOINT=Class Breakpoint TOOLTIP_DISABLED_CLASS_BREAKPOINT=Disabled Class Breakpoint +TOOLTIP_BREAKPOINT_STROKE=Deactivated breakpoint #SourcesNodeModel CTL_SourcesModel_Column_Name_LibrarySources = {0} --- a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/DebuggerBreakpointAnnotation.java Tue Feb 26 15:54:39 2013 +0100 +++ a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/DebuggerBreakpointAnnotation.java Tue Feb 26 16:37:11 2013 +0100 @@ -92,6 +92,10 @@ return NbBundle.getMessage (DebuggerBreakpointAnnotation.class, "TOOLTIP_BREAKPOINT_BROKEN"); // NOI18N } + if (type.endsWith("_stroke")) { + return NbBundle.getMessage(DebuggerBreakpointAnnotation.class, + "TOOLTIP_BREAKPOINT_STROKE"); + } if (type == EditorContext.BREAKPOINT_ANNOTATION_TYPE) { return NbBundle.getMessage (DebuggerBreakpointAnnotation.class, "TOOLTIP_BREAKPOINT"); // NOI18N --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/resources/Bundle.properties Tue Feb 26 15:54:39 2013 +0100 +++ a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/resources/Bundle.properties Tue Feb 26 16:37:11 2013 +0100 @@ -45,7 +45,13 @@ #Annotations HINT_FIELD_BREAKPOINT=Field Breakpoint HINT_DISABLED_FIELD_BREAKPOINT=Disabled Field Breakpoint +HINT_FIELD_BREAKPOINT_STROKE=Deactivated Field Breakpoint +HINT_DISABLED_FIELD_BREAKPOINT_STROKE=Deactivated Disabled Field Breakpoint HINT_METHOD_BREAKPOINT=Method Breakpoint HINT_DISABLED_METHOD_BREAKPOINT=Disabled Method Breakpoint +HINT_METHOD_BREAKPOINT_STROKE=Deactivated Method Breakpoint +HINT_DISABLED_METHOD_BREAKPOINT_STROKE=Deactivated Disabled Method Breakpoint HINT_CLASS_BREAKPOINT=Class Breakpoint -HINT_DISABLED_CLASS_BREAKPOINT=Disabled Class Breakpoint +HINT_DISABLED_CLASS_BREAKPOINT=Disabled Class Breakpoint +HINT_CLASS_BREAKPOINT_STROKE=Deactivated Class Breakpoint +HINT_DISABLED_CLASS_BREAKPOINT_STROKE=Deactivated Disabled Class Breakpoint --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 55edf326bb27 Tue Feb 26 16:37:11 2013 +0100 @@ -0,0 +1,59 @@ + + + + + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 55edf326bb27 Tue Feb 26 16:37:11 2013 +0100 @@ -0,0 +1,59 @@ + + + + + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 55edf326bb27 Tue Feb 26 16:37:11 2013 +0100 @@ -0,0 +1,59 @@ + + + + + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 55edf326bb27 Tue Feb 26 16:37:11 2013 +0100 @@ -0,0 +1,59 @@ + + + + + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 55edf326bb27 Tue Feb 26 16:37:11 2013 +0100 @@ -0,0 +1,59 @@ + + + + + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 55edf326bb27 Tue Feb 26 16:37:11 2013 +0100 @@ -0,0 +1,59 @@ + + + + + --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/resources/mf-layer.xml Tue Feb 26 15:54:39 2013 +0100 +++ a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/resources/mf-layer.xml Tue Feb 26 16:37:11 2013 +0100 @@ -119,6 +119,12 @@ + + + + + + @@ -291,6 +297,23 @@ + + + + + + + + + + + + + + + + --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/BreakpointOutput.java Tue Feb 26 15:54:39 2013 +0100 +++ a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/BreakpointOutput.java Tue Feb 26 16:37:11 2013 +0100 @@ -144,6 +144,10 @@ if (breakpoint.getSuspend() != JPDABreakpoint.SUSPEND_NONE) { getBreakpointsNodeModel ().setCurrentBreakpoint (breakpoint); } + System.err.println("BP variable = "+event.getVariable()); + if (event.getVariable() != null) { + System.err.println(" value = "+event.getVariable().getValue()); + } String printText = breakpoint.getPrintText (); substituteAndPrintText(printText, event); } --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 55edf326bb27 Tue Feb 26 16:37:11 2013 +0100 @@ -0,0 +1,245 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle 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]" + * + * 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. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.debugger.jpda.ui.models; + +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.datatransfer.Transferable; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.swing.AbstractButton; +import javax.swing.ImageIcon; +import javax.swing.JToggleButton; +import javax.swing.border.EmptyBorder; +import org.netbeans.api.debugger.DebuggerEngine; +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.jpda.JPDABreakpoint; +import org.netbeans.api.debugger.jpda.JPDADebugger; +import org.netbeans.api.debugger.jpda.LineBreakpoint; +import org.netbeans.spi.debugger.ContextProvider; +import org.netbeans.spi.debugger.DebuggerServiceRegistration; +import org.netbeans.spi.viewmodel.ExtendedNodeModel; +import org.netbeans.spi.viewmodel.ExtendedNodeModelFilter; +import org.netbeans.spi.viewmodel.ModelEvent; +import org.netbeans.spi.viewmodel.ModelListener; +import org.netbeans.spi.viewmodel.NodeModel; +import org.netbeans.spi.viewmodel.UnknownTypeException; +import org.openide.util.ImageUtilities; +import org.openide.util.NbBundle; +import org.openide.util.RequestProcessor; +import org.openide.util.WeakListeners; +import org.openide.util.datatransfer.PasteType; + +/** + * + * @author Martin Entlicher + */ +@DebuggerServiceRegistration(path="netbeans-JPDASession/BreakpointsView", types=ExtendedNodeModelFilter.class) +public class BreakpointModelActiveSessionFilter implements ExtendedNodeModelFilter, + PropertyChangeListener { + + private static final String DEACTIVATED_LINE_BREAKPOINT = + "org/netbeans/modules/debugger/resources/editor/Breakpoint_stroke.png"; // NOI18N + private static final String DEACTIVATED_DISABLED_LINE_BREAKPOINT = + "org/netbeans/modules/debugger/resources/editor/DisabledBreakpoint_stroke.png"; // NOI18N + private static final String DEACTIVATED_NONLINE_BREAKPOINT = + "org/netbeans/modules/debugger/resources/editor/Breakpoint_nonline_stroke.png"; // NOI18N + private static final String DEACTIVATED_DISABLED_NONLINE_BREAKPOINT = + "org/netbeans/modules/debugger/resources/editor/DisabledBreakpoint_nonline_stroke.png"; // NOI18N + + private static final RequestProcessor RP = new RequestProcessor(BreakpointModelActiveSessionFilter.class.getName()); + + private JPDADebugger debugger; + private final List listeners = new ArrayList(); + + public BreakpointModelActiveSessionFilter(ContextProvider contextProvider) { + debugger = contextProvider.lookupFirst(null, JPDADebugger.class); + debugger.addPropertyChangeListener(WeakListeners.propertyChange(this, debugger)); + } + + @Override + public String getDisplayName(NodeModel original, Object node) throws UnknownTypeException { + return original.getDisplayName(node); + } + + @Override + public String getShortDescription(NodeModel original, Object node) throws UnknownTypeException { + return original.getShortDescription(node); + } + + @Override + public String getIconBaseWithExtension(ExtendedNodeModel original, Object node) throws UnknownTypeException { + if (debugger.getBreakpointsActive()) { + return original.getIconBaseWithExtension(node); + } else { + if (node instanceof LineBreakpoint) { + LineBreakpoint breakpoint = (LineBreakpoint)node; + if (!breakpoint.isEnabled()) { + return DEACTIVATED_DISABLED_LINE_BREAKPOINT; + } else { + return DEACTIVATED_LINE_BREAKPOINT; + } + } else if (node instanceof JPDABreakpoint) { + JPDABreakpoint breakpoint = (JPDABreakpoint) node; + if (!breakpoint.isEnabled()) { + return DEACTIVATED_DISABLED_NONLINE_BREAKPOINT; + } else { + return DEACTIVATED_NONLINE_BREAKPOINT; + } + } + throw new UnknownTypeException(node); + } + } + + @Override + public String getIconBase(NodeModel original, Object node) throws UnknownTypeException { + throw new UnsupportedOperationException("Not supported, overriden by getIconBaseWithExtension()."); + } + + @Override + public void setName(ExtendedNodeModel original, Object node, String name) throws UnknownTypeException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean canRename(ExtendedNodeModel original, Object node) throws UnknownTypeException { + return original.canRename(node); + } + + @Override + public boolean canCopy(ExtendedNodeModel original, Object node) throws UnknownTypeException { + return original.canCopy(node); + } + + @Override + public boolean canCut(ExtendedNodeModel original, Object node) throws UnknownTypeException { + return original.canCut(node); + } + + @Override + public Transferable clipboardCopy(ExtendedNodeModel original, Object node) throws IOException, UnknownTypeException { + return original.clipboardCopy(node); + } + + @Override + public Transferable clipboardCut(ExtendedNodeModel original, Object node) throws IOException, UnknownTypeException { + return original.clipboardCut(node); + } + + @Override + public PasteType[] getPasteTypes(ExtendedNodeModel original, Object node, Transferable t) throws UnknownTypeException { + return original.getPasteTypes(node, t); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); + if (JPDADebugger.PROP_BREAKPOINTS_ACTIVE.equals(propertyName)) { + fireChangeEvent(new ModelEvent.NodeChanged(this, null, ModelEvent.NodeChanged.ICON_MASK)); + } + } + + @Override + public void addModelListener(ModelListener l) { + synchronized (listeners) { + listeners.add(l); + } + } + + @Override + public void removeModelListener(ModelListener l) { + synchronized (listeners) { + listeners.remove(l); + } + } + + private void fireChangeEvent(ModelEvent me) { + List ls; + synchronized (listeners) { + ls = new ArrayList(listeners); + } + for (ModelListener ml : ls) { + ml.modelChanged(me); + } + } + + + @NbBundle.Messages({"CTL_DeactivateAllBreakpoints=Deactivate all breakpoints", + "CTL_ActivateAllBreakpoints=Activate all breakpoints"}) + public static AbstractButton createActivateBreakpointsActionButton() { + ImageIcon icon = ImageUtilities.loadImageIcon(DEACTIVATED_LINE_BREAKPOINT, false); + final JToggleButton button = new JToggleButton(icon); + // ensure small size, just for the icon + Dimension size = new Dimension(icon.getIconWidth() + 8, icon.getIconHeight() + 8); + button.setPreferredSize(size); + button.setMargin(new Insets(1, 1, 1, 1)); + button.setBorder(new EmptyBorder(button.getBorder().getBorderInsets(button))); + button.setToolTipText(Bundle.CTL_DeactivateAllBreakpoints()); + button.setFocusable(false); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + DebuggerEngine engine = DebuggerManager.getDebuggerManager().getCurrentEngine(); + final JPDADebugger debugger = engine.lookupFirst(null, JPDADebugger.class); + final boolean active = !button.isSelected(); + if (active) { + button.setToolTipText(Bundle.CTL_DeactivateAllBreakpoints()); + } else { + button.setToolTipText(Bundle.CTL_ActivateAllBreakpoints()); + } + RP.post(new Runnable() { + @Override + public void run() { + debugger.setBreakpointsActive(active); + } + }); + } + }); + return button; + } + +} --- a/debugger.jpda/src/org/netbeans/modules/debugger/jpda/JPDADebuggerImpl.java Tue Feb 26 15:54:39 2013 +0100 +++ a/debugger.jpda/src/org/netbeans/modules/debugger/jpda/JPDADebuggerImpl.java Tue Feb 26 16:37:11 2013 +0100 @@ -206,6 +206,7 @@ private boolean doContinue = true; // Whether resume() will actually resume private Boolean singleThreadStepResumeDecision = null; private Boolean stepInterruptByBptResumeDecision = null; + private boolean breakpointsActive = true; private InputOutput io; @@ -554,6 +555,22 @@ } } + @Override + public boolean getBreakpointsActive() { + return breakpointsActive; + } + + @Override + public void setBreakpointsActive(boolean active) { + synchronized (this) { + if (breakpointsActive == active) { + return ; + } + breakpointsActive = active; + } + firePropertyChange(PROP_BREAKPOINTS_ACTIVE, !active, active); + } + public Session getSession() { return lookupProvider.lookupFirst(null, Session.class); } --- a/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointImpl.java Tue Feb 26 15:54:39 2013 +0100 +++ a/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointImpl.java Tue Feb 26 16:37:11 2013 +0100 @@ -143,6 +143,7 @@ */ final void set () { breakpoint.addPropertyChangeListener (this); + debugger.addPropertyChangeListener(JPDADebugger.PROP_BREAKPOINTS_ACTIVE, this); if (breakpoint instanceof PropertyChangeListener && isApplicable()) { Session s = debugger.getSession(); DebuggerEngine de = s.getEngineForLanguage ("Java"); @@ -169,7 +170,7 @@ (getDebugger ().getState () == JPDADebugger.STATE_DISCONNECTED) ) return; removeAllEventRequests (); - if (breakpoint.isEnabled () && isEnabled()) { + if (breakpoint.isEnabled () && isEnabled() && debugger.getBreakpointsActive()) { setRequests (); } } @@ -196,7 +197,7 @@ } else if (!Breakpoint.PROP_VALIDITY.equals(propertyName) && !Breakpoint.PROP_GROUP_NAME.equals(propertyName) && !Breakpoint.PROP_GROUP_PROPERTIES.equals(propertyName)) { - if (reader != null) { + if (reader != null && !JPDADebugger.PROP_BREAKPOINTS_ACTIVE.equals(propertyName)) { reader.storeCachedClassName(breakpoint, null); } debugger.getRequestProcessor().post(new Runnable() { @@ -224,6 +225,7 @@ removeAllEventRequests (); } breakpoint.removePropertyChangeListener(this); + debugger.removePropertyChangeListener(JPDADebugger.PROP_BREAKPOINTS_ACTIVE, this); setValidity(Breakpoint.VALIDITY.UNKNOWN, null); if (breakpoint instanceof PropertyChangeListener) { Session s = debugger.getSession(); --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ 55edf326bb27 Tue Feb 26 16:37:11 2013 +0100 @@ -0,0 +1,237 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle 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-2006 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.api.debugger.jpda; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import junit.framework.Test; +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent; +import org.netbeans.api.debugger.jpda.event.JPDABreakpointListener; +import org.netbeans.junit.NbTestCase; + +/** + * Tests breakpoints deactivation. + * + */ +public class BreakpointsDeactivationTest extends NbTestCase { + + private static final String TEST_APP_PATH = System.getProperty ("test.dir.src") + + "org/netbeans/api/debugger/jpda/testapps/LineBreakpointApp.java"; + + private JPDASupport support; + + + public BreakpointsDeactivationTest (String s) { + super (s); + } + + public static Test suite() { + return JPDASupport.createTestSuite(BreakpointsDeactivationTest.class); + } + + public void testBreakpointsDeactivation () throws Exception { + try { + Utils.BreakPositions bp = Utils.getBreakPositions(TEST_APP_PATH); + LineBreakpoint[] lb = bp.getBreakpoints().toArray(new LineBreakpoint[0]); + { + LineBreakpoint b; + b = lb[4]; + lb[4] = lb[2]; + lb[2] = b; + } + /* + LineBreakpoint lb1 = LineBreakpoint.create (TEST_APP, 32); + LineBreakpoint lb2 = LineBreakpoint.create (TEST_APP, 37); + LineBreakpoint lb3 = LineBreakpoint.create (TEST_APP, 109); + lb3.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$Inner"); + LineBreakpoint lb4 = LineBreakpoint.create (TEST_APP, 92); + lb4.setPreferredClassName("org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp$InnerStatic"); + LineBreakpoint lb5 = LineBreakpoint.create (TEST_APP, 41); + */ + DebuggerManager dm = DebuggerManager.getDebuggerManager (); + for (int i = 0; i < lb.length; i++) { + dm.addBreakpoint (lb[i]); + } + + TestBreakpointListener[] tb = new TestBreakpointListener[lb.length]; + for (int i = 0; i < lb.length; i++) { + tb[i] = new TestBreakpointListener (lb[i]); + lb[i].addJPDABreakpointListener (tb[i]); + } + support = JPDASupport.attach ( + "org.netbeans.api.debugger.jpda.testapps.LineBreakpointApp" + ); + JPDADebugger debugger = support.getDebugger(); + assertEquals("Breakpoints should be active initially.", true, debugger.getBreakpointsActive()); + + support.waitState (JPDADebugger.STATE_STOPPED); // stopped on the first breakpoint + + final PropertyChangeEvent[] propertyPtr = new PropertyChangeEvent[] { null }; + debugger.addPropertyChangeListener(JPDADebugger.PROP_BREAKPOINTS_ACTIVE, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + propertyPtr[0] = evt; + } + }); + debugger.setBreakpointsActive(false); + assertNotNull(propertyPtr[0]); + assertEquals(propertyPtr[0].getSource(), debugger); + assertEquals(propertyPtr[0].getOldValue(), Boolean.TRUE); + assertEquals(propertyPtr[0].getNewValue(), Boolean.FALSE); + assertEquals("Breakpoints should be inactive after deactivation.", false, debugger.getBreakpointsActive()); + + int j = 0; + assertEquals ( + "Debugger stopped at wrong line for breakpoint " + j, + lb[j].getLineNumber (), + debugger.getCurrentCallStackFrame ().getLineNumber (null) + ); + for (int i = j+1; i < tb.length; i++) { + tb[i].checkNotNotified(); + } + if (j < lb.length - 1) { + support.doContinue(); + } + + for (int i = 0; i < tb.length; i++) { + dm.removeBreakpoint (lb[i]); + } + support.waitState (JPDADebugger.STATE_DISCONNECTED); + } finally { + if (support != null) { + support.doFinish (); + } + } + } + + // innerclasses ............................................................ + + private class TestBreakpointListener implements JPDABreakpointListener { + + private LineBreakpoint lineBreakpoint; + private int conditionResult; + + private JPDABreakpointEvent event; + private AssertionError failure; + + public TestBreakpointListener (LineBreakpoint lineBreakpoint) { + this (lineBreakpoint, JPDABreakpointEvent.CONDITION_NONE); + } + + public TestBreakpointListener ( + LineBreakpoint lineBreakpoint, + int conditionResult + ) { + this.lineBreakpoint = lineBreakpoint; + this.conditionResult = conditionResult; + } + + @Override + public void breakpointReached (JPDABreakpointEvent event) { + try { + checkEvent (event); + } catch (AssertionError e) { + failure = e; + } catch (Throwable e) { + failure = new AssertionError (e); + } + } + + private void checkEvent (JPDABreakpointEvent event) { + this.event = event; + assertEquals ( + "Breakpoint event: Wrong source breakpoint", + lineBreakpoint, + event.getSource () + ); + assertNotNull ( + "Breakpoint event: Context thread is null", + event.getThread () + ); + + int result = event.getConditionResult (); + if ( result == JPDABreakpointEvent.CONDITION_FAILED && + conditionResult != JPDABreakpointEvent.CONDITION_FAILED + ) { + failure = new AssertionError (event.getConditionException ()); + } else + if (result != conditionResult) { + failure = new AssertionError ( + "Unexpected breakpoint condition result: " + result + ); + } + } + + public void checkResult () { + if (event == null) { + CallStackFrame f = support.getDebugger (). + getCurrentCallStackFrame (); + int ln = -1; + if (f != null) { + ln = f.getLineNumber (null); + } + throw new AssertionError ( + "Breakpoint was not hit (listener was not notified) " + ln + ); + } + if (failure != null) { + throw failure; + } + } + + public void checkNotNotified() { + if (event != null) { + JPDAThread t = event.getThread(); + throw new AssertionError ( + "Breakpoint was hit (listener was notified) in thread " + t + ); + } + if (failure != null) { + throw failure; + } + } + } +}