|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.debugger.jpda.models; import com.sun.jdi.AbsentInformationException; import com.sun.jdi.ArrayReference; import com.sun.jdi.ArrayType; import com.sun.jdi.ClassLoaderReference; import com.sun.jdi.ClassNotLoadedException; import com.sun.jdi.ClassType; import com.sun.jdi.Field; import com.sun.jdi.IncompatibleThreadStateException; import com.sun.jdi.InvalidStackFrameException; import com.sun.jdi.LocalVariable; import com.sun.jdi.NativeMethodException; import com.sun.jdi.ObjectCollectedException; import com.sun.jdi.ObjectReference; import com.sun.jdi.PrimitiveType; import com.sun.jdi.PrimitiveValue; import com.sun.jdi.ReferenceType; import com.sun.jdi.StackFrame; import com.sun.jdi.ThreadReference; import com.sun.jdi.VMDisconnectedException; import com.sun.jdi.Value; import com.sun.jdi.VirtualMachine; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.Vector; import java.util.WeakHashMap; import org.netbeans.api.debugger.DebuggerEngine; import org.netbeans.spi.debugger.ContextProvider; import org.netbeans.api.debugger.jpda.JPDADebugger; import org.netbeans.api.debugger.jpda.Variable; import org.netbeans.spi.viewmodel.NoInformationException; import org.netbeans.spi.viewmodel.TreeModel; import org.netbeans.spi.viewmodel.TreeModelListener; import org.netbeans.spi.viewmodel.UnknownTypeException; import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl; import org.openide.util.RequestProcessor; /** * @author Jan Jancura */ public class ClassesTreeModel implements TreeModel { private static boolean verbose = (System.getProperty ("netbeans.debugger.viewrefresh") != null) && (System.getProperty ("netbeans.debugger.viewrefresh").indexOf ('s') >= 0); private JPDADebuggerImpl debugger; private Listener listener; private Vector listeners = new Vector (); public ClassesTreeModel(ContextProvider lookupProvider) { debugger = (JPDADebuggerImpl) lookupProvider. lookupFirst (null, JPDADebugger.class); } public Object getRoot () { return ROOT; } public Object[] getChildren (Object o, int from, int to) throws NoInformationException, UnknownTypeException { try { Object[] r = null; if (o.equals (ROOT)) { r = getLoaders (); } else if (o instanceof Object[]) { r = getChildren ((Object[]) o); } else if (o instanceof ClassLoaderReference) { r = getPackages ((ClassLoaderReference) o); } else if (o == NULL_CLASS_LOADER) { r = getPackages (null); } else if (o instanceof ReferenceType) { r = ((ReferenceType) o).nestedTypes ().toArray (); } else throw new UnknownTypeException (o); Object[] rr = new Object [to - from]; System.arraycopy (r, from, rr, 0, to - from); return rr; } catch (VMDisconnectedException ex) { return new Object [0]; } } /** * Returns number of children for given node. * * @param node the parent node * @throws UnknownTypeException if this TreeModel implementation is not * able to resolve children for given node type * * @return true if node is leaf */ public int getChildrenCount (Object node) throws NoInformationException, UnknownTypeException { try { if (node.equals (ROOT)) return getLoaders ().length; if (node instanceof Object[]) return getChildren ((Object[]) node).length; if (node instanceof ClassLoaderReference) return getPackages ((ClassLoaderReference) node).length; if (node == NULL_CLASS_LOADER) return getPackages (null).length; if (node instanceof ReferenceType) { return ((ReferenceType) node).nestedTypes ().size (); } throw new UnknownTypeException (node); } catch (VMDisconnectedException ex) { return 0; } } public boolean isLeaf (Object o) throws UnknownTypeException { if (o.equals (ROOT)) return false; if (o instanceof Object[]) return false; if (o instanceof ReferenceType) return false; if (o instanceof ClassLoaderReference) return false; if (o == NULL_CLASS_LOADER) return false; throw new UnknownTypeException (o); } public void addTreeModelListener (TreeModelListener l) { listeners.add (l); if (listener == null) listener = new Listener (this, debugger); } public void removeTreeModelListener (TreeModelListener l) { listeners.remove (l); if (listeners.size () == 0) { listener.destroy (); listener = null; } } public void fireTreeChanged () { classes = null; names = null; cache = new HashMap (); Vector v = (Vector) listeners.clone (); int i, k = v.size (); for (i = 0; i < k; i++) ((TreeModelListener) v.get (i)).treeChanged (); } // private methods ......................................................... private List classes = null; // name of class -> ReferenceType private List names = null; // list on names of all clases private HashMap cache = new HashMap (); // null => list of class loaders // ClassLoaderReference -> list of packages & ReferenceTypes // package name -> list of packages & ReferenceTypes private Comparator comparator = new PackageComarator (); private Comparator comparator1 = new ClassLoaderComarator (); static final Integer NULL_CLASS_LOADER = new Integer (11); private List getNames () { if (classes == null) { VirtualMachine vm = debugger.getVirtualMachine (); List referenceTypes = new ArrayList (); if (vm != null) referenceTypes = vm.allClasses (); int i, k = referenceTypes.size (); names = new ArrayList (); classes = new ArrayList (); for (i = 0; i < k; i++) { ReferenceType rt = (ReferenceType) referenceTypes.get (i); if (rt instanceof ArrayType) continue; names.add (rt.name ()); classes.add (rt); } } return names; } private Object[] getLoaders () { Object[] ch = (Object[]) cache.get (null); if (ch != null) return ch; List names = getNames (); Set loaders = new TreeSet (comparator1); int i, k = names.size (); for (i = 0; i < k; i++) { try { String name = (String) names.get (i); ReferenceType rt = (ReferenceType) classes.get (i); ClassLoaderReference clr = rt.classLoader (); if (clr == null) loaders.add (NULL_CLASS_LOADER); else if (clr.referenceType ().name ().equals ("sun.reflect.DelegatingClassLoader")) continue; else loaders.add (clr); } catch (ObjectCollectedException ex) { } } ch = loaders.toArray (); cache.put (null, ch); return ch; } private Object[] getPackages (ClassLoaderReference clr) { Object[] ch = clr == null ? (Object[]) cache.get (NULL_CLASS_LOADER) : (Object[]) cache.get (clr); if (ch != null) return ch; List names = getNames (); Set objects = new TreeSet (comparator); int i, k = names.size (); for (i = 0; i < k; i++) { String name = (String) names.get (i); ReferenceType rt = (ReferenceType) classes.get (i); if (rt.classLoader () != clr) continue; int start = 0; int end = name.indexOf ('.', start); if (end < 0) { // ReferenceType found if (name.indexOf ('$', start) < 0) { ReferenceType tr = (ReferenceType) classes.get (i); objects.add (tr); } } else objects.add (new Object[] {name.substring (0, end), clr}); } ch = objects.toArray (); if (clr == null) cache.put (NULL_CLASS_LOADER, ch); else cache.put (clr, ch); return ch; } private Object[] getChildren (Object[] parent) { Object[] ch = (Object[]) cache.get (parent); if (ch != null) return ch; List names = getNames (); Set objects = new TreeSet (comparator); int i, k = names.size (); for (i = 0; i < k; i++) { String name = (String) names.get (i); ReferenceType rt = (ReferenceType) classes.get (i); if (rt.classLoader () != parent [1]) continue; String parentN = ((String) parent [0]) + '.'; if (!name.startsWith (parentN)) continue; int start = (parentN).length (); int end = name.indexOf ('.', start); if (end < 0) { // ReferenceType found if (name.indexOf ('$', start) < 0) { objects.add (rt); } } else objects.add (new Object[] {name.substring (0, end), rt.classLoader ()}); } ch = objects.toArray (); cache.put (parent, ch); return ch; } JPDADebuggerImpl getDebugger () { return debugger; } private static String shortName (String name) { int i = name.lastIndexOf ('.'); if (i < 0) return name; return name.substring (i + 1); } // innerclasses ............................................................ private static class Listener implements PropertyChangeListener { private JPDADebugger debugger; private WeakReference model; private Listener ( ClassesTreeModel tm, JPDADebugger debugger ) { this.debugger = debugger; model = new WeakReference (tm); debugger.addPropertyChangeListener (this); } void destroy () { debugger.removePropertyChangeListener (this); if (task != null) { // cancel old task task.cancel (); if (verbose) System.out.println ("ClTM cancel old task " + task); task = null; } } private ClassesTreeModel getModel () { ClassesTreeModel tm = (ClassesTreeModel) model.get (); if (tm == null) { destroy (); } return tm; } // currently waiting / running refresh task // there is at most one private RequestProcessor.Task task; public void propertyChange (PropertyChangeEvent e) { if ( ( (e.getPropertyName () == debugger.PROP_CURRENT_CALL_STACK_FRAME) || //(e.getPropertyName () == debugger.PROP_CURRENT_THREAD) || (e.getPropertyName () == debugger.PROP_STATE) ) && (debugger.getState () == debugger.STATE_STOPPED) ) { // IF state has been changed to STOPPED or // IF current call stack frame has been changed & state is stoped final ClassesTreeModel ltm = getModel (); if (ltm == null) return; if (task != null) { // cancel old task task.cancel (); if (verbose) System.out.println ("ClTM cancel old task " + task); task = null; } task = RequestProcessor.getDefault ().post (new Runnable () { public void run () { if (debugger.getState () != debugger.STATE_STOPPED) { if (verbose) System.out.println ("ClTM cancel started task " + task); return; } if (verbose) System.out.println ("ClTM do task " + task); ltm.fireTreeChanged (); } }, 500); if (verbose) System.out.println ("ClTM create task " + task); } else if ( (e.getPropertyName () == debugger.PROP_STATE) && (debugger.getState () != debugger.STATE_STOPPED) && (task != null) ) { // debugger has been resumed // =>> cancel task task.cancel (); if (verbose) System.out.println ("ClTM cancel task " + task); task = null; } } } private static class PackageComarator implements Comparator { public int compare (Object o1, Object o2) { if (o1 instanceof Object[]) { if (o2 instanceof Object[]) return ((String) ((Object[]) o1) [0]).compareTo (((Object[]) o2) [0]); return -1; } if (o2 instanceof Object[]) return 1; return shortName (((ReferenceType) o1).name ()).compareTo ( shortName (((ReferenceType) o2).name ()) ); } } private static class ClassLoaderComarator implements Comparator { public int compare (Object o1, Object o2) { if (o1 == NULL_CLASS_LOADER) { if (o2 == NULL_CLASS_LOADER) return 0; return -1; } if (o2 == NULL_CLASS_LOADER) return 1; return ((ClassLoaderReference) o1).toString ().compareTo ( ((ClassLoaderReference) o2).toString () ); } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.