diff --git a/spi.debugger.ui/manifest.mf b/spi.debugger.ui/manifest.mf --- a/spi.debugger.ui/manifest.mf +++ b/spi.debugger.ui/manifest.mf @@ -2,6 +2,6 @@ OpenIDE-Module: org.netbeans.spi.debugger.ui/1 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/debugger/ui/Bundle.properties OpenIDE-Module-Layer: org/netbeans/modules/debugger/resources/mf-layer.xml -OpenIDE-Module-Specification-Version: 2.41 +OpenIDE-Module-Specification-Version: 2.42 OpenIDE-Module-Provides: org.netbeans.spi.debugger.ui OpenIDE-Module-Install: org/netbeans/modules/debugger/ui/DebuggerModule.class diff --git a/spi.debugger.ui/nbproject/project.xml b/spi.debugger.ui/nbproject/project.xml --- a/spi.debugger.ui/nbproject/project.xml +++ b/spi.debugger.ui/nbproject/project.xml @@ -137,6 +137,14 @@ + org.openide.explorer + + + + 6.55 + + + org.openide.filesystems diff --git a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/registry/DebuggerProcessor.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/registry/DebuggerProcessor.java --- a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/registry/DebuggerProcessor.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/registry/DebuggerProcessor.java @@ -67,6 +67,7 @@ import org.netbeans.spi.debugger.ui.BreakpointType; import org.netbeans.spi.debugger.ui.ColumnModelRegistration; import org.netbeans.spi.debugger.ui.ColumnModelRegistrations; +import org.netbeans.spi.debugger.ui.DebuggingView; import org.netbeans.spi.viewmodel.ColumnModel; import org.openide.filesystems.annotations.LayerBuilder; @@ -86,7 +87,9 @@ return new HashSet(Arrays.asList( AttachType.Registration.class.getCanonicalName(), BreakpointType.Registration.class.getCanonicalName(), - ColumnModelRegistration.class.getCanonicalName() + ColumnModelRegistration.class.getCanonicalName(), + ColumnModelRegistrations.class.getCanonicalName(), + DebuggingView.DVSupport.Registration.class.getCanonicalName() )); } @@ -137,6 +140,13 @@ } cnt++; } + for (Element e : env.getElementsAnnotatedWith(DebuggingView.DVSupport.Registration.class)) { + DebuggingView.DVSupport.Registration reg = e.getAnnotation(DebuggingView.DVSupport.Registration.class); + final String path = reg.path(); + final int position = reg.position(); + handleProviderRegistration(e, DebuggingView.DVSupport.class, path, position); + cnt++; + } return cnt == annotations.size(); } diff --git a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/Bundle.properties b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/Bundle.properties new file mode 100644 --- /dev/null +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/Bundle.properties @@ -0,0 +1,110 @@ +# 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-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. + +#DebuggingView +CTL_Debugging_view=Debugging +CTL_Debugging_tooltip=Debugging View +LBL_No_Session_Running=no session running + +LBL_THREAD_GROUPS_TIP=Show thread groups +LBL_SUSPEND_TABLE_TIP=Show suspend/resume table +LBL_SYSTEM_THREADS_TIP=Show system threads +LBL_SUPSENDED_THREADS_ONLY_TIP=Show Less (suspended and current threads only) +LBL_MONITORS_TIP=Show monitors +LBL_QUALIFIED_NAMES_TIP=Show qualified names +LBL_SUSPEND_SORT_TIP=Sort by suspended/resumed state +LBL_ALPHABETIC_SORT_TIP=Sort by name +LBL_NATURAL_SORT_TIP=Sort by default + +LBL_THREAD_GROUPS=Show Thread &Groups +LBL_SUSPEND_TABLE=Show Suspend/Resume &Table +LBL_SYSTEM_THREADS=Show &System Threads +LBL_SUPSENDED_THREADS_ONLY=Show &Less +LBL_MONITORS=Show &Monitors +LBL_QUALIFIED_NAMES=Show Qualified &Names +LBL_SUSPEND_SORT=Sort by S&tate +LBL_ALPHABETIC_SORT=Sort by &Name +LBL_NATURAL_SORT=&Default Sorting + +LBL_FilterSubmenu=&Options + +LBL_CURRENT_BAR_TIP=Current thread (selected for stepping and evaluation) +LBL_CURRENT_DEADLOCKED_TIP=Current thread in deadlock +LBL_BREAKPOINT_HIT_TIP=New breakpoint hit +LBL_DEADLOCKED_THREAD_TIP=Thread in deadlock + +LBL_SUSPEND_THREAD=Suspend thread {0} +LBL_RESUME_THREAD=Resume thread {0} + +#InfoPanel +LBL_OneNewHit=New Breakpoint Hit +LBL_NewHits=New Breakpoint Hits ({0}) + +#Threads History action +CTL_ThreadsHistoryAction=Threads History +CTL_THREADS_CHOOSER=Current Thread Chooser + +InfoPanel.hitsLabel.text=New Breakpoint Hit +InfoPanel.infoIcon.text= +InfoPanel.infoIcon1.text= +InfoPanel.deadlocksLabel.text=Deadlock detected +InfoPanel.infoIcon2.text= +InfoPanel.debuggerDeadlocksLabelThread.text=Step is blocked by suspended thread ''{0}''. +InfoPanel.debuggerDeadlocksLabel.Method.text=Method invocation is blocked by other suspended threads. +InfoPanel.debuggerDeadlocksLabelThread.Method.text=Method invocation is blocked by suspended thread ''{0}''. +InfoPanel.debuggerDeadlocksLabel.text=Step is blocked by other suspended threads. +InfoPanel.debuggerDeadlocksLabel.tooltip=Blocking threads are: {0}. +InfoPanel.resumeDebuggerDeadlockLabelThread.text=Resume this thread to proceed? +InfoPanel.resumeDebuggerDeadlockLabel.text=Resume these threads to proceed? +InfoPanel.resumeDebuggerDeadlockButton.text=Resume +InfoPanel.resumeDebuggerDeadlockButton.tooltip=Resume threads {0} to complete the step. +InfoPanel.resumeDebuggerDeadlockButton.Method.tooltip=Resume threads {0} to complete the method evaluation. +InfoPanel.resumeDebuggerDeadlockButtonThread.tooltip=Resume thread ''{0}'' to complete the step. +InfoPanel.resumeDebuggerDeadlockButtonThread.Method.tooltip=Resume thread ''{0}'' to complete the method evaluation. +DebuggingView.sessionComboBox.AccessibleContext.accessibleName=Sessions +DebuggingView.sessionComboBox.AccessibleContext.accessibleDescription=List of running sessions. +DebuggingView.treeView.AccessibleContext.accessibleName=Debugging Tree +DebuggingView.treeView.AccessibleContext.accessibleDescription=Tree structure of threads in debugged VM. +InfoPanel.infoIcon3.text= +InfoPanel.stepBrkpLabel.text=Step interrupted by a breakpoint in another thread ''{0}''. +InfoPanel.stepBrkpIgnoreButton.text=Ignore Breakpoint +InfoPanel.stepBrkpIgnoreButton.tooltip=Ignore this breakpoint and complete the step. diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/ClickableIcon.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/ClickableIcon.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/ClickableIcon.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/ClickableIcon.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/ClickableIcon.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/ClickableIcon.java @@ -40,7 +40,7 @@ * Portions Copyrighted 2008 Sun Microsystems, Inc. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import java.awt.Container; import java.awt.Dimension; @@ -51,8 +51,7 @@ import javax.swing.JLabel; import javax.swing.SwingConstants; import org.netbeans.api.debugger.Session; -import org.netbeans.api.debugger.jpda.JPDADebugger; -import org.netbeans.api.debugger.jpda.JPDAThread; +import org.netbeans.spi.debugger.ui.DebuggingView.DVThread; import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.RequestProcessor; @@ -79,11 +78,11 @@ private int state; private boolean isThreadSupended; - private JPDAThread jpdaThread; + private DVThread dvThread; private DebugTreeView tree; ClickableIcon(ImageIcon normalR, ImageIcon focusedR, ImageIcon pressedR, - ImageIcon normalS, ImageIcon focusedS, ImageIcon pressedS, JPDAThread jpdaThread, DebugTreeView tree) { + ImageIcon normalS, ImageIcon focusedS, ImageIcon pressedS, DVThread dvThread, DebugTreeView tree) { this.tree = tree; this.resumeIcon = normalR; this.focusedResumeIcon = focusedR; @@ -93,8 +92,8 @@ this.focusedSuspendIcon = focusedS; this.pressedSuspendIcon = pressedS; - isThreadSupended = jpdaThread.isSuspended(); - this.jpdaThread = jpdaThread; + isThreadSupended = dvThread.isSuspended(); + this.dvThread = dvThread; setHorizontalAlignment(SwingConstants.CENTER); setVerticalAlignment(SwingConstants.CENTER); @@ -115,13 +114,13 @@ addMouseListener(this); } - void changeThread(JPDAThread newThread, Container container, int sx, int sy, int width, int height) { + void changeThread(DVThread newThread, Container container, int sx, int sy, int width, int height) { boolean suspended = newThread.isSuspended(); - if (jpdaThread == newThread && suspended == isThreadSupended) { + if (dvThread == newThread && suspended == isThreadSupended) { return; } isThreadSupended = newThread.isSuspended(); - this.jpdaThread = newThread; + this.dvThread = newThread; Point point = container.getMousePosition(true); state = point != null && sx <= point.x && point.x < sx + width && sy <= point.y && point.y < sy + height ? STATE_FOCUSED : STATE_NORMAL; @@ -131,11 +130,11 @@ private void setFocusedThread() { if (state != STATE_NORMAL) { - if (tree != null && tree.threadFocuseGained(jpdaThread)) { + if (tree != null && tree.threadFocuseGained(dvThread)) { getParent().repaint(); } } else { - if (tree != null && tree.threadFocuseLost(jpdaThread)) { + if (tree != null && tree.threadFocuseLost(dvThread)) { getParent().repaint(); } } @@ -160,7 +159,7 @@ private void changeIcon() { setIcon(computeIcon()); String key = isThreadSupended ? "LBL_RESUME_THREAD" : "LBL_SUSPEND_THREAD"; // NOI18N - String text = NbBundle.getMessage(ClickableIcon.class, key, jpdaThread.getName()); + String text = NbBundle.getMessage(ClickableIcon.class, key, dvThread.getName()); setToolTipText(text); } @@ -168,8 +167,7 @@ final boolean suspended = isThreadSupended; RequestProcessor rp; try { - JPDADebugger debugger = (JPDADebugger) jpdaThread.getClass().getMethod("getDebugger").invoke(jpdaThread); - Session s = (Session) debugger.getClass().getMethod("getSession").invoke(debugger); + Session s = dvThread.getDVSupport().getSession(); rp = s.lookupFirst(null, RequestProcessor.class); } catch (Exception e) { Exceptions.printStackTrace(e); @@ -182,9 +180,9 @@ rp.post(new Runnable() { public void run() { if (suspended) { - jpdaThread.resume(); + dvThread.resume(); } else { - jpdaThread.suspend(); + dvThread.suspend(); } } }); diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/DebugTreeView.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/DebugTreeView.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/DebugTreeView.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/DebugTreeView.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/DebugTreeView.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/DebugTreeView.java @@ -40,7 +40,7 @@ * Portions Copyrighted 2008 Sun Microsystems, Inc. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import java.awt.Color; import java.awt.Component; @@ -63,11 +63,12 @@ import javax.swing.tree.RowMapper; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; +import org.netbeans.api.debugger.DebuggerEngine; +import org.netbeans.api.debugger.DebuggerManager; -import org.netbeans.api.debugger.jpda.JPDADebugger; -import org.netbeans.api.debugger.jpda.JPDAThread; -import org.netbeans.api.debugger.jpda.JPDAThreadGroup; -import org.netbeans.modules.debugger.jpda.ui.models.DebuggingTreeModel; +import org.netbeans.spi.debugger.ui.DebuggingView; +import org.netbeans.spi.debugger.ui.DebuggingView.DVThread; +import org.netbeans.spi.debugger.ui.DebuggingView.DVThreadGroup; import org.netbeans.spi.viewmodel.TreeExpansionModel; import org.openide.explorer.view.BeanTreeView; @@ -88,7 +89,7 @@ private final Color highlightColor; private final Color currentThreadColor; - private JPDAThread focusedThread; + private DVThread focusedThread; DebugTreeView() { super(); @@ -96,7 +97,7 @@ if (c == null) { c = new Color(233, 255, 230); Color tbc = tree.getBackground(); - int dl = Math.abs(DebuggingView.luminance(c) - DebuggingView.luminance(tbc)); + int dl = Math.abs(DebuggingViewComponent.luminance(c) - DebuggingViewComponent.luminance(tbc)); if (dl > 125) { c = new Color(30, 80, 28); } @@ -106,7 +107,7 @@ if (c == null) { c = new Color(233, 239, 248); Color tbc = tree.getBackground(); - int dl = Math.abs(DebuggingView.luminance(c) - DebuggingView.luminance(tbc)); + int dl = Math.abs(DebuggingViewComponent.luminance(c) - DebuggingViewComponent.luminance(tbc)); if (dl > 125) { c = new Color(40, 60, 38); } @@ -191,13 +192,18 @@ } } - public Object getJPDAObject(TreePath path) { + /** + * Get the DVThread or DVThreadGroup instance on the given path. + * @param path + * @return an instance of DVThread or DVThreadGroup + */ + public Object getThreadObject(TreePath path) { Node node = Visualizer.findNode(path.getLastPathComponent()); - JPDAThread jpdaThread = node.getLookup().lookup(JPDAThread.class); + DVThread jpdaThread = node.getLookup().lookup(DVThread.class); if (jpdaThread != null) { return jpdaThread; } - JPDAThreadGroup jpdaThreadGroup = node.getLookup().lookup(JPDAThreadGroup.class); + DVThreadGroup jpdaThreadGroup = node.getLookup().lookup(DVThreadGroup.class); return jpdaThreadGroup; } @@ -273,20 +279,14 @@ } Color origColor = g.getColor(); - ThreadsListener threadsListener = ThreadsListener.getDefault(); - JPDADebugger debugger = threadsListener != null ? threadsListener.getDebugger() : null; - JPDAThread currentThread = (debugger != null) ? debugger.getCurrentThread() : null; - if (currentThread != null && !currentThread.isSuspended() && - !DebuggingTreeModel.isMethodInvoking(currentThread)) { - currentThread = null; - } + DVThread currentThread = getCurrentThread(); boolean isHighlighted = false; boolean isCurrent = false; Iterator iter = paths.iterator(); int firstGroupNumber = clipY / rowHeight; for (int x = 0; x <= firstGroupNumber && iter.hasNext(); x++) { Node node = Visualizer.findNode(iter.next().getLastPathComponent()); - JPDAThread thread = node.getLookup().lookup(JPDAThread.class); + DVThread thread = node.getLookup().lookup(DVThread.class); isHighlighted = focusedThread != null && thread == focusedThread; if (thread != null) { isCurrent = currentThread == thread; @@ -306,7 +306,7 @@ sy += rowHeight; if (iter.hasNext()) { Node node = Visualizer.findNode(iter.next().getLastPathComponent()); - JPDAThread thread = node.getLookup().lookup(JPDAThread.class); + DVThread thread = node.getLookup().lookup(DVThread.class); isHighlighted = focusedThread != null && thread == focusedThread; if (thread != null) { isCurrent = currentThread == thread; @@ -322,8 +322,20 @@ // } g.setColor(origColor); } + + private DVThread getCurrentThread() { + DVThread currentThread = null; + DebuggerEngine currentEngine = DebuggerManager.getDebuggerManager().getCurrentEngine(); + if (currentEngine != null) { + DebuggingView.DVSupport dvSupport = currentEngine.lookupFirst(null, DebuggingView.DVSupport.class); + if (dvSupport != null) { + currentThread = dvSupport.getCurrentThread(); + } + } + return currentThread; + } - boolean threadFocuseGained(JPDAThread jpdaThread) { + boolean threadFocuseGained(DVThread jpdaThread) { if (jpdaThread != null && focusedThread != jpdaThread) { focusedThread = jpdaThread; repaint(); @@ -332,7 +344,7 @@ return false; } - boolean threadFocuseLost(JPDAThread jpdaThread) { + boolean threadFocuseLost(DVThread jpdaThread) { if (jpdaThread != null && focusedThread == jpdaThread) { focusedThread = null; repaint(); @@ -357,21 +369,15 @@ } if (value instanceof Node) { Node node = (Node) value; - JPDAThread thread; + DVThread thread; do { - thread = node.getLookup().lookup(JPDAThread.class); + thread = node.getLookup().lookup(DVThread.class); if (thread == null) { node = node.getParentNode(); } } while (thread == null && node != null); if (thread != null) { - ThreadsListener threadsListener = ThreadsListener.getDefault(); - JPDADebugger debugger = threadsListener != null ? threadsListener.getDebugger() : null; - JPDAThread currentThread = (debugger != null) ? debugger.getCurrentThread() : null; - if (currentThread != null && !currentThread.isSuspended() && - !DebuggingTreeModel.isMethodInvoking(currentThread)) { - currentThread = null; - } + DVThread currentThread = getCurrentThread(); boolean isHighlighted = focusedThread != null && thread == focusedThread && node == value; boolean isCurrent = currentThread == thread; if (isHighlighted || isCurrent) { diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/DebuggingView.form b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/DebuggingViewComponent.form copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/DebuggingView.form copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/DebuggingViewComponent.form --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/DebuggingView.form +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/DebuggingViewComponent.form @@ -1,4 +1,4 @@ - +
@@ -29,10 +29,10 @@ - + - + diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/DebuggingView.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/DebuggingViewComponent.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/DebuggingView.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/DebuggingViewComponent.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/DebuggingView.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/DebuggingViewComponent.java @@ -40,7 +40,7 @@ * Portions Copyrighted 2008 Sun Microsystems, Inc. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import java.awt.BorderLayout; import java.awt.Color; @@ -98,12 +98,10 @@ import org.netbeans.api.debugger.DebuggerEngine; import org.netbeans.api.debugger.DebuggerManager; import org.netbeans.api.debugger.Session; -import org.netbeans.api.debugger.jpda.DeadlockDetector.Deadlock; -import org.netbeans.api.debugger.jpda.JPDADebugger; -import org.netbeans.api.debugger.jpda.JPDAThread; -import org.netbeans.api.debugger.jpda.JPDAThreadGroup; -import org.netbeans.api.debugger.jpda.ThreadsCollector; -import org.netbeans.modules.debugger.jpda.ui.models.DebuggingTreeModel; +import org.netbeans.spi.debugger.ui.DebuggingView.DVSupport; +import org.netbeans.spi.debugger.ui.DebuggingView.DVThread; +import org.netbeans.spi.debugger.ui.DebuggingView.DVThreadGroup; +import org.netbeans.spi.debugger.ui.DebuggingView.Deadlock; import org.netbeans.spi.debugger.ui.ViewFactory; import org.netbeans.spi.debugger.ui.ViewLifecycle; @@ -126,7 +124,7 @@ * * @author Dan */ -public class DebuggingView extends TopComponent implements org.openide.util.HelpCtx.Provider, +public class DebuggingViewComponent extends TopComponent implements org.openide.util.HelpCtx.Provider, ExplorerManager.Provider, PropertyChangeListener, TreeExpansionListener, TreeModelListener, AdjustmentListener, ChangeListener, MouseWheelListener, TreeSelectionListener, ViewLifecycle.ModelUpdateListener { @@ -159,11 +157,11 @@ private DebugTreeView treeView; private TapPanel tapPanel; private InfoPanel infoPanel; - private JPDADebugger debugger; + private DVSupport debugger; private Session session; - private JPDADebugger previousDebugger; - private Reference threadMadeCurrentRef; - private Reference threadToScrollRef; + private DVSupport previousDebugger; + private Reference threadMadeCurrentRef; + private Reference threadToScrollRef; private ViewRefresher viewRefresher = new ViewRefresher(); private BarsPanel leftPanel; @@ -216,10 +214,10 @@ * * @see #getInstance */ - private static Reference instance = null; + private static Reference instance = null; /** Creates new form DebuggingView */ - public DebuggingView() { + public DebuggingViewComponent() { setIcon(ImageUtilities.loadImage ("org/netbeans/modules/debugger/jpda/resources/debugging.png")); // NOI18N // Remember the location of the component when closed. putClientProperty("KeepNonPersistentTCInModelWhenClosed", Boolean.TRUE); // NOI18N @@ -296,8 +294,8 @@ gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; add(sessionComboBox, gridBagConstraints); - sessionComboBox.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(DebuggingView.class, "DebuggingView.sessionComboBox.AccessibleContext.accessibleName")); // NOI18N - sessionComboBox.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(DebuggingView.class, "DebuggingView.sessionComboBox.AccessibleContext.accessibleDescription")); // NOI18N + sessionComboBox.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(DebuggingViewComponent.class, "DebuggingViewComponent.sessionComboBox.AccessibleContext.accessibleName")); // NOI18N + sessionComboBox.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(DebuggingViewComponent.class, "DebuggingViewComponent.sessionComboBox.AccessibleContext.accessibleDescription")); // NOI18N mainScrollPane.setBorder(null); mainScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -378,10 +376,10 @@ threadsListener = ThreadsListener.getDefault(); } if (engine != null) { - final JPDADebugger deb = engine.lookupFirst(null, JPDADebugger.class); + final DVSupport deb = engine.lookupFirst(null, DVSupport.class); if (deb != null) { if (threadsListener != null) { - threadsListener.setDebuggingView(this); + threadsListener.setDebuggingView(deb, this); } } synchronized (lock) { @@ -405,6 +403,7 @@ } }); } + FiltersDescriptor.getInstance().setUpFilters(deb); } else { synchronized (lock) { if (previousDebugger != null) { @@ -422,6 +421,7 @@ } }); } + FiltersDescriptor.getInstance().setUpFilters(null); } SwingUtilities.invokeLater(new Runnable() { @Override @@ -461,9 +461,9 @@ return manager; } - public static DebuggingView getInstance() { - DebuggingView view; - view = (DebuggingView) WindowManager.getDefault().findTopComponent(ID); + public static DebuggingViewComponent getInstance() { + DebuggingViewComponent view; + view = (DebuggingViewComponent) WindowManager.getDefault().findTopComponent(ID); if (view == null) { view = getDefault(); } @@ -488,16 +488,16 @@ * * @return singleton - instance of this class */ - public static synchronized DebuggingView getDefault() { - DebuggingView view; + public static synchronized DebuggingViewComponent getDefault() { + DebuggingViewComponent view; if (instance == null) { - view = new DebuggingView(); - instance = new WeakReference(view); + view = new DebuggingViewComponent(); + instance = new WeakReference(view); } else { view = instance.get(); if (view == null) { - view = new DebuggingView(); - instance = new WeakReference(view); + view = new DebuggingViewComponent(); + instance = new WeakReference(view); } } return view; @@ -556,12 +556,12 @@ @Override public String getName() { - return NbBundle.getMessage (DebuggingView.class, "CTL_Debugging_view"); // NOI18N + return NbBundle.getMessage (DebuggingViewComponent.class, "CTL_Debugging_view"); // NOI18N } @Override public String getToolTipText() { - return NbBundle.getMessage (DebuggingView.class, "CTL_Debugging_tooltip"); // NOI18N + return NbBundle.getMessage (DebuggingViewComponent.class, "CTL_Debugging_tooltip"); // NOI18N } @Override @@ -570,13 +570,13 @@ if (ExplorerManager.PROP_ROOT_CONTEXT.equals(propertyName) || ExplorerManager.PROP_NODE_CHANGE.equals(propertyName)) { refreshView(); - } else if (JPDADebugger.PROP_CURRENT_THREAD.equals(propertyName)) { - JPDAThread currentThread; + } else if (DVSupport.PROP_CURRENT_THREAD.equals(propertyName)) { + DVThread currentThread; synchronized (lock) { currentThread = (debugger != null) ? debugger.getCurrentThread() : null; } if (currentThread != null) { - JPDAThread thread = threadMadeCurrentRef != null ? threadMadeCurrentRef.get() : null; + DVThread thread = threadMadeCurrentRef != null ? threadMadeCurrentRef.get() : null; if (thread == currentThread) { threadToScrollRef = new WeakReference(thread); } @@ -597,12 +597,12 @@ } } - private static boolean isJPDASession(Session s) { + private static boolean isDebuggingSession(Session s) { DebuggerEngine engine = s.getCurrentEngine (); if (engine == null) { return false; } - return engine.lookupFirst(null, JPDADebugger.class) != null; + return engine.lookupFirst(null, DVSupport.class) != null; } void updateSessionsComboBox() { @@ -616,7 +616,7 @@ DebuggerManager dm = DebuggerManager.getDebuggerManager(); Session[] sessions = dm.getSessions(); for (int x = 0; x < sessions.length; x++) { - if (isJPDASession(sessions[x])) { + if (isDebuggingSession(sessions[x])) { sessionComboBox.addItem(new SessionItem(sessions[x])); } } @@ -631,7 +631,7 @@ }); } - void makeThreadCurrent(JPDAThread thread) { + void makeThreadCurrent(DVThread thread) { threadMadeCurrentRef = new WeakReference(thread); thread.makeCurrent(); } @@ -643,8 +643,8 @@ treeView.setRootVisible(false); treeView.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); treeView.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - treeView.getAccessibleContext().setAccessibleName(NbBundle.getMessage(DebuggingView.class, "DebuggingView.treeView.AccessibleContext.accessibleName")); // NOI18N - treeView.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(DebuggingView.class, "DebuggingView.treeView.AccessibleContext.accessibleDescription")); // NOI18N + treeView.getAccessibleContext().setAccessibleName(NbBundle.getMessage(DebuggingViewComponent.class, "DebuggingView.treeView.AccessibleContext.accessibleName")); // NOI18N + treeView.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(DebuggingViewComponent.class, "DebuggingView.treeView.AccessibleContext.accessibleDescription")); // NOI18N treeView.getTree().addMouseWheelListener(this); treeView.addTreeExpansionListener(this); TreeModel model = treeView.getTree().getModel(); @@ -723,19 +723,22 @@ @Override public void run() { refreshScheduled.set(false); - JPDAThread currentThread; - ThreadsCollector tc; - synchronized (DebuggingView.this.lock) { - currentThread = debugger != null ? debugger.getCurrentThread() : null; - tc = debugger != null ? debugger.getThreadsCollector() : null; + DVThread currentThread = null; + Set deadlocks = null; + DVSupport supp; + synchronized (DebuggingViewComponent.this.lock) { + supp = debugger; + } + if (supp != null) { + currentThread = supp.getCurrentThread(); + deadlocks = supp.getDeadlocks(); } // collect all deadlocked threads - Set deadlocks = tc != null ? tc.getDeadlockDetector().getDeadlocks() : null; - Set deadlockedThreads; + Set deadlockedThreads; if (deadlocks == null) { deadlockedThreads = Collections.EMPTY_SET; } else { - deadlockedThreads = new HashSet(); + deadlockedThreads = new HashSet(); for (Deadlock deadlock : deadlocks) { deadlockedThreads.addAll(deadlock.getThreads()); } @@ -870,10 +873,10 @@ private final class ViewRefresher implements Runnable { - private JPDAThread currentThread; - private Set deadlockedThreads; + private DVThread currentThread; + private Set deadlockedThreads; - void setup(JPDAThread currentThread, Set deadlockedThreads) { + void setup(DVThread currentThread, Set deadlockedThreads) { this.currentThread = currentThread; this.deadlockedThreads = deadlockedThreads; } @@ -886,7 +889,7 @@ int sx = (rightPanel.getWidth() - ClickableIcon.CLICKABLE_ICON_WIDTH) / 2; int sy = 0; - JPDAThread threadToScroll = threadToScrollRef != null ? threadToScrollRef.get() : null; + DVThread threadToScroll = threadToScrollRef != null ? threadToScrollRef.get() : null; threadToScrollRef = null; int scrollStart = -1, scrollEnd = -1; boolean pathToScrollSearching = false; @@ -904,8 +907,8 @@ if (tView != null) { for (TreePath path : tView.getVisiblePaths()) { Node node = Visualizer.findNode(path.getLastPathComponent()); - JPDAThread jpdaThread = node.getLookup().lookup(JPDAThread.class); - JPDAThreadGroup jpdaThreadGroup = node.getLookup().lookup(JPDAThreadGroup.class); + DVThread jpdaThread = node.getLookup().lookup(DVThread.class); + DVThreadGroup jpdaThreadGroup = node.getLookup().lookup(DVThreadGroup.class); JTree tree = tView.getTree(); Rectangle rect = tree.getRowBounds(tree.getRowForPath(path)); @@ -922,8 +925,8 @@ } leftBarHeight = 0; if (jpdaThread != null) { - isCurrent = jpdaThread == currentThread && (jpdaThread.isSuspended() || - DebuggingTreeModel.isMethodInvoking(jpdaThread)); + isCurrent = jpdaThread == currentThread;/* && (jpdaThread.isSuspended() || + DebuggingTreeModel.isMethodInvoking(jpdaThread));*/ isAtBreakpoint = threadsListener.isBreakpointHit(jpdaThread); isInDeadlock = deadlockedThreads.contains(jpdaThread); } else { @@ -975,13 +978,13 @@ } } - private void addPanels(Object jpdaObject, boolean current, boolean atBreakpoint, + private void addPanels(Object dvObject, boolean current, boolean atBreakpoint, boolean inDeadlock, int height, int sx, int sy, int rowHeight) { if (current || atBreakpoint || inDeadlock) { leftPanel.addBar(current, atBreakpoint, inDeadlock, height, sy); } - if (jpdaObject instanceof JPDAThread) { - rightPanel.addIcon(sx, sy, rowHeight, (JPDAThread)jpdaObject); + if (dvObject instanceof DVThread) { + rightPanel.addIcon(sx, sy, rowHeight, (DVThread) dvObject); } } } @@ -1007,17 +1010,17 @@ Color secondaryColor = null; if (inDeadlock) { color = deadlockColor; - toolTipText = NbBundle.getMessage(DebuggingView.class, "LBL_DEADLOCKED_THREAD_TIP"); + toolTipText = NbBundle.getMessage(DebuggingViewComponent.class, "LBL_DEADLOCKED_THREAD_TIP"); } else if (isCurrent) { color = greenBarColor; - toolTipText = NbBundle.getMessage(DebuggingView.class, "LBL_CURRENT_BAR_TIP"); + toolTipText = NbBundle.getMessage(DebuggingViewComponent.class, "LBL_CURRENT_BAR_TIP"); } else if (atBreakpoint) { color = hitsBarColor; - toolTipText = NbBundle.getMessage(DebuggingView.class, "LBL_BREAKPOINT_HIT_TIP"); + toolTipText = NbBundle.getMessage(DebuggingViewComponent.class, "LBL_BREAKPOINT_HIT_TIP"); } if (isCurrent && inDeadlock) { secondaryColor = greenBarColor; - toolTipText = NbBundle.getMessage(DebuggingView.class, "LBL_CURRENT_DEADLOCKED_TIP"); + toolTipText = NbBundle.getMessage(DebuggingViewComponent.class, "LBL_CURRENT_DEADLOCKED_TIP"); } Bar bar = new Bar(sy, height, color, secondaryColor, toolTipText); bars.add(bar); @@ -1123,12 +1126,12 @@ } } - public void addIcon(int sx, int sy, int rowHeight, JPDAThread jpdaThread) { + public void addIcon(int sx, int sy, int rowHeight, DVThread dvThread) { int height = sy - endSY + rowHeight; IconItem item; if (counter < icons.size()) { item = icons.get(counter); - item.icon.changeThread(jpdaThread, DebuggingView.this, sx, sy, + item.icon.changeThread(dvThread, DebuggingViewComponent.this, sx, sy, ClickableIcon.CLICKABLE_ICON_WIDTH, height); item.panel.setPreferredSize(new Dimension(ClickableIcon.CLICKABLE_ICON_WIDTH, height)); item.height = height; @@ -1139,7 +1142,7 @@ panel.setPreferredSize(new Dimension(ClickableIcon.CLICKABLE_ICON_WIDTH, height)); ClickableIcon icon = new ClickableIcon(resumeIcon, focusedResumeIcon, pressedResumeIcon, - suspendIcon, focusedSuspendIcon, pressedSuspendIcon, jpdaThread, treeView); + suspendIcon, focusedSuspendIcon, pressedSuspendIcon, dvThread, treeView); icon.setBackground(treeBackgroundColor); GridBagConstraints gridBagConstraints = new GridBagConstraints(); @@ -1154,7 +1157,7 @@ gridBagConstraints.insets = new Insets(insetTop, 0, insetBottom, 0); panel.add(icon, gridBagConstraints); - icon.initializeState(DebuggingView.this, sx, sy, ClickableIcon.CLICKABLE_ICON_WIDTH, height); + icon.initializeState(DebuggingViewComponent.this, sx, sy, ClickableIcon.CLICKABLE_ICON_WIDTH, height); item = new IconItem(height, icon, panel); icons.add(item); @@ -1249,7 +1252,7 @@ if (session != null) { return session.getName(); } else { - return '<' + NbBundle.getMessage(DebuggingView.class, "LBL_No_Session_Running") + '>'; + return '<' + NbBundle.getMessage(DebuggingViewComponent.class, "LBL_No_Session_Running") + '>'; } } diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/FiltersDescriptor.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/FiltersDescriptor.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/FiltersDescriptor.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/FiltersDescriptor.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/FiltersDescriptor.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/FiltersDescriptor.java @@ -42,7 +42,7 @@ * made subject to such option by the copyright holder. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import java.awt.event.ActionEvent; import java.awt.event.HierarchyEvent; @@ -52,6 +52,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.prefs.AbstractPreferences; +import java.util.prefs.BackingStoreException; import java.util.prefs.PreferenceChangeEvent; import java.util.prefs.PreferenceChangeListener; import java.util.prefs.Preferences; @@ -66,12 +68,12 @@ import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JRadioButtonMenuItem; +import org.netbeans.spi.debugger.ui.DebuggingView.DVFilter; +import org.netbeans.spi.debugger.ui.DebuggingView.DVFilter.Group; +import org.netbeans.spi.debugger.ui.DebuggingView.DVSupport; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; -import org.netbeans.modules.debugger.jpda.ui.models.DebuggingMonitorModel; -import org.netbeans.modules.debugger.jpda.ui.models.DebuggingNodeModel; -import org.netbeans.modules.debugger.jpda.ui.models.DebuggingTreeModel; import org.openide.awt.Mnemonics; import org.openide.util.ImageUtilities; import org.openide.util.WeakListeners; @@ -89,30 +91,61 @@ public static final String SHOW_SUSPEND_TABLE = "show_suspend_table"; public static final String SHOW_THREAD_GROUPS = "thread_group"; public static final String SHOW_SUSPENDED_THREADS_ONLY = "suspended_threads_only"; + + public static final String PREF_SORT_ALPHABET = "sort.alphabet"; + public static final String PREF_SORT_NATURAL = "sort.natural"; + public static final String PREF_SORT_SUSPEND = "sort.suspend"; + public static final String PREF_SHOW_MONITORS = "show.monitors"; // NOI18N + public static final String PREF_SHOW_SYSTEM_THREADS = "show.systemThreads"; + public static final String PREF_SHOW_THREAD_GROUPS = "show.threadGroups"; + public static final String PREF_SHOW_SUSPENDED_THREADS_ONLY = "show.suspendedThreadsOnly"; + public static final String PREF_SHOW_SUSPEND_TABLE = "show_suspend_table"; + public static final String PREF_SHOW_PACKAGE_NAMES = "show.packageNames"; + private static FiltersDescriptor instance; /** List of describing filters properties */ - private List filters; + private List filters; private Action[] filterActions; + + private FiltersAccessor filtersAccessor; /** Creates a new instance of FiltersDescriptor */ private FiltersDescriptor() { - filters = new ArrayList(); + filters = Collections.emptyList(); } public synchronized static FiltersDescriptor getInstance() { if (instance == null) { - instance = createDebuggingViewFilters(); + instance = new FiltersDescriptor(); + //instance = createDebuggingViewFilters(); } return instance; } + void setUpFilters(DVSupport dvs) { + List fs; + if (dvs != null) { + fs = filtersAccessor.getFilters(dvs); + } else { + fs = Collections.emptyList(); + } + synchronized (this) { + this.filters = fs; + this.filterActions = null; + } + } + public synchronized Action[] getFilterActions() { if (filterActions == null) { + if (filters.isEmpty()) { + filterActions = new Action[] {}; + return filterActions; + } List list = new ArrayList(); - for (Item item : filters) { + for (DVFilter item : filters) { if (item.getGroup() != null) { SortAction action = new SortAction(item); list.add(action); @@ -134,23 +167,23 @@ } public String getName(int index) { - return filters.get(index).name; + return filters.get(index).getName(); } public String getDisplayName(int index) { - return filters.get(index).displayName; + return filters.get(index).getDisplayName(); } public String getTooltip(int index) { - return filters.get(index).tooltip; + return filters.get(index).getTooltip(); } public Icon getSelectedIcon(int index) { - return filters.get(index).selectedIcon; + return filters.get(index).getIcon(); } public boolean isSelected(int index) { - return filters.get(index).isSelected; + return filters.get(index).isSelected(); } public void setSelected(int index, boolean selected) { @@ -158,7 +191,7 @@ } public void setSelected(String filterName, boolean selected) { - for (Item item : filters) { + for (DVFilter item : filters) { if (item.getName().equals(filterName)) { item.setSelected(selected); break; @@ -167,11 +200,13 @@ } public void connectToggleButton(int index, JToggleButton button) { - filters.get(index).setToggleButton(button); + FilterImpl impl = FiltersDescriptor.getInstance().filtersAccessor.getImpl(filters.get(index)); + impl.setToggleButton(button); } // ************************************************************************** + /* private static FiltersDescriptor createDebuggingViewFilters() { FiltersDescriptor desc = new FiltersDescriptor(); desc.addItem(new Item(SHOW_SUSPENDED_THREADS_ONLY, getString("LBL_SUPSENDED_THREADS_ONLY"), getString("LBL_SUPSENDED_THREADS_ONLY_TIP"), @@ -212,12 +247,13 @@ group.setItems(groupMembers); return desc; } + */ // ************************************************************************** - private void addItem (Item newItem) { + /*private void addItem (Item newItem) { filters.add(newItem); - } + }*/ private static Icon loadIcon(String iconName) { return ImageUtilities.loadImageIcon("org/netbeans/modules/debugger/jpda/resources/" + iconName, false); @@ -226,28 +262,122 @@ private static String getString(String label) { return NbBundle.getMessage(FiltersDescriptor.class, label); } + + public void setFiltersAccessor(FiltersAccessor filtersAccessor) { + this.filtersAccessor = filtersAccessor; + } + + public static interface FiltersAccessor { + public List getFilters(DVSupport dvs); + public FilterImpl getImpl(DVFilter filter); + } // ************************************************************************** // filter Item // ************************************************************************** - static class Item { - String name; - String displayName; - String tooltip; - Icon selectedIcon; - PreferenceChangeListener pchl; + public static class FilterImpl { + private String name; + private String displayName; + private String tooltip; + private Icon selectedIcon; + private Preferences prefs; + private String prefKey; + private PreferenceChangeListener pchl; private boolean isSelected; private Group group; private Reference toggleButtonRef; - Item (String name, String displayName, String tooltip, - boolean isSelected, Icon selectedIcon) { + public static FilterImpl createDefault(DVFilter.DefaultFilter df) { + FilterImpl fimpl; + switch (df) { + case showMonitors: + fimpl = new FilterImpl(SHOW_MONITORS, getString("LBL_MONITORS"), + getString("LBL_MONITORS_TIP"), + loadIcon("monitor_acquired_16.png"), + getDefaultPreferences(), + PREF_SHOW_MONITORS, false); + break; + case showQualifiedNames: + fimpl = new FilterImpl(SHOW_QUALIFIED_NAMES, + getString("LBL_QUALIFIED_NAMES"), + getString("LBL_QUALIFIED_NAMES_TIP"), + loadIcon("show_fqn_option_16.png"), + getDefaultPreferences(), + PREF_SHOW_PACKAGE_NAMES, false); + break; + case showSuspendTable: + fimpl = new FilterImpl(SHOW_SUSPEND_TABLE, + getString("LBL_SUSPEND_TABLE"), + getString("LBL_SUSPEND_TABLE_TIP"), + loadIcon("show_suspend_table_option_16.png"), + getDefaultPreferences(), + PREF_SHOW_SUSPEND_TABLE, true); + break; + case showSuspendedThreadsOnly: + fimpl = new FilterImpl(SHOW_SUSPENDED_THREADS_ONLY, + getString("LBL_SUPSENDED_THREADS_ONLY"), + getString("LBL_SUPSENDED_THREADS_ONLY_TIP"), + loadIcon("show_suspended_threads_option_16.png"), + getDefaultPreferences(), + PREF_SHOW_SUSPENDED_THREADS_ONLY, false); + break; + case showSystemThreads: + fimpl = new FilterImpl(SHOW_SYSTEM_THREADS, + getString("LBL_SYSTEM_THREADS"), + getString("LBL_SYSTEM_THREADS_TIP"), + loadIcon("show_system_threads_option_16.png"), + getDefaultPreferences(), + PREF_SHOW_SYSTEM_THREADS, false); + break; + case showThreadGroups: + fimpl = new FilterImpl(SHOW_THREAD_GROUPS, + getString("LBL_THREAD_GROUPS"), + getString("LBL_THREAD_GROUPS_TIP"), + loadIcon("thread_group_mixed_16.png"), + getDefaultPreferences(), + PREF_SHOW_THREAD_GROUPS, false); + break; + case sortAlphabetic: + fimpl = new FilterImpl(ALPHABETIC_SORT, + getString("LBL_ALPHABETIC_SORT"), + getString("LBL_ALPHABETIC_SORT_TIP"), + loadIcon("alphabetic_sort_order_16.png"), + getDefaultPreferences(), + PREF_SORT_ALPHABET, false); + break; + case sortNatural: + fimpl = new FilterImpl(NATURAL_SORT, + getString("LBL_NATURAL_SORT"), + getString("LBL_NATURAL_SORT_TIP"), + loadIcon("natural_sort_order_16.png"), + getDefaultPreferences(), + PREF_SORT_NATURAL, true); + break; + case sortSuspend: + fimpl = new FilterImpl(SUSPEND_SORT, + getString("LBL_SUSPEND_SORT"), + getString("LBL_SUSPEND_SORT_TIP"), + loadIcon("suspend_property_sort_order_16.png"), + getDefaultPreferences(), + PREF_SORT_SUSPEND, false); + break; + default: + throw new IllegalArgumentException(df.name()); + } + return fimpl; + } + + public FilterImpl (String name, String displayName, String tooltip, + Icon selectedIcon, Preferences prefs, String prefKey, + boolean isSelectedDefault) { this.name = name; this.displayName = displayName; this.tooltip = tooltip; this.selectedIcon = selectedIcon; - this.isSelected = isSelected; + this.isSelected = isSelectedDefault; + this.prefs= prefs; + this.prefKey = prefKey; readValue(); } @@ -267,10 +397,22 @@ public String getDisplayName() { return displayName; } + + public String getTooltip() { + return tooltip; + } public Icon getIcon() { return selectedIcon; } + + public Preferences getPreferences() { + return prefs; + } + + public String getPrefKey() { + return prefKey; + } public boolean isSelected() { return isSelected; @@ -291,8 +433,9 @@ toggleButton.setSelected(state); } if (state && group != null) { - for (Item item : group.getItems()) { - if (item != this && item.isSelected()) { + for (DVFilter item : group.getItems()) { + FilterImpl impl = FiltersDescriptor.getInstance().filtersAccessor.getImpl(item); + if (impl != this && item.isSelected()) { item.setSelected(false); } // if } // for @@ -307,9 +450,13 @@ } private void readValue() { + isSelected = prefs.getBoolean(prefKey, isSelected); + /* + Preferences origPrefs = NbPreferences.root().node("org/netbeans/modules/debugger/jpda/ui").node("debugging"); Preferences preferences = NbPreferences.forModule(getClass()).node("debugging"); // NOI18N if (name.equals(SHOW_SYSTEM_THREADS)) { - isSelected = preferences.getBoolean(DebuggingTreeModel.SHOW_SYSTEM_THREADS, false); + isSelected = origPrefs.getBoolean(DebuggingTreeModel.SHOW_SYSTEM_THREADS, false); + isSelected = preferences.getBoolean(DebuggingTreeModel.SHOW_SYSTEM_THREADS, isSelected); } else if (name.equals(SHOW_THREAD_GROUPS)) { isSelected = preferences.getBoolean(DebuggingTreeModel.SHOW_THREAD_GROUPS, false); } else if (name.equals(ALPHABETIC_SORT)) { @@ -329,7 +476,7 @@ isSelected = preferences.getBoolean(SHOW_SUSPEND_TABLE, true); } else { isSelected = false; - } + }*/ if (pchl == null) { pchl = new PreferenceChangeListener() { @Override @@ -341,11 +488,13 @@ } } }; - preferences.addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, pchl, preferences)); + prefs.addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, pchl, prefs)); } } private void writeValue() { + prefs.putBoolean(prefKey, isSelected); + /* String keyName = null; Preferences preferences = NbPreferences.forModule(getClass()).node("debugging"); // NOI18N if (name.equals(SHOW_SYSTEM_THREADS)) { @@ -367,7 +516,71 @@ } if (keyName != null) { preferences.putBoolean(keyName, isSelected); - } + }*/ + } + + private static Preferences getDefaultPreferences() { + final Preferences origPrefs = NbPreferences.root().node("org/netbeans/modules/debugger/jpda/ui").node("debugging"); + final Preferences preferences = NbPreferences.forModule(FilterImpl.class).node("debugging"); // NOI18N + return new AbstractPreferences(null, "debugging") { + + @Override + protected void putSpi(String key, String value) { + preferences.put(key, value); + } + + @Override + protected String getSpi(String key) { + String value = origPrefs.get(key, null); + if (value == null) { + value = preferences.get(key, null); + } + return value; + } + + @Override + protected void removeSpi(String key) {} + + @Override + protected void removeNodeSpi() throws BackingStoreException {} + + @Override + protected String[] keysSpi() throws BackingStoreException { + return preferences.keys(); + } + + @Override + protected String[] childrenNamesSpi() throws BackingStoreException { + return preferences.childrenNames(); + } + + @Override + protected AbstractPreferences childSpi(String name) { + return null; + } + + @Override + protected void syncSpi() throws BackingStoreException { + origPrefs.sync(); + preferences.sync(); + } + + @Override + protected void flushSpi() throws BackingStoreException { + preferences.flush(); + } + + @Override + public void addPreferenceChangeListener(PreferenceChangeListener pcl) { + preferences.addPreferenceChangeListener(pcl); + } + + @Override + public void removePreferenceChangeListener(PreferenceChangeListener pcl) { + preferences.removePreferenceChangeListener(pcl); + } + + }; } } @@ -375,7 +588,7 @@ // ************************************************************************** // Group of Items // ************************************************************************** - static class Group { + /*static class Group { List items = Collections.EMPTY_LIST; public void setItems(List items) { @@ -389,7 +602,7 @@ return items; } - } + }*/ // ************************************************************************** // Filter Actions Support @@ -397,10 +610,10 @@ private static final class SortAction extends AbstractAction implements Presenter.Popup { - private Item filterItem; + private DVFilter filterItem; /** Creates a new instance of SortByNameAction */ - SortAction (Item item) { + SortAction (DVFilter item) { this.filterItem = item; String displayName = item.getDisplayName(); int i = Mnemonics.findMnemonicAmpersand(displayName); @@ -421,12 +634,12 @@ Mnemonics.setLocalizedText(menuItem, filterItem.getDisplayName()); menuItem.setAction(this); menuItem.addHierarchyListener(new ParentChangeListener(menuItem)); - menuItem.setSelected(filterItem.isSelected); + menuItem.setSelected(filterItem.isSelected()); return menuItem; } public void actionPerformed(ActionEvent e) { - filterItem.setSelected(!filterItem.isSelected); + filterItem.setSelected(!filterItem.isSelected()); } private class ParentChangeListener implements HierarchyListener { @@ -483,7 +696,7 @@ Mnemonics.setLocalizedText(menu, NbBundle.getMessage(FiltersDescriptor.class, "LBL_FilterSubmenu")); JMenuItem menuItem; String filterName; - for (Item item : filtersDesc.filters) { + for (DVFilter item : filtersDesc.filters) { if (item.getGroup() != null) { continue; } diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/InfoPanel.form b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/InfoPanel.form copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/InfoPanel.form copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/InfoPanel.form diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/InfoPanel.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/InfoPanel.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/InfoPanel.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/InfoPanel.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/InfoPanel.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/InfoPanel.java @@ -40,7 +40,7 @@ * Portions Copyrighted 2008 Sun Microsystems, Inc. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import java.awt.BorderLayout; import java.awt.Color; @@ -71,12 +71,11 @@ import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.border.EmptyBorder; +import org.netbeans.api.debugger.Breakpoint; import org.netbeans.api.debugger.DebuggerManager; import org.netbeans.api.debugger.Session; -import org.netbeans.api.debugger.jpda.JPDABreakpoint; -import org.netbeans.api.debugger.jpda.JPDADebugger; -import org.netbeans.api.debugger.jpda.JPDAThread; -import org.netbeans.modules.debugger.jpda.ui.models.DebuggingNodeModel; +import org.netbeans.spi.debugger.ui.DebuggingView.DVSupport; +import org.netbeans.spi.debugger.ui.DebuggingView.DVThread; import org.openide.awt.DropDownButtonFactory; import org.openide.util.Exceptions; import org.openide.util.ImageUtilities; @@ -108,17 +107,17 @@ private JButton arrowButton; private JPopupMenu arrowMenu; - private Map threadToMenuItem = new WeakHashMap(); - private JPDAThread debuggerDeadlockThread; - private WeakReference stepBrkpDebuggerRef; - private DebuggingView debuggingView; + private Map threadToMenuItem = new WeakHashMap(); + private DVThread debuggerDeadlockThread; + private WeakReference stepBrkpDVSupportRef; + private DebuggingViewComponent debuggingView; /** Creates new form InfoPanel */ - public InfoPanel(TapPanel tapPanel, DebuggingView debuggingView) { + public InfoPanel(TapPanel tapPanel, DebuggingViewComponent debuggingView) { this.tapPanel = tapPanel; this.debuggingView = debuggingView; filterPanelColor = tapPanel.getBackground(); - hitsPanelColor = DebuggingView.hitsColor; + hitsPanelColor = DebuggingViewComponent.hitsColor; deadlockPanelColor = hitsPanelColor; stepBrkpColor = hitsPanelColor; tapPanelMinimumHeight = tapPanel.getMinimumHeight(); @@ -165,7 +164,7 @@ }); } - void removeBreakpointHit(final JPDAThread thread, final int newHitsCount) { + void removeBreakpointHit(final DVThread thread, final int newHitsCount) { SwingUtilities.invokeLater(new Runnable() { public void run() { JMenuItem item = threadToMenuItem.remove(thread); @@ -181,13 +180,13 @@ }); } - void addBreakpointHit(final JPDAThread thread, final int newHitsCount) { + void addBreakpointHit(final DVThread thread, final int newHitsCount) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (threadToMenuItem.get(thread) != null) { return; } - JMenuItem item = createMenuItem(thread); + JMenuItem item = createMenuItem(thread.getDVSupport(), thread); threadToMenuItem.put(thread, item); arrowMenu.add(item); setHitsText(newHitsCount); @@ -198,13 +197,13 @@ }); } - void setBreakpointHits(final List hits) { + void setBreakpointHits(final DVSupport dvs, final List hits) { SwingUtilities.invokeLater(new Runnable() { public void run() { arrowMenu.removeAll(); threadToMenuItem.clear(); - for (JPDAThread thread : hits) { - JMenuItem item = createMenuItem(thread); + for (DVThread thread : hits) { + JMenuItem item = createMenuItem(dvs, thread); threadToMenuItem.put(thread, item); arrowMenu.add(item); } @@ -218,13 +217,13 @@ }); } - public void recomputeMenuItems(final List hits) { + public void recomputeMenuItems(final DVSupport dvs, final List hits) { SwingUtilities.invokeLater(new Runnable() { public void run() { arrowMenu.removeAll(); threadToMenuItem.clear(); - for (JPDAThread thread : hits) { - JMenuItem item = createMenuItem(thread); + for (DVThread thread : hits) { + JMenuItem item = createMenuItem(dvs, thread); threadToMenuItem.put(thread, item); arrowMenu.add(item); } @@ -232,24 +231,9 @@ }); } - private JMenuItem createMenuItem(final JPDAThread thread) { - String displayName; - try { - displayName = DebuggingNodeModel.getDisplayName(thread, false); - Method method = thread.getClass().getMethod("getDebugger"); // [TODO] - JPDADebugger debugger = (JPDADebugger)method.invoke(thread); - method = debugger.getClass().getMethod("getSession"); - Session session = (Session) method.invoke(debugger); - Session currSession = DebuggerManager.getDebuggerManager().getCurrentSession(); - if (session != currSession) { - String str = NbBundle.getMessage(ThreadsHistoryAction.class, "CTL_Session", // [TODO] bundle - session.getName()); - displayName = displayName.charAt(0) + str + ", " + displayName.substring(1); - } - } catch (Exception e) { // [TODO] - displayName = thread.getName(); - } - Image image = Utilities.loadImage(DebuggingNodeModel.getIconBase(thread)); + private JMenuItem createMenuItem(final DVSupport dvs, final DVThread thread) { + String displayName = dvs.getDisplayName(thread); + Image image = dvs.getIcon(thread); Icon icon = image != null ? new ImageIcon(image) : null; JMenuItem item = new JMenuItem(displayName, icon); item.addActionListener(new ActionListener() { @@ -283,7 +267,7 @@ }); } - void setShowThreadLocks(final JPDAThread thread, final List lockerThreads) { + void setShowThreadLocks(final DVThread thread, final List lockerThreads) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (lockerThreads != null) { @@ -295,11 +279,11 @@ }); } - void setShowStepBrkp(final JPDADebugger debugger, final JPDAThread thread, final JPDABreakpoint breakpoint) { + void setShowStepBrkp(final DVSupport dvSupport, final DVThread thread, final Breakpoint breakpoint) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (breakpoint != null) { - showStepBrkpPanel(debugger, thread, breakpoint); + showStepBrkpPanel(dvSupport, thread, breakpoint); } else { hideStepBrkpPanel(); } @@ -376,18 +360,7 @@ hidePanel(DEADLOCKS_BY_DEBUGGER); } - private boolean isInStep(JPDAThread t) { - // TODO: Make JPDAThread.isInStep() - try { - java.lang.reflect.Method isInStepMethod = t.getClass().getMethod("isInStep", new Class[] {}); - return (Boolean) isInStepMethod.invoke(t, new Object[] {}); - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - return false; - } - } - - private void showDebuggerDeadlockPanel(JPDAThread thread, List lockerThreads) { + private void showDebuggerDeadlockPanel(DVThread thread, List lockerThreads) { //this.debuggerDeadlockThreads = lockerThreads; this.debuggerDeadlockThread = thread; String infoResource; @@ -395,7 +368,7 @@ String resumeTooltipResource; int numThreads = lockerThreads.size(); if (numThreads == 1) { - if (isInStep(thread)) { + if (thread.isInStep()) { infoResource = "InfoPanel.debuggerDeadlocksLabelThread.text"; // NOI18N resumeTooltipResource = "InfoPanel.resumeDebuggerDeadlockButtonThread.tooltip"; } else { @@ -407,7 +380,7 @@ resumeDebuggerDeadlockButton.setToolTipText(org.openide.util.NbBundle.getMessage(InfoPanel.class, resumeTooltipResource, lockerThreads.get(0).getName())); } else { - if (isInStep(thread)) { + if (thread.isInStep()) { infoResource = "InfoPanel.debuggerDeadlocksLabel.text"; // NOI18N resumeTooltipResource = "InfoPanel.resumeDebuggerDeadlockButton.tooltip"; // NOI18N } else { @@ -443,8 +416,8 @@ hidePanel(STEP_BRKP); } - private void showStepBrkpPanel(JPDADebugger debugger, JPDAThread thread, JPDABreakpoint breakpoint) { - this.stepBrkpDebuggerRef = new WeakReference(debugger); + private void showStepBrkpPanel(DVSupport dvSupport, DVThread thread, Breakpoint breakpoint) { + this.stepBrkpDVSupportRef = new WeakReference(dvSupport); String text = org.openide.util.NbBundle.getMessage(InfoPanel.class, "InfoPanel.stepBrkpLabel.text", thread.getName()); // NOI18N stepBrkpLabel.setText(text); stepBrkpLabel.setToolTipText(text); @@ -463,7 +436,7 @@ public void actionPerformed(ActionEvent e) { if (arrowMenu.getComponentCount() > 0) { Object item = arrowMenu.getComponent(0); - for (Map.Entry entry : threadToMenuItem.entrySet()) { + for (Map.Entry entry : threadToMenuItem.entrySet()) { if (entry.getValue() == item) { debuggingView.makeThreadCurrent(entry.getKey()); } // if @@ -536,7 +509,7 @@ return toggleButton; } - private void resumeThreadToFreeMonitor(JPDAThread thread) { + private void resumeThreadToFreeMonitor(DVThread thread) { // Do not have monitor breakpoints in the API. // Have to do that in the implementation module. try { @@ -732,11 +705,11 @@ }// //GEN-END:initComponents private void resumeDebuggerDeadlockButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resumeDebuggerDeadlockButtonActionPerformed - //final List threadsToResume = debuggerDeadlockThreads; - final JPDAThread blockedThread = debuggerDeadlockThread; + //final List threadsToResume = debuggerDeadlockThreads; + final DVThread blockedThread = debuggerDeadlockThread; RequestProcessor rp; try { - JPDADebugger debugger = (JPDADebugger) blockedThread.getClass().getMethod("getDebugger").invoke(blockedThread); + DVSupport debugger = blockedThread.getDVSupport(); rp = getRP(debugger); if (rp == null) { return ; @@ -747,29 +720,28 @@ } rp.post(new Runnable() { public void run() { - resumeThreadToFreeMonitor(blockedThread); + blockedThread.resumeBlockingThreads(); + //resumeThreadToFreeMonitor(blockedThread); } }); hideDebuggerDeadlockPanel(); }//GEN-LAST:event_resumeDebuggerDeadlockButtonActionPerformed - private static RequestProcessor getRP(JPDADebugger debugger) { + private static RequestProcessor getRP(DVSupport debugger) { RequestProcessor rp; - try { - Session s = (Session) debugger.getClass().getMethod("getSession").invoke(debugger); // NOI18N - rp = s.lookupFirst(null, RequestProcessor.class); - } catch (Exception e) { - Exceptions.printStackTrace(e); - return null; + Session s = debugger.getSession(); + rp = s.lookupFirst(null, RequestProcessor.class); + if (rp == null) { + rp = new RequestProcessor(InfoPanel.class); } return rp; } private void stepBrkpIgnoreButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stepBrkpIgnoreButtonActionPerformed - if (stepBrkpDebuggerRef != null) { - final JPDADebugger d = stepBrkpDebuggerRef.get(); - if (d != null) { - RequestProcessor rp = getRP(d); + if (stepBrkpDVSupportRef != null) { + final DVSupport ds = stepBrkpDVSupportRef.get(); + if (ds != null) { + RequestProcessor rp = getRP(ds); if (rp == null) { return ; } @@ -777,7 +749,7 @@ @Override public void run() { try { - d.getClass().getMethod("resume").invoke(d); // NOI18N + ds.resume(); } catch (Exception ex) { Exceptions.printStackTrace(ex); } diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/KeyboardPopupSwitcher.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/KeyboardPopupSwitcher.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/KeyboardPopupSwitcher.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/KeyboardPopupSwitcher.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/KeyboardPopupSwitcher.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/KeyboardPopupSwitcher.java @@ -42,7 +42,7 @@ * made subject to such option by the copyright holder. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import java.awt.AWTEvent; import java.awt.Component; diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/SwitcherTable.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/SwitcherTable.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/SwitcherTable.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/SwitcherTable.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/SwitcherTable.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/SwitcherTable.java @@ -42,7 +42,7 @@ * made subject to such option by the copyright holder. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import java.awt.Color; import java.awt.Component; diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/SwitcherTableItem.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/SwitcherTableItem.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/SwitcherTableItem.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/SwitcherTableItem.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/SwitcherTableItem.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/SwitcherTableItem.java @@ -42,7 +42,7 @@ * made subject to such option by the copyright holder. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import javax.swing.Icon; diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/SwitcherTableModel.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/SwitcherTableModel.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/SwitcherTableModel.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/SwitcherTableModel.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/SwitcherTableModel.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/SwitcherTableModel.java @@ -42,7 +42,7 @@ * made subject to such option by the copyright holder. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import javax.swing.event.TableModelEvent; import javax.swing.table.AbstractTableModel; diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/TapPanel.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/TapPanel.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/TapPanel.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/TapPanel.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/TapPanel.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/TapPanel.java @@ -42,7 +42,7 @@ * made subject to such option by the copyright holder. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import javax.swing.*; import java.awt.*; diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/ThreadsHistoryAction.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/ThreadsHistoryAction.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/ThreadsHistoryAction.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/ThreadsHistoryAction.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/ThreadsHistoryAction.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/ThreadsHistoryAction.java @@ -43,7 +43,7 @@ */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; import java.awt.Color; import java.awt.Component; @@ -65,10 +65,9 @@ import javax.swing.KeyStroke; import org.netbeans.api.debugger.DebuggerManager; import org.netbeans.api.debugger.Session; -import org.netbeans.api.debugger.jpda.DeadlockDetector.Deadlock; -import org.netbeans.api.debugger.jpda.JPDADebugger; -import org.netbeans.api.debugger.jpda.JPDAThread; -import org.netbeans.modules.debugger.jpda.ui.models.DebuggingNodeModel; +import org.netbeans.spi.debugger.ui.DebuggingView.DVSupport; +import org.netbeans.spi.debugger.ui.DebuggingView.DVThread; +import org.netbeans.spi.debugger.ui.DebuggingView.Deadlock; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle; import org.openide.util.Utilities; @@ -83,7 +82,7 @@ @Override public void actionPerformed(ActionEvent evt) { - List threads = getThreads(); + List threads = getThreads(); int threadsCount = threads.size(); if (threadsCount < 1) { Toolkit.getDefaultToolkit().beep(); @@ -127,43 +126,28 @@ } } - public static SwitcherTableItem[] createSwitcherItems(List threads) { + public static SwitcherTableItem[] createSwitcherItems(List threads) { ThreadsListener threadsListener = ThreadsListener.getDefault(); - JPDADebugger debugger = threadsListener.getDebugger(); - JPDAThread currentThread = debugger != null ? debugger.getCurrentThread() : null; + DVSupport debugger = threadsListener.getDVSupport(); + DVThread currentThread = debugger != null ? debugger.getCurrentThread() : null; // collect all deadlocked threads - Set deadlocks = debugger != null ? debugger.getThreadsCollector().getDeadlockDetector().getDeadlocks() + Set deadlocks = debugger != null ? debugger.getDeadlocks() : Collections.EMPTY_SET; if (deadlocks == null) { deadlocks = Collections.EMPTY_SET; } - Set deadlockedThreads = new HashSet(); + Set deadlockedThreads = new HashSet(); for (Deadlock deadlock : deadlocks) { deadlockedThreads.addAll(deadlock.getThreads()); } SwitcherTableItem[] items = new SwitcherTableItem[threads.size()]; int i = 0; - for (JPDAThread thread : threads) { - String name; - try { - name = DebuggingNodeModel.getDisplayName(thread, false); - Method method = thread.getClass().getMethod("getDebugger"); // [TODO] - JPDADebugger deb = (JPDADebugger)method.invoke(thread); - method = deb.getClass().getMethod("getSession"); - Session session = (Session) method.invoke(deb); - Session currSession = DebuggerManager.getDebuggerManager().getCurrentSession(); - if (session != currSession) { - String str = NbBundle.getMessage(ThreadsHistoryAction.class, "CTL_Session", - session.getName()); - name = name.charAt(0) + str + ", " + name.substring(1); - } - } catch (Exception e) { // [TODO] - name = thread.getName(); - } + for (DVThread thread : threads) { + String name = debugger.getDisplayName(thread); String htmlName = name; String description = ""; // tc.getToolTipText(); - Image image = ImageUtilities.loadImage(DebuggingNodeModel.getIconBase(thread)); + Image image = debugger.getIcon(thread);//ImageUtilities.loadImage(DebuggingNodeModel.getIconBase(thread)); Icon icon = null; if (image != null) { boolean isCurrent = thread == currentThread; @@ -186,9 +170,9 @@ private static class ActivatableElement implements SwitcherTableItem.Activatable { - JPDAThread thread; + DVThread thread; - private ActivatableElement(JPDAThread thread) { + private ActivatableElement(DVThread thread) { this.thread = thread; } @Override @@ -197,21 +181,21 @@ } } - public static List getThreads() { + public static List getThreads() { ThreadsListener threadsListener = ThreadsListener.getDefault(); if (threadsListener == null) { return Collections.emptyList(); } - List history = threadsListener.getCurrentThreadsHistory(); - List allThreads = threadsListener.getThreads(); - Set hitsSet = new HashSet(); - for (JPDAThread hit : threadsListener.getHits()) { + List history = threadsListener.getCurrentThreadsHistory(); + List allThreads = threadsListener.getThreads(); + Set hitsSet = new HashSet(); + for (DVThread hit : threadsListener.getHits()) { hitsSet.add(hit); } Set set = new HashSet(history); - List result = new LinkedList(); + List result = new LinkedList(); result.addAll(history); - for (JPDAThread thread : allThreads) { + for (DVThread thread : allThreads) { if (!set.contains(thread) && thread.isSuspended()) { result.add(thread); } @@ -220,7 +204,7 @@ int index = 1; int size = result.size(); for (int x = 1; x < size; x++) { - JPDAThread t = result.get(x); + DVThread t = result.get(x); if (hitsSet.contains(t)) { if (x > index) { result.remove(x); @@ -256,14 +240,14 @@ Color primaryColor = null; Color secondaryColor = null; if (isInDeadlock) { - primaryColor = DebuggingView.deadlockColor; + primaryColor = DebuggingViewComponent.deadlockColor; } else if (isCurrent) { - primaryColor = DebuggingView.greenBarColor; + primaryColor = DebuggingViewComponent.greenBarColor; } else if (isAtBreakpoint) { - primaryColor = DebuggingView.hitsBarColor; + primaryColor = DebuggingViewComponent.hitsBarColor; } if (isCurrent && isInDeadlock) { - secondaryColor = DebuggingView.greenBarColor; + secondaryColor = DebuggingViewComponent.greenBarColor; } Color originalColor = g.getColor(); @@ -272,12 +256,12 @@ g.drawImage(image, x + width, y, iconBase.getImageObserver()); if (primaryColor != null) { g.setColor(primaryColor); - g.fillRect(x, y, DebuggingView.BAR_WIDTH, height); + g.fillRect(x, y, DebuggingViewComponent.BAR_WIDTH, height); } if (secondaryColor != null) { g.setColor(secondaryColor); - int w = DebuggingView.BAR_WIDTH / 2 + 1; - g.fillRect(x + DebuggingView.BAR_WIDTH - w, y, w, height); + int w = DebuggingViewComponent.BAR_WIDTH / 2 + 1; + g.fillRect(x + DebuggingViewComponent.BAR_WIDTH - w, y, w, height); } g.setColor(originalColor); } diff --git a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/ThreadsListener.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/ThreadsListener.java copy from debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/ThreadsListener.java copy to spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/ThreadsListener.java --- a/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/debugging/ThreadsListener.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/debugging/ThreadsListener.java @@ -42,9 +42,8 @@ * made subject to such option by the copyright holder. */ -package org.netbeans.modules.debugger.jpda.ui.debugging; +package org.netbeans.modules.debugger.ui.views.debugging; -import java.beans.Customizer; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; @@ -55,15 +54,14 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import org.netbeans.api.debugger.Breakpoint; import org.netbeans.api.debugger.DebuggerEngine; import org.netbeans.api.debugger.DebuggerManager; import org.netbeans.api.debugger.DebuggerManagerAdapter; import org.netbeans.api.debugger.LazyDebuggerManagerListener; -import org.netbeans.api.debugger.jpda.DeadlockDetector; -import org.netbeans.api.debugger.jpda.JPDABreakpoint; -import org.netbeans.api.debugger.jpda.JPDADebugger; -import org.netbeans.api.debugger.jpda.JPDAThread; import org.netbeans.spi.debugger.DebuggerServiceRegistration; +import org.netbeans.spi.debugger.ui.DebuggingView.DVSupport; +import org.netbeans.spi.debugger.ui.DebuggingView.DVThread; import org.openide.util.Exceptions; @DebuggerServiceRegistration(types=LazyDebuggerManagerListener.class) @@ -73,11 +71,11 @@ private static PropertyChangeSupport pchs = new PropertyChangeSupport(ThreadsListener.class); private static final ThreadsPropertyChangeListener tpchl = new ThreadsPropertyChangeListener(); - final LinkedList currentThreadsHistory = new LinkedList(); + final LinkedList currentThreadsHistory = new LinkedList(); final BreakpointHits hits = new BreakpointHits(); - private Map debuggerToListener = new WeakHashMap(); - private JPDADebugger currentDebugger = null; - private DebuggingView debuggingView; + private Map debuggerToListener = new WeakHashMap(); + private DVSupport currentDebugger = null; + private DebuggingViewComponent debuggingView; /** * Constructor for the registry only. @@ -103,22 +101,22 @@ pchs.removePropertyChangeListener(listener); } - public void setDebuggingView(DebuggingView debuggingView) { + public void setDebuggingView(DVSupport dvs, DebuggingViewComponent debuggingView) { this.debuggingView = debuggingView; InfoPanel infoPanel = debuggingView.getInfoPanel(); - infoPanel.setBreakpointHits(getHits()); + infoPanel.setBreakpointHits(dvs, getHits()); } - public synchronized void changeDebugger(JPDADebugger deb) { + public synchronized void changeDebugger(DVSupport deb) { if (currentDebugger == deb) { return; } if (currentDebugger != null) { - currentDebugger.getThreadsCollector().removePropertyChangeListener(tpchl); + currentDebugger.removePropertyChangeListener(tpchl); } if (deb != null) { - deb.getThreadsCollector().addPropertyChangeListener(tpchl); - JPDAThread currThread = deb.getCurrentThread(); + deb.addPropertyChangeListener(tpchl); + DVThread currThread = deb.getCurrentThread(); if (currThread != null) { synchronized(currentThreadsHistory) { currentThreadsHistory.remove(currThread); @@ -141,15 +139,15 @@ InfoPanel infoPanel = debuggingView.getInfoPanel(); DebuggerListener listener = debuggerToListener.get(deb); if (listener != null) { - DeadlockDetector detector = deb.getThreadsCollector().getDeadlockDetector(); - detector.addPropertyChangeListener(this); - if (detector.getDeadlocks() != null) { + //DeadlockDetector detector = deb.getThreadsCollector().getDeadlockDetector(); + //detector.addPropertyChangeListener(this); + if (deb.getDeadlocks() != null) { infoPanel.setShowDeadlock(true); } infoPanel.setShowThreadLocks(listener.lockedThread, listener.lockerThreads); infoPanel.setShowStepBrkp(listener.debugger, listener.stepBrkpThread, listener.stepBrkpBreakpoint); } - infoPanel.recomputeMenuItems(getHits()); + infoPanel.recomputeMenuItems(deb, getHits()); } else { // Release reference to DebuggingView when there's no debugger. debuggingView = null; @@ -157,10 +155,10 @@ this.currentDebugger = deb; } - public synchronized List getCurrentThreadsHistory() { + public synchronized List getCurrentThreadsHistory() { synchronized(currentThreadsHistory) { - List result = new ArrayList(currentThreadsHistory.size()); - for (JPDAThread thread : currentThreadsHistory) { + List result = new ArrayList(currentThreadsHistory.size()); + for (DVThread thread : currentThreadsHistory) { if (thread.isSuspended()) { result.add(thread); } @@ -169,17 +167,17 @@ } } - public synchronized List getThreads() { - List result = new ArrayList(); - for (JPDADebugger debugger : debuggerToListener.keySet()) { - if (debugger != null && debugger.getState() != JPDADebugger.STATE_DISCONNECTED) { - result.addAll(debugger.getThreadsCollector().getAllThreads()); + public synchronized List getThreads() { + List result = new ArrayList(); + for (DVSupport debugger : debuggerToListener.keySet()) { + if (debugger != null && debugger.getState() != DVSupport.STATE.DISCONNECTED) { + result.addAll(debugger.getAllThreads()); } } return result; } - private void addBreakpointHit(JPDAThread thread) { + private void addBreakpointHit(DVThread thread) { if (thread != null && !hits.contains(thread)) { // System.out.println("Hit added: " + thread.getName()); hits.add(thread); @@ -189,7 +187,7 @@ } } - private void removeBreakpointHit(JPDAThread thread) { + private void removeBreakpointHit(DVThread thread) { if (thread != null && hits.contains(thread)) { // System.out.println("Hit removed: " + thread.getName()); hits.remove(thread); @@ -199,9 +197,9 @@ } } - public synchronized List getHits() { - List result = new ArrayList(); - for (JPDAThread thread : hits.getStoppedThreads()) { + public synchronized List getHits() { + List result = new ArrayList(); + for (DVThread thread : hits.getStoppedThreads()) { result.add(thread); } return result; @@ -211,7 +209,7 @@ return hits.size(); } - public synchronized boolean isBreakpointHit(JPDAThread thread) { + public synchronized boolean isBreakpointHit(DVThread thread) { return hits.contains(thread); } @@ -219,7 +217,7 @@ hits.goToHit(); } - public JPDADebugger getDebugger() { + public DVSupport getDVSupport() { return currentDebugger; } @@ -230,7 +228,7 @@ @Override public synchronized void engineAdded(DebuggerEngine engine) { - JPDADebugger deb = engine.lookupFirst(null, JPDADebugger.class); + DVSupport deb = engine.lookupFirst(null, DVSupport.class); if (deb != null) { DebuggerListener listener = new DebuggerListener(deb); debuggerToListener.put(deb, listener); @@ -242,7 +240,7 @@ @Override public synchronized void engineRemoved(DebuggerEngine engine) { - JPDADebugger deb = engine.lookupFirst(null, JPDADebugger.class); + DVSupport deb = engine.lookupFirst(null, DVSupport.class); if (deb != null) { DebuggerListener listener = debuggerToListener.remove(deb); if (listener != null) { @@ -260,23 +258,23 @@ class DebuggerListener implements PropertyChangeListener { - private JPDADebugger debugger; - Set threads = new HashSet(); - List lockerThreads; - JPDAThread lockedThread; - JPDAThread stepBrkpThread; - JPDABreakpoint stepBrkpBreakpoint; + private DVSupport debugger; + Set threads = new HashSet(); + List lockerThreads; + DVThread lockedThread; + DVThread stepBrkpThread; + Breakpoint stepBrkpBreakpoint; - DebuggerListener(JPDADebugger debugger) { + DebuggerListener(DVSupport debugger) { this.debugger = debugger; debugger.addPropertyChangeListener(this); - List allThreads = debugger.getThreadsCollector().getAllThreads(); - for (JPDAThread thread : allThreads) { + List allThreads = debugger.getAllThreads(); + for (DVThread thread : allThreads) { threads.add(thread); - ((Customizer)thread).addPropertyChangeListener(this); + thread.addPropertyChangeListener(this); } - DeadlockDetector detector = debugger.getThreadsCollector().getDeadlockDetector(); - detector.addPropertyChangeListener(this); + //DeadlockDetector detector = debugger.getThreadsCollector().getDeadlockDetector(); + //detector.addPropertyChangeListener(this); } public synchronized void propertyChange(PropertyChangeEvent evt) { @@ -284,38 +282,40 @@ String propName = evt.getPropertyName(); Object source = evt.getSource(); - if (source instanceof JPDADebugger) { - if (JPDADebugger.PROP_THREAD_STARTED.equals(propName)) { + if (source instanceof DVSupport) { + if (DVSupport.PROP_THREAD_STARTED.equals(propName)) { //System.out.println("STARTED: " + evt.getNewValue()); - final JPDAThread jpdaThread = (JPDAThread)evt.getNewValue(); + final DVThread jpdaThread = (DVThread)evt.getNewValue(); if (threads.add(jpdaThread)) { - ((Customizer)jpdaThread).addPropertyChangeListener(this); + jpdaThread.addPropertyChangeListener(this); // System.out.println("WATCHED: " + jpdaThread.getName()); } - } else if (JPDADebugger.PROP_THREAD_DIED.equals(propName)) { + } else if (DVSupport.PROP_THREAD_DIED.equals(propName)) { //System.out.println("DIED: " + evt.getOldValue()); - JPDAThread jpdaThread = (JPDAThread)evt.getOldValue(); + DVThread jpdaThread = (DVThread)evt.getOldValue(); if (threads.remove(jpdaThread)) { synchronized(currentThreadsHistory) { currentThreadsHistory.remove(jpdaThread); } - ((Customizer)jpdaThread).removePropertyChangeListener(this); + jpdaThread.removePropertyChangeListener(this); // System.out.println("RELEASED: " + jpdaThread.getName()); } - } else if (JPDADebugger.PROP_CURRENT_THREAD.equals(propName)) { - JPDAThread currentThread = debugger.getCurrentThread(); + } else if (DVSupport.PROP_CURRENT_THREAD.equals(propName)) { + DVThread currentThread = debugger.getCurrentThread(); removeBreakpointHit(currentThread); synchronized(currentThreadsHistory) { currentThreadsHistory.remove(currentThread); currentThreadsHistory.addFirst(currentThread); } - } else if (JPDADebugger.PROP_STATE.equals(propName) && - debugger != null && debugger.getState() == JPDADebugger.STATE_DISCONNECTED) { + } else if (DVSupport.PROP_STATE.equals(propName) && + debugger != null && debugger.getState() == DVSupport.STATE.DISCONNECTED) { unregister(); + } else if (DVSupport.PROP_DEADLOCK.equals(propName)) { + setShowDeadlock(true); } - } else if (source instanceof JPDAThread) { - final JPDAThread thread = (JPDAThread)source; - if (JPDAThread.PROP_BREAKPOINT.equals(propName)) { + } else if (source instanceof DVThread) { + final DVThread thread = (DVThread)source; + if (DVThread.PROP_BREAKPOINT.equals(propName)) { // System.out.println("THREAD: " + thread.getName() + ", curr: " + isCurrent(thread) + ", brk: " + isAtBreakpoint(thread)); if (!isCurrent(thread)) { if (isAtBreakpoint(thread)) { @@ -329,46 +329,43 @@ if (debugger == currentDebugger && debuggingView != null) { debuggingView.refreshView(); // [TODO] } - } else if (JPDAThread.PROP_SUSPENDED.equals(propName)) { + } else if (DVThread.PROP_SUSPENDED.equals(propName)) { if (!thread.isSuspended()) { removeBreakpointHit(thread); } if (debugger == currentDebugger && debuggingView != null) { debuggingView.refreshView(); // [TODO] } - } else if ("lockerThreads".equals(propName)) { // NOI18N - // Calling List getLockerThreads() - List currLockerThreads; + } else if (DVThread.PROP_LOCKER_THREADS.equals(propName)) { // NOI18N + // Calling List getLockerThreads() + List currLockerThreads = thread.getLockerThreads(); + /*List currLockerThreads; try { java.lang.reflect.Method lockerThreadsMethod = thread.getClass().getMethod("getLockerThreads", new Class[] {}); // NOI18N - currLockerThreads = (List) lockerThreadsMethod.invoke(thread, new Object[] {}); + currLockerThreads = (List) lockerThreadsMethod.invoke(thread, new Object[] {}); } catch (Exception ex) { Exceptions.printStackTrace(ex); currLockerThreads = null; - } + }*/ setShowThreadLocks(thread, currLockerThreads); } else if ("stepSuspendedByBreakpoint".equals(propName)) { - setShowStepBrkp(thread, (JPDABreakpoint) evt.getNewValue()); - } - } else if (source instanceof DeadlockDetector) { - if (DeadlockDetector.PROP_DEADLOCK.equals(propName)) { - setShowDeadlock(true); + setShowStepBrkp(thread, (Breakpoint) evt.getNewValue()); } } } private synchronized void unregister() { if (debugger == null) return ; - for (JPDAThread thread : threads) { - ((Customizer) thread).removePropertyChangeListener(this); + for (DVThread thread : threads) { + thread.removePropertyChangeListener(this); } synchronized(currentThreadsHistory) { - for (JPDAThread thread : threads) { + for (DVThread thread : threads) { currentThreadsHistory.remove(thread); } } synchronized(hits) { - for (JPDAThread thread : threads) { + for (DVThread thread : threads) { removeBreakpointHit(thread); } } @@ -378,17 +375,17 @@ stepBrkpThread = null; stepBrkpBreakpoint = null; debugger.removePropertyChangeListener(this); - debugger.getThreadsCollector().getDeadlockDetector().removePropertyChangeListener(this); + debugger./*getThreadsCollector().getDeadlockDetector().*/removePropertyChangeListener(this); debugger = null; } - private boolean isCurrent(JPDAThread thread) { + private boolean isCurrent(DVThread thread) { return debugger.getCurrentThread() == thread; } - private boolean isAtBreakpoint(JPDAThread thread) { - JPDABreakpoint breakpoint = thread.getCurrentBreakpoint(); - return breakpoint != null && !breakpoint.isHidden(); + private boolean isAtBreakpoint(DVThread thread) { + Breakpoint breakpoint = thread.getCurrentBreakpoint(); + return breakpoint != null;// && !breakpoint.isHidden(); } private void setShowDeadlock(boolean detected) { @@ -397,7 +394,7 @@ } } - private void setShowThreadLocks(JPDAThread thread, List currLockerThreads) { + private void setShowThreadLocks(DVThread thread, List currLockerThreads) { lockerThreads = currLockerThreads; lockedThread = thread; if (debugger == currentDebugger && debuggingView != null) { @@ -405,7 +402,7 @@ } } - private void setShowStepBrkp(JPDAThread thread, JPDABreakpoint breakpoint) { + private void setShowStepBrkp(DVThread thread, Breakpoint breakpoint) { stepBrkpThread = thread; stepBrkpBreakpoint = breakpoint; if (debugger == currentDebugger && debuggingView != null) { @@ -416,22 +413,22 @@ } static class BreakpointHits { - private Set stoppedThreadsSet = new HashSet(); - private LinkedList stoppedThreads = new LinkedList(); + private Set stoppedThreadsSet = new HashSet(); + private LinkedList stoppedThreads = new LinkedList(); public void goToHit() { - JPDAThread thread; + DVThread thread; synchronized (this) { thread = stoppedThreads.getLast(); } thread.makeCurrent(); } - public synchronized boolean contains(JPDAThread thread) { + public synchronized boolean contains(DVThread thread) { return stoppedThreadsSet.contains(thread); } - public synchronized boolean add(JPDAThread thread) { + public synchronized boolean add(DVThread thread) { if (stoppedThreadsSet.add(thread)) { stoppedThreads.addFirst(thread); return true; @@ -439,7 +436,7 @@ return false; } - public synchronized boolean remove(JPDAThread thread) { + public synchronized boolean remove(DVThread thread) { if (stoppedThreadsSet.remove(thread)) { stoppedThreads.remove(thread); return true; @@ -456,8 +453,8 @@ return stoppedThreads.size(); } - private synchronized Iterable getStoppedThreads() { - return new ArrayList(stoppedThreads); + private synchronized Iterable getStoppedThreads() { + return new ArrayList(stoppedThreads); } } diff --git a/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/DebuggingView.java b/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/DebuggingView.java new file mode 100644 --- /dev/null +++ b/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/DebuggingView.java @@ -0,0 +1,626 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 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 2013 Sun Microsystems, Inc. + */ + +package org.netbeans.spi.debugger.ui; + +import java.awt.Image; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.prefs.Preferences; +import javax.swing.Action; +import javax.swing.Icon; +import org.netbeans.api.debugger.Breakpoint; +import org.netbeans.api.debugger.Session; +import org.netbeans.modules.debugger.ui.views.debugging.DebuggingViewComponent; +import org.netbeans.modules.debugger.ui.views.debugging.FiltersDescriptor; +import org.netbeans.modules.debugger.ui.views.debugging.FiltersDescriptor.FilterImpl; +import org.netbeans.modules.debugger.ui.views.debugging.FiltersDescriptor.FiltersAccessor; +import org.openide.windows.TopComponent; + +/** + * Debugging view component provider. The debugging view displays application threads. + * Implement {@link DVSupport} and register under your session name to use + * debugging view UI and register appropriate view models for path <session name>/DebuggingView. + * + * @author Martin Entlicher + * @since 2.42 + */ +public final class DebuggingView { + + private final static DebuggingView INSTANCE = new DebuggingView(); + + private Reference dvcRef = new WeakReference(null); + + private DebuggingView() { + //this.dvc = DebuggingViewComponent.getInstance(); + } + + /** + * Get the default implementation of debugging view provider. + * @return the default instance of debugging view provider. + */ + public static DebuggingView getDefault() { + return INSTANCE; + } + + private DebuggingViewComponent getDVC() { + DebuggingViewComponent dvc; + synchronized (this) { + dvc = dvcRef.get(); + if (dvc == null) { + dvc = DebuggingViewComponent.getInstance(); + dvcRef = new WeakReference(dvc); + } + } + return dvc; + } + + /** + * Get the debugging view top component. + * @return the {@link TopComponent} of the debugging view. + */ + public TopComponent getViewTC() { + return getDVC(); + } + + /** + * Support for debugging view. The component tree is created from view models + * registered under path <session name>/DebuggingView. But to fully + * support the debugging view UI, additional information is necessary. + * Implement this class to provide the additional information. + * Debugging view is created for the given debugger session only when an + * implementation of this class is found in the current session engine lookup. + */ + public static abstract class DVSupport { + + /** Property name constant. */ + public static final String PROP_THREAD_STARTED = "threadStarted"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_DIED = "threadDied"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_GROUP_ADDED = "threadGroupAdded"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_SUSPENDED = "threadSuspended"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_RESUMED = "threadResumed"; // NOI18N + /** Property name constant. */ + public static final String PROP_CURRENT_THREAD = "currentThread"; // NOI18N + + /** + * Name of property which is fired when deadlock occurs. + */ + public static final String PROP_DEADLOCK = "deadlock"; // NOI18N + public static final String PROP_STATE = "state"; // NOI18N + + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + /** + * The debugger state. + */ + public static enum STATE { + RUNNING, + DISCONNECTED + } + + static { + FiltersDescriptor.getInstance().setFiltersAccessor(new FiltersAccessor() { + @Override + public List getFilters(DVSupport dvs) { + return dvs.getFilters(); + } + @Override + public FilterImpl getImpl(DVFilter filter) { + return filter.getImpl(); + } + }); + } + + protected DVSupport() { + } + + /** + * Get the debugger state. + * @return current state of debugger + */ + public abstract STATE getState(); + + /** + * Get listing of all threads at this moment. + * @return list of all threads + */ + public abstract List getAllThreads(); + + /** + * Get a current thread, if any. + * @return a current thread, or null. + */ + public abstract DVThread getCurrentThread(); + + /** + * Get the display name of the thread. It can contain more information + * than a thread name, like current session name, etc. + * @param thread the thread + * @return the thread display name + */ + public abstract String getDisplayName(DVThread thread); + + /** + * Get the thread icon. + * @param thread the thread + * @return the thread icon + */ + public abstract Image getIcon(DVThread thread); + + /** + * Get the session associated with this debugging view. + * @return + */ + public abstract Session getSession(); + + /** + * Resume the application (all it's threads). + */ + public abstract void resume(); + + /** + * Get the set of detected deadlocks, if any. + * @return The set of deadlocks, or null when no deadlocks are detected. + */ + public abstract Set getDeadlocks(); + + /** + * Utility method used by the implementing class to create deadlock description instances. + * @param threads The threads in deadlock + * @return Deadlock instance + */ + protected final Deadlock createDeadlock(Collection threads) { + return new Deadlock(threads); + } + + /** + * Get the list of filters applied to debugging view. + * @return list of filters + */ + protected abstract List getFilters(); + + /** + * Get actions created from the provided filters. + * The result can be added to actions provider view model. + * @return filter actions. + */ + public final Action[] getFilterActions() { + return FiltersDescriptor.getInstance().getFilterActions(); + } + + protected final void firePropertyChange(PropertyChangeEvent pce) { + pcs.firePropertyChange(pce); + } + + /** + * Fire a property change event. + * @param propertyName the property name + * @param oldValue old value + * @param newValue new value + */ + protected final void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * Add a property change listener. + * @param pcl the property change listener + */ + public final void addPropertyChangeListener(PropertyChangeListener pcl) { + pcs.addPropertyChangeListener(pcl); + } + + /** + * Remove a property change listener. + * @param pcl the property change listener + */ + public final void removePropertyChangeListener(PropertyChangeListener pcl) { + pcs.removePropertyChangeListener(pcl); + } + + /** + * Declarative registration of a DVSupport implementation. + * By marking the implementation class with this annotation, + * you automatically register that implementation for use by the debugging view. + * The class must be public and have a public constructor which takes + * no arguments or takes {@link ContextProvider} as an argument. + * + * @author Martin Entlicher + */ + @Retention(RetentionPolicy.SOURCE) + @Target({ElementType.TYPE}) + public @interface Registration { + /** + * The path to register this implementation in. + * Usually the session ID. + */ + String path(); + + /** + * An optional position in which to register this service relative to others. + * Lower-numbered services are returned in the lookup result first. + * Services with no specified position are returned last. + */ + int position() default Integer.MAX_VALUE; + + } + + } + + /** + * Representation of a thread in debugging view. + * Nodes representing a thread in debugging view model should implement this + * interface. + */ + public static interface DVThread { + + /** + * Property name fired when a thread gets suspended. + */ + public static final String PROP_SUSPENDED = "suspended"; // NOI18N + /** + * Property name fired when list of locker threads change. + */ + public static final String PROP_LOCKER_THREADS = "lockerThreads"; // NOI18N + /** + * Property name fired when current breakpoint is changed. + */ + public static final String PROP_BREAKPOINT = "currentBreakpoint"; // NOI18N + + /** + * Get the name of the thread. + * @return the name of the thread + */ + public String getName(); + + /** + * Test if this thread is currently suspended by debugger. + * @return true when the thread is suspended, false otherwise. + */ + public boolean isSuspended(); + + /** + * Resume this thread. + */ + public void resume(); + + /** + * Suspend this thread. + */ + public void suspend(); + + /** + * Make this thread current. Code evaluation and stepping should be performed + * in the current thread. + */ + public void makeCurrent(); + + /** + * Get the debugging view support that provides this thread. + * @return the debugging view support + */ + public DVSupport getDVSupport(); + + /** + * Lists threads that hold monitors that this thread is waiting on. + * @return list of locker threads + */ + public List getLockerThreads(); + + /** + * Resume any suspended threads that block execution of this thread by holding monitors. + */ + public void resumeBlockingThreads(); + + /** + * Get current breakpoint, if any. This is a breakpoint that this thread is suspended on. + * @return the current breakpoint or null + */ + public Breakpoint getCurrentBreakpoint(); + + /** + * Test if this thread is performing a step operation right now. + * @return true if this thread is in a step, false otherwise. + */ + public boolean isInStep(); + + /** + * Add a property change listener. + * @param pcl the property change listener + */ + public void addPropertyChangeListener(PropertyChangeListener pcl); + + /** + * Remove a property change listener. + * @param pcl the property change listener + */ + public void removePropertyChangeListener(PropertyChangeListener pcl); + + } + + /** + * Representation of a thread group in debugging view. + * Nodes representing a thread group in debugging view model should implement + * this interface. + */ + public static interface DVThreadGroup { + + /** + * Get the name of the thread group. + * @return the name of the thread group + */ + public String getName(); + + /** + * Get the parent thread group, if exists. + * @return the parent thread group or null if this thread group has no parent (root thread group). + */ + public DVThreadGroup getParentThreadGroup(); + + /** + * Get this thread group's threads. + * @return threads from this thread group + */ + public DVThread[] getThreads(); + + /** + * Get this thread group's thread groups. + * @return thread groups from this thread group + */ + public DVThreadGroup[] getThreadGroups(); + } + + /** + * Representation of a deadlock - one set of mutually deadlocked threads. + */ + public static final class Deadlock { + + private final Collection threads; + + private Deadlock(Collection threads) { + this.threads = threads; + } + + /** + * Get the threads in deadlock. + * @return The threads in deadlock. + */ + public Collection getThreads() { + return threads; + } + } + + /** + * Boolean state filter that is applied to the debugging view. + * It's icon is made visible in the debugging view bottom panel. + */ + public static final class DVFilter { + + /** + * Pre-defined default filters enumeration. + */ + public static enum DefaultFilter { + sortAlphabetic, + sortSuspend, + sortNatural, + showQualifiedNames, + showMonitors, + showSystemThreads, + showSuspendTable, + showThreadGroups, + showSuspendedThreadsOnly, + } + + private static final Group sortGroup = new Group(); + + /** + * Get an instance of a default filter. + * @param filter the default filter kind + * @return filter implementation + */ + public static DVFilter getDefault(DefaultFilter filter) { + FilterImpl fimpl = FilterImpl.createDefault(filter); + Group g; + switch (filter) { + case sortAlphabetic: + case sortNatural: + case sortSuspend: + g = sortGroup; + break; + default: + g = null; + } + fimpl.setGroup(g); + return new DVFilter(fimpl, g); + } + + /** + * Create a custom filter. + * @param name name of the filter + * @param displayName display name of the filter (visible in an action menu) + * @param tooltip tool-tip of the filter + * @param selectedIcon icon of the filter + * @param valuePrefs preferences which are asked for the filter value + * @param valuePrefKey key that is used to retrieve the filter value from preferences + * @param isSelectedDefault whether the filter should be selected by default when preferences do not contain the value + * @param group a filter group, can be null + * @return implementation of the filter + */ + public static DVFilter create(String name, String displayName, + String tooltip, Icon selectedIcon, + Preferences valuePrefs, String valuePrefKey, + boolean isSelectedDefault, Group group) { + FilterImpl fimpl = new FilterImpl(name, displayName, tooltip, selectedIcon, + valuePrefs, valuePrefKey, isSelectedDefault); + fimpl.setGroup(group); + return new DVFilter(fimpl, group); + } + + private final FilterImpl fimpl; + private final Group group; + + DVFilter (FilterImpl fimpl, Group group) { + this.fimpl = fimpl; + this.group = group; + group.add(this); + } + + private FilterImpl getImpl() { + return fimpl; + } + + /** + * Get the filter group. + * @return the filter group, or null when the filter has no group + */ + public Group getGroup() { + return group; + } + + /** + * Get the filter name. + * @return the filter name + */ + public String getName() { + return fimpl.getName(); + } + + /** + * Get the filter display name. + * @return the filter display name + */ + public String getDisplayName() { + return fimpl.getDisplayName(); + } + + /** + * Get the filter tooltip. + * @return the filter tooltip + */ + public String getTooltip() { + return fimpl.getTooltip(); + } + + /** + * Get the filter icon. + * @return the filter icon + */ + public Icon getIcon() { + return fimpl.getIcon(); + } + + /** + * Test if the filter is selected. + * @return whether the filter is selected right now + */ + public boolean isSelected() { + return fimpl.isSelected(); + } + + /** + * Set the filter as selected/unselected. + * @param state whether to select the filter + */ + public void setSelected(boolean state) { + fimpl.setSelected(state); + } + + /** + * Get the filter preferences. + * @return the preferences of this filter + */ + public Preferences getPreferences() { + return fimpl.getPreferences(); + } + + /** + * Get the preference key. + * @return key that is used to retrieve the filter value from preferences + */ + public String getPrefKey() { + return fimpl.getPrefKey(); + } + + /** + * The filter group. + */ + public static final class Group { + + private final List items = new LinkedList(); + + /** + * Create a new empty group. + */ + public Group() { + } + + void add(DVFilter filter) { + items.add(filter); + } + + /** + * Get list of filters in this group. + * @return list of filters + */ + public List getItems() { + return items; + } + } + + } + +}