diff --git a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDABreakpoint.java b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDABreakpoint.java --- a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDABreakpoint.java +++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDABreakpoint.java @@ -251,6 +251,11 @@ synchronized JPDADebugger getSession() { return session; } + + @Override + public boolean canHaveDependentBreakpoints() { + return true; + } /** * Adds a JPDABreakpointListener. diff --git a/api.debugger/apichanges.xml b/api.debugger/apichanges.xml --- a/api.debugger/apichanges.xml +++ b/api.debugger/apichanges.xml @@ -463,6 +463,31 @@ + + + Added a possibility to enable/disable other breakpoints when one is hit. + + + + + + Four methods are added to the Breakpoint class, that allow to + get or set a set of breakpoints, that are enabled or disabled when + the breakpoint is hit. One test method is provided, which determines + if the dependent breakpoints are supported by the implementation. +

+ Added methods:
+ Breakpoint.canHaveDependentBreakpoints(), + Breakpoint.getBreakpointsToEnable(), + Breakpoint.setBreakpointsToEnable(), + Breakpoint.getBreakpointsToDisable(), + Breakpoint.setBreakpointsToDisable(). +

+
+ + +
+ diff --git a/api.debugger/manifest.mf b/api.debugger/manifest.mf --- a/api.debugger/manifest.mf +++ b/api.debugger/manifest.mf @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.api.debugger/1 OpenIDE-Module-Localizing-Bundle: org/netbeans/api/debugger/Bundle.properties -OpenIDE-Module-Specification-Version: 1.33 +OpenIDE-Module-Specification-Version: 1.34 OpenIDE-Module-Layer: org/netbeans/api/debugger/layer.xml diff --git a/api.debugger/nbproject/project.xml b/api.debugger/nbproject/project.xml --- a/api.debugger/nbproject/project.xml +++ b/api.debugger/nbproject/project.xml @@ -50,6 +50,15 @@ org.netbeans.api.debugger + org.netbeans.api.annotations.common + + + + 1 + 1.11 + + + org.netbeans.modules.projectapi diff --git a/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java b/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java --- a/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java +++ b/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java @@ -46,6 +46,9 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.util.Collections; +import java.util.Set; +import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.project.Project; import org.openide.filesystems.FileObject; @@ -86,6 +89,8 @@ private String validityMessage; private int hitCountFilter; private HIT_COUNT_FILTERING_STYLE hitCountFilteringStyle; + private volatile Set breakpointsToEnable = Collections.EMPTY_SET; + private volatile Set breakpointsToDisable = Collections.EMPTY_SET; { pcs = new PropertyChangeSupport (this); } @@ -230,6 +235,93 @@ return null; } + /** + * Determines if the breakpoint supports dependent breakpoints. + * If true, get/setBreakpointsToEnable/Disable methods can be used to get + * or set dependent breakpoints. + * If false, the methods throw an UnsupportedOperationException. + * @return true if the dependent breakpoints are supported, + * false otherwise. + * @since 1.34 + */ + public boolean canHaveDependentBreakpoints() { + return false; + } + + /** + * Get the set of breakpoints that will be enabled after this breakpoint + * is hit. + *

+ * Not all breakpoint implementations honor dependent breakpoints. + * Use {@link #canHaveDependentBreakpoints()} to determine if the operation is supported. + * @return The set of breakpoints. + * @throws UnsupportedOperationException if the breakpoint does not support + * dependent breakpoints - see {@link #canHaveDependentBreakpoints()}. + * @since 1.34 + */ + @NonNull + public Set getBreakpointsToEnable() { + if (!canHaveDependentBreakpoints()) { + throw new UnsupportedOperationException("Can not have dependent breakpoints."); // NOI18N + } + return breakpointsToEnable; + } + + /** + * Get the set of breakpoints that will be disabled after this breakpoint + * is hit. + *

+ * Not all breakpoint implementations honor dependent breakpoints. + * Use {@link #canHaveDependentBreakpoints()} to determine if the operation is supported. + * @throws UnsupportedOperationException if the breakpoint does not support + * dependent breakpoints - see {@link #canHaveDependentBreakpoints()}. + * @return The set of breakpoints. + * @since 1.34 + */ + @NonNull + public Set getBreakpointsToDisable() { + if (!canHaveDependentBreakpoints()) { + throw new UnsupportedOperationException("Can not have dependent breakpoints."); // NOI18N + } + return breakpointsToDisable; + } + + /** + * Set the set of breakpoints that will be enabled after this breakpoint + * is hit. + *

+ * Not all breakpoint implementations honor dependent breakpoints. + * Use {@link #canHaveDependentBreakpoints()} to determine if the operation is supported. + * @param breakpointsToEnable The set of breakpoints. + * @throws UnsupportedOperationException if the breakpoint does not support + * dependent breakpoints - see {@link #canHaveDependentBreakpoints()}. + * @since 1.34 + */ + public void setBreakpointsToEnable(@NonNull Set breakpointsToEnable) { + if (!canHaveDependentBreakpoints()) { + throw new UnsupportedOperationException("Can not have dependent breakpoints."); // NOI18N + } + this.breakpointsToEnable = breakpointsToEnable; + } + + /** + * Set the set of breakpoints that will be disabled after this breakpoint + * is hit. + *

+ * Not all breakpoint implementations honor dependent breakpoints. + * Use {@link #canHaveDependentBreakpoints()} to determine if the operation is supported. + * @param breakpointsToEnable The set of breakpoints. + * @throws UnsupportedOperationException if the breakpoint does not support + * dependent breakpoints - see {@link #canHaveDependentBreakpoints()}. + * @since 1.34 + */ + public void setBreakpointsToDisable(@NonNull Set breakpointsToDisable) { + if (!canHaveDependentBreakpoints()) { + throw new UnsupportedOperationException("Can not have dependent breakpoints."); // NOI18N + } + this.breakpointsToDisable = breakpointsToDisable; + } + /** * Add a listener to property changes. * diff --git a/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointImpl.java b/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointImpl.java --- a/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointImpl.java +++ b/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointImpl.java @@ -66,6 +66,7 @@ import java.beans.PropertyChangeEvent; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.SwingUtilities; @@ -471,6 +472,7 @@ getBreakpoint (), e ); + enableDisableDependentBreakpoints(); Integer brkpSuspend = (Integer) event.request().getProperty("brkpSuspend"); if (brkpSuspend == null) { brkpSuspend = getBreakpoint().getSuspend(); @@ -493,6 +495,17 @@ return resume; } + private void enableDisableDependentBreakpoints() { + Set breakpoints = breakpoint.getBreakpointsToEnable(); + for (Breakpoint b : breakpoints) { + b.enable(); + } + breakpoints = breakpoint.getBreakpointsToDisable(); + for (Breakpoint b : breakpoints) { + b.disable(); + } + } + private boolean checkWhetherResumeToFinishStep(ThreadReference thread) throws InternalExceptionWrapper, VMDisconnectedExceptionWrapper { List stepRequests = EventRequestManagerWrapper.stepRequests( VirtualMachineWrapper.eventRequestManager(MirrorWrapper.virtualMachine(thread))); diff --git a/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsFromGroup.java b/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsFromGroup.java new file mode 100644 --- /dev/null +++ b/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsFromGroup.java @@ -0,0 +1,146 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 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 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.debugger.jpda.breakpoints; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.netbeans.api.debugger.Breakpoint; +import org.netbeans.api.debugger.DebuggerManager; + +/** + * Set of breakpoints from a group. + * + * @author Martin + */ +public final class BreakpointsFromGroup implements Set { + + private final String groupName; + + public BreakpointsFromGroup(String groupName) { + this.groupName = groupName; + } + + public String getGroupName() { + return groupName; + } + + private List getBreakpointsFromGroup() { + List breakpoints = new ArrayList(); + Breakpoint[] bps = DebuggerManager.getDebuggerManager().getBreakpoints(); + for (Breakpoint b : bps) { + if (groupName.equals(b.getGroupName())) { + breakpoints.add(b); + } + } + return breakpoints; + } + + @Override + public int size() { + return getBreakpointsFromGroup().size(); + } + + @Override + public boolean isEmpty() { + return getBreakpointsFromGroup().isEmpty(); + } + + @Override + public boolean contains(Object o) { + return getBreakpointsFromGroup().contains(o); + } + + @Override + public Iterator iterator() { + return getBreakpointsFromGroup().iterator(); + } + + @Override + public boolean containsAll(Collection c) { + return getBreakpointsFromGroup().containsAll(c); + } + + @Override + public Object[] toArray() { + return getBreakpointsFromGroup().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return getBreakpointsFromGroup().toArray(a); + } + + @Override + public boolean add(Breakpoint e) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public boolean addAll(Collection c) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public void clear() { + throw new UnsupportedOperationException("Not supported."); + } + +} diff --git a/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsReader.java b/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsReader.java --- a/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsReader.java +++ b/debugger.jpda/src/org/netbeans/modules/debugger/jpda/breakpoints/BreakpointsReader.java @@ -47,6 +47,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Map; +import java.util.Set; import java.util.WeakHashMap; import org.netbeans.api.debugger.Breakpoint; @@ -274,6 +275,14 @@ b.enable (); else b.disable (); + String breakpointsToEnableGroup = properties.getString("breakpointsToEnableGroup", null); + if (breakpointsToEnableGroup != null) { + b.setBreakpointsToEnable(new BreakpointsFromGroup(breakpointsToEnableGroup)); + } + String breakpointsToDisableGroup = properties.getString("breakpointsToDisableGroup", null); + if (breakpointsToDisableGroup != null) { + b.setBreakpointsToDisable(new BreakpointsFromGroup(breakpointsToDisableGroup)); + } return b; } @@ -292,6 +301,22 @@ properties.setInt(JPDABreakpoint.PROP_HIT_COUNT_FILTER, b.getHitCountFilter()); Breakpoint.HIT_COUNT_FILTERING_STYLE style = b.getHitCountFilteringStyle(); properties.setInt(JPDABreakpoint.PROP_HIT_COUNT_FILTER+"_style", style != null ? style.ordinal() : 0); // NOI18N + Set breakpointsToEnable = b.getBreakpointsToEnable(); + String breakpointsToEnableGroup; + if (breakpointsToEnable instanceof BreakpointsFromGroup) { + breakpointsToEnableGroup = ((BreakpointsFromGroup) breakpointsToEnable).getGroupName(); + } else { + breakpointsToEnableGroup = null; + } + properties.setString("breakpointsToEnableGroup", breakpointsToEnableGroup); + Set breakpointsToDisable = b.getBreakpointsToDisable(); + String breakpointsToDisableGroup; + if (breakpointsToDisable instanceof BreakpointsFromGroup) { + breakpointsToDisableGroup = ((BreakpointsFromGroup) breakpointsToDisable).getGroupName(); + } else { + breakpointsToDisableGroup = null; + } + properties.setString("breakpointsToDisableGroup", breakpointsToDisableGroup); if (object instanceof LineBreakpoint) { LineBreakpoint lb = (LineBreakpoint) object;