1 19 20 package org.netbeans.modules.debugger.jpda.models; 21 22 import com.sun.jdi.ArrayType; 23 import com.sun.jdi.ClassLoaderReference; 24 import com.sun.jdi.ObjectCollectedException; 25 import com.sun.jdi.ReferenceType; 26 import com.sun.jdi.VMDisconnectedException; 27 import com.sun.jdi.VirtualMachine; 28 29 import java.beans.PropertyChangeEvent ; 30 import java.beans.PropertyChangeListener ; 31 import java.lang.ref.WeakReference ; 32 import java.util.ArrayList ; 33 import java.util.Comparator ; 34 import java.util.HashMap ; 35 import java.util.List ; 36 import java.util.Set ; 37 import java.util.TreeSet ; 38 import java.util.Vector ; 39 import org.netbeans.api.debugger.Properties; 40 41 import org.netbeans.spi.debugger.ContextProvider; 42 import org.netbeans.api.debugger.jpda.JPDADebugger; 43 import org.netbeans.spi.viewmodel.TreeModel; 44 import org.netbeans.spi.viewmodel.ModelListener; 45 import org.netbeans.spi.viewmodel.UnknownTypeException; 46 47 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl; 48 49 import org.openide.util.RequestProcessor; 50 51 52 55 public class ClassesTreeModel implements TreeModel { 56 57 58 private static boolean verbose = 59 (System.getProperty ("netbeans.debugger.viewrefresh") != null) && 60 (System.getProperty ("netbeans.debugger.viewrefresh").indexOf ('s') >= 0); 61 62 private Properties classesProperties = Properties.getDefault(). 63 getProperties("debugger").getProperties("classesView"); 65 66 private JPDADebuggerImpl debugger; 67 private Listener listener; 68 private Vector <ModelListener> listeners = new Vector <ModelListener>(); 69 70 71 public ClassesTreeModel(ContextProvider lookupProvider) { 72 debugger = (JPDADebuggerImpl) lookupProvider. 73 lookupFirst (null, JPDADebugger.class); 74 } 75 76 public Object getRoot () { 77 return ROOT; 78 } 79 80 public Object [] getChildren (Object o, int from, int to) 81 throws UnknownTypeException { 82 try { 83 Object [] r = null; 84 if (o.equals (ROOT)) { 85 r = getLoaders (); 86 } else 87 if (o instanceof Object []) { 88 r = getChildren ((Object []) o); 89 } else 90 if (o instanceof ClassLoaderReference) { 91 r = getPackages ((ClassLoaderReference) o); 92 } else 93 if (o == NULL_CLASS_LOADER) { 94 r = getPackages (null); 95 } else 96 if (o instanceof ReferenceType) { 97 r = ((ReferenceType) o).nestedTypes ().toArray (); 98 } else 99 throw new UnknownTypeException (o); 100 to = Math.min(r.length, to); 101 from = Math.min(r.length, from); 102 Object [] rr = new Object [to - from]; 103 System.arraycopy (r, from, rr, 0, to - from); 104 return rr; 105 } catch (VMDisconnectedException ex) { 106 return new Object [0]; 107 } 108 } 109 110 119 public int getChildrenCount (Object node) throws UnknownTypeException { 120 try { 121 if (node.equals (ROOT)) 122 return Integer.MAX_VALUE; 124 if (node instanceof Object []) 126 return Integer.MAX_VALUE; 128 if (node instanceof ClassLoaderReference) 130 return Integer.MAX_VALUE; 132 if (node == NULL_CLASS_LOADER) 134 return Integer.MAX_VALUE; 136 if (node instanceof ReferenceType) { 138 return Integer.MAX_VALUE; 140 } 142 throw new UnknownTypeException (node); 143 } catch (VMDisconnectedException ex) { 144 return 0; 145 } 146 } 147 148 public boolean isLeaf (Object o) throws UnknownTypeException { 149 if (o.equals (ROOT)) return false; 150 if (o instanceof Object []) return false; 151 if (o instanceof ReferenceType) return false; 152 if (o instanceof ClassLoaderReference) return false; 153 if (o == NULL_CLASS_LOADER) return false; 154 throw new UnknownTypeException (o); 155 } 156 157 public void addModelListener (ModelListener l) { 158 listeners.add (l); 159 if (listener == null) 160 listener = new Listener (this, debugger); 161 } 162 163 public void removeModelListener (ModelListener l) { 164 listeners.remove (l); 165 if (listeners.size () == 0) { 166 listener.destroy (); 167 listener = null; 168 } 169 } 170 171 public void fireTreeChanged () { 172 classes = null; 173 names = null; 174 cache = new HashMap (); 175 Vector v = (Vector ) listeners.clone (); 176 int i, k = v.size (); 177 for (i = 0; i < k; i++) 178 ((ModelListener) v.get (i)).modelChanged (null); 179 } 180 181 182 184 private List <ReferenceType> classes = null; private List <String > names = null; private HashMap cache = new HashMap (); 187 private Comparator comparator = new PackageComparator (); 191 private Comparator comparator1 = new ClassLoaderComparator (); 192 static final Integer NULL_CLASS_LOADER = new Integer (11); 193 194 195 private List <String > getNames () { 196 if (classes == null) { 197 VirtualMachine vm = debugger.getVirtualMachine (); 198 List referenceTypes = new ArrayList (); 199 if (vm != null) 200 referenceTypes = vm.allClasses (); 201 int i, k = referenceTypes.size (); 202 names = new ArrayList <String >(); 203 classes = new ArrayList <ReferenceType>(); 204 for (i = 0; i < k; i++) { 205 ReferenceType rt = (ReferenceType) referenceTypes.get (i); 206 if (rt instanceof ArrayType) continue; 207 names.add (rt.name ()); 208 classes.add (rt); 209 } 210 } 211 return names; 212 } 213 214 private Object [] getLoaders () { 215 Object [] ch = (Object []) cache.get (null); 216 if (ch != null) return ch; 217 List <String > names = getNames (); 218 Set loaders = new TreeSet (comparator1); 219 int i, k = names.size (); 220 for (i = 0; i < k; i++) { 221 try { 222 String name = names.get (i); 223 ReferenceType rt = classes.get (i); 224 ClassLoaderReference clr = rt.classLoader (); 225 if (clr == null) 226 loaders.add (NULL_CLASS_LOADER); 227 else 228 if (clr.referenceType ().name ().equals ("sun.reflect.DelegatingClassLoader")) 229 continue; 230 else 231 loaders.add (clr); 232 } catch (ObjectCollectedException ex) { 233 } 234 } 235 ch = loaders.toArray (); 236 cache.put (null, ch); 237 return ch; 238 } 239 240 private Object [] getPackages (ClassLoaderReference clr) { 241 Object [] ch = clr == null ? 242 (Object []) cache.get (NULL_CLASS_LOADER) : 243 (Object []) cache.get (clr); 244 if (ch != null) return ch; 245 boolean flat = classesProperties.getBoolean("flat", true); 246 List <String > names = getNames (); 247 Set objects = new TreeSet (comparator); 248 int i, k = names.size (); 249 for (i = 0; i < k; i++) { 250 String name = names.get (i); 251 ReferenceType rt = classes.get (i); 252 if (rt.classLoader () != clr) continue; 253 int end; 254 if (flat) { 255 end = name.lastIndexOf ('.'); 256 } else { 257 end = name.indexOf ('.'); 258 } 259 if (end < 0) { 260 if (name.indexOf ('$') < 0) { 262 ReferenceType tr = classes.get (i); 263 objects.add (tr); 264 } 265 } else 266 objects.add (new Object [] {name.substring (0, end), clr}); 267 } 268 ch = objects.toArray (); 269 if (clr == null) 270 cache.put (NULL_CLASS_LOADER, ch); 271 else 272 cache.put (clr, ch); 273 return ch; 274 } 275 276 private Object [] getChildren (Object [] parent) { 277 Object [] ch = (Object []) cache.get (parent); 278 if (ch != null) return ch; 279 List <String > names = getNames (); 280 Set objects = new TreeSet (comparator); 281 int i, k = names.size (); 282 boolean flat = classesProperties.getBoolean("flat", true); 283 for (i = 0; i < k; i++) { 284 String name = names.get (i); 285 ReferenceType rt = classes.get (i); 286 if (rt.classLoader () != parent [1]) continue; 287 String parentN = ((String ) parent [0]) + '.'; 288 if (!name.startsWith (parentN)) continue; 289 int start = (parentN).length (); 290 int end = name.indexOf ('.', start); 291 if (end < 0) { 292 if (name.indexOf ('$', start) < 0) { 294 objects.add (rt); 295 } 296 } else if (!flat) { 297 objects.add (new Object [] {name.substring (0, end), rt.classLoader ()}); 298 } 299 } 300 ch = objects.toArray (); 301 cache.put (parent, ch); 302 return ch; 303 } 304 305 JPDADebuggerImpl getDebugger () { 306 return debugger; 307 } 308 309 private static String shortName (String name) { 310 int i = name.lastIndexOf ('.'); 311 if (i < 0) return name; 312 return name.substring (i + 1); 313 } 314 315 316 318 private static class Listener implements PropertyChangeListener { 319 320 private JPDADebugger debugger; 321 private WeakReference <ClassesTreeModel> model; 322 323 public Listener ( 324 ClassesTreeModel tm, 325 JPDADebugger debugger 326 ) { 327 this.debugger = debugger; 328 model = new WeakReference <ClassesTreeModel>(tm); 329 debugger.addPropertyChangeListener (this); 330 } 331 332 void destroy () { 333 debugger.removePropertyChangeListener (this); 334 if (task != null) { 335 task.cancel (); 337 if (verbose) 338 System.out.println ("ClTM cancel old task " + task); 339 task = null; 340 } 341 } 342 343 private ClassesTreeModel getModel () { 344 ClassesTreeModel tm = model.get (); 345 if (tm == null) { 346 destroy (); 347 } 348 return tm; 349 } 350 351 private RequestProcessor.Task task; 354 355 public void propertyChange (PropertyChangeEvent e) { 356 if ( ( (e.getPropertyName () == 357 debugger.PROP_CURRENT_CALL_STACK_FRAME) || 358 (e.getPropertyName () == debugger.PROP_STATE) 360 ) && (debugger.getState () == debugger.STATE_STOPPED) 361 ) { 362 final ClassesTreeModel ltm = getModel (); 365 if (ltm == null) return; 366 if (task != null) { 367 task.cancel (); 369 if (verbose) 370 System.out.println ("ClTM cancel old task " + task); 371 task = null; 372 } 373 task = RequestProcessor.getDefault ().post (new Runnable () { 374 public void run () { 375 if (debugger.getState () != debugger.STATE_STOPPED) { 376 if (verbose) 377 System.out.println ("ClTM cancel started task " + task); 378 return; 379 } 380 if (verbose) 381 System.out.println ("ClTM do task " + task); 382 ltm.fireTreeChanged (); 383 } 384 }, 500); 385 if (verbose) 386 System.out.println ("ClTM create task " + task); 387 } else 388 if ( (e.getPropertyName () == debugger.PROP_STATE) && 389 (debugger.getState () != debugger.STATE_STOPPED) && 390 (task != null) 391 ) { 392 task.cancel (); 395 if (verbose) 396 System.out.println ("ClTM cancel task " + task); 397 task = null; 398 } 399 } 400 } 401 402 private static class PackageComparator implements Comparator { 403 public PackageComparator () {} 404 405 public int compare (Object o1, Object o2) { 406 if (o1 instanceof Object []) { 407 if (o2 instanceof Object []) 408 return ((String ) ((Object []) o1) [0]).compareTo ((String ) ((Object []) o2) [0]); 409 return -1; 410 } 411 if (o2 instanceof Object []) 412 return 1; 413 return shortName (((ReferenceType) o1).name ()).compareTo ( 414 shortName (((ReferenceType) o2).name ()) 415 ); 416 } 417 } 418 419 private static class ClassLoaderComparator implements Comparator { 420 public ClassLoaderComparator () {} 421 422 public int compare (Object o1, Object o2) { 423 if (o1 == NULL_CLASS_LOADER) { 424 if (o2 == NULL_CLASS_LOADER) 425 return 0; 426 return -1; 427 } 428 if (o2 == NULL_CLASS_LOADER) 429 return 1; 430 return ((ClassLoaderReference) o1).toString ().compareTo ( 431 ((ClassLoaderReference) o2).toString () 432 ); 433 } 434 } 435 } 436 | Popular Tags |