1 19 20 package org.netbeans.modules.apisupport.beanbrowser; 21 22 import java.awt.Container ; 23 import java.awt.datatransfer.Clipboard ; 24 import java.beans.IntrospectionException ; 25 import java.beans.PropertyChangeEvent ; 26 import java.beans.PropertyChangeListener ; 27 import java.io.File ; 28 import java.lang.reflect.Method ; 29 import java.util.ArrayList ; 30 import java.util.Collection ; 31 import java.util.Collections ; 32 import java.util.LinkedList ; 33 import java.util.List ; 34 import java.util.StringTokenizer ; 35 import org.openide.ErrorManager; 36 import org.openide.cookies.InstanceCookie; 37 import org.openide.filesystems.FileObject; 38 import org.openide.filesystems.FileSystem; 39 import org.openide.filesystems.LocalFileSystem; 40 import org.openide.filesystems.MultiFileSystem; 41 import org.openide.filesystems.XMLFileSystem; 42 import org.openide.loaders.DataObject; 43 import org.openide.nodes.AbstractNode; 44 import org.openide.nodes.BeanNode; 45 import org.openide.nodes.Children; 46 import org.openide.nodes.FilterNode; 47 import org.openide.nodes.Node; 48 import org.openide.nodes.NodeAdapter; 49 import org.openide.nodes.NodeListener; 50 import org.openide.nodes.NodeMemberEvent; 51 import org.openide.nodes.NodeReorderEvent; 52 import org.openide.util.HelpCtx; 53 import org.openide.util.Lookup; 54 import org.openide.util.lookup.Lookups; 55 56 60 class WrapperKids extends Children.Keys implements Cloneable { 61 62 private static final Object instanceKey = new Object () { 64 public String toString() { 65 return "Key for instance cookie."; 66 } 67 }; 68 private static final Object rawBeanPropsKey = new Object () { 69 public String toString() { 70 return "Key for raw bean properties."; 71 } 72 }; 73 private static final class NormalChildKey { 74 private final Node child; 75 public NormalChildKey(Node child) { 76 this.child = child; 77 } 78 public Node wrap() { 79 return Wrapper.make(child); 80 } 81 } 82 private static final class LookupProviderKey { 83 public final Lookup.Provider p; 84 public LookupProviderKey(Lookup.Provider p) { 85 this.p = p; 86 } 87 } 88 89 private Node original; 90 private NodeListener nListener = null; 91 private PropertyChangeListener fsListener = null; 92 private FileSystem fileSystemToListenOn = null; 93 94 WrapperKids(Node orig) { 95 original = orig; 96 } 97 public Object clone() { 99 return new WrapperKids(original); 100 } 101 102 112 private void updateKeys(final boolean addListeners) { 113 Children.MUTEX.postWriteRequest(new Runnable () { public void run() { 116 List newkeys = new ArrayList (); 117 Node[] children = original.getChildren().getNodes(false); 118 for (int i = 0; i < children.length; i++) { 119 newkeys.add(new NormalChildKey(children[i])); 120 } 121 newkeys.addAll(makePSKeys()); 122 if (! (original instanceof BeanNode) && original.getCookie(InstanceCookie.class) != null) 124 newkeys.add(instanceKey); 125 if (original instanceof BeanNode) { 127 newkeys.add(rawBeanPropsKey); 128 try { 129 InstanceCookie cookie = (InstanceCookie) original.getCookie(InstanceCookie.class); 130 Object instance = cookie.instanceCreate(); 131 Class [] recognized = { Node.class, Container .class, FileSystem.class, FileObject.class, Clipboard .class }; 132 for (int i = 0; i < recognized.length; i++) 133 if (recognized[i].isInstance(instance)) 134 newkeys.add(instance); 135 if (instance instanceof FileSystem) 137 fileSystemToListenOn = (FileSystem) instance; 138 if (instance instanceof Lookup.Provider) { 139 newkeys.add(new LookupProviderKey((Lookup.Provider)instance)); 140 } 141 } catch (Exception e) { 142 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 143 } 144 } else { 145 newkeys.add(new LookupProviderKey(original)); 146 } 147 setKeys(newkeys); 148 if (addListeners) { 150 nListener = new NodeAdapter() { 151 public void propertyChange(PropertyChangeEvent ev) { 152 if (Node.PROP_PROPERTY_SETS.equals(ev.getPropertyName())) { 153 updateKeys(false); 154 } 155 } 156 public void childrenAdded(NodeMemberEvent ev) { 158 updateKeys(false); 159 } 160 public void childrenRemoved(NodeMemberEvent ev) { 161 updateKeys(false); 162 } 163 public void childrenReordered(NodeReorderEvent ev) { 164 updateKeys(false); 165 } 166 }; 167 original.addNodeListener(nListener); 168 if (fileSystemToListenOn != null) { 169 fsListener = new PropertyChangeListener () { 170 public void propertyChange(PropertyChangeEvent ev) { 171 if (FileSystem.PROP_ROOT.equals(ev.getPropertyName())) { 172 updateKeys(false); 173 } 174 } 175 }; 176 fileSystemToListenOn.addPropertyChangeListener(fsListener); 177 } 178 } 179 }}); 180 } 181 182 186 protected void addNotify() { 187 updateKeys(true); 189 } 190 191 protected void removeNotify() { 192 if (nListener != null) { 193 original.removeNodeListener(nListener); 194 nListener = null; 195 } 196 if (fsListener != null) { 197 fileSystemToListenOn.removePropertyChangeListener(fsListener); 198 fsListener = null; 199 fileSystemToListenOn = null; 200 } 201 setKeys(Collections.EMPTY_SET); 202 } 203 204 212 private Collection makePSKeys() { 213 Collection toret = new ArrayList (); 214 Node.PropertySet[] pss = original.getPropertySets(); 215 for (int i = 0; i < pss.length; i++) { 216 Node.PropertySet ps = pss[i]; 217 Node.Property[] props = ps.getProperties(); 218 boolean useme = false; 219 for (int j = 0; j < props.length; j++) { 220 Node.Property prop = props[j]; 221 if (prop.canRead()) { 222 Class type = prop.getValueType(); 223 if (! (type.isPrimitive() || type == String .class || type == Class .class)) { 224 useme = true; 225 } 226 } 227 } 228 if (useme) toret.add(ps); 229 } 230 return toret; 231 } 232 233 239 protected Node[] createNodes(Object key) { 240 if (key instanceof NormalChildKey) { 241 return new Node[] {((NormalChildKey) key).wrap()}; 242 } else if (key instanceof Node.PropertySet) { 243 return new Node[] { new PropSet(original, (Node.PropertySet) key) }; 245 } else if (key == rawBeanPropsKey) { 246 try { 248 InstanceCookie inst = (InstanceCookie) original.getCookie(InstanceCookie.class); 249 AbstractNode n = new AbstractNode(new RawBeanPropKids(inst.instanceCreate())) { 250 public HelpCtx getHelpCtx() { 251 return new HelpCtx("org.netbeans.modules.apisupport.beanbrowser"); 252 } 253 }; 254 n.setName("Raw bean properties..."); 255 n.setIconBaseWithExtension("org/netbeans/modules/apisupport/beanbrowser/BeanBrowserIcon.gif"); 256 return new Node[] { n }; 257 } catch (Exception e) { 258 return new Node[] { Wrapper.make(PropSetKids.makeErrorNode(e)) }; 259 } 260 } else if (key == instanceKey) { 261 try { 264 InstanceCookie inst = (InstanceCookie) original.getCookie(InstanceCookie.class); 265 Node node = new RefinedBeanNode(inst.instanceCreate()); 266 node.setShortDescription("Instance name: `" + inst.instanceName() + 267 "'; normal node name: `" + node.getDisplayName() + "'; normal description: `" + 268 node.getShortDescription() + "'"); 269 node.setDisplayName("Instance of class " + inst.instanceClass().getName()); 270 return new Node[] { Wrapper.make(node) }; 271 } catch (Exception e) { 272 return new Node[] { Wrapper.make(PropSetKids.makeErrorNode(e)) }; 273 } 274 } else if (key instanceof Node) { 275 List toret = new LinkedList (); AbstractNode marker = new AbstractNode(new Children.Array()) { 278 public HelpCtx getHelpCtx() { 279 return new HelpCtx("org.netbeans.modules.apisupport.beanbrowser"); 280 } 281 }; 282 marker.setName("An actual node here:"); 283 marker.setIconBaseWithExtension("org/netbeans/modules/apisupport/beanbrowser/BeanBrowserIcon.gif"); 284 marker.getChildren().add(new Node[] { Wrapper.make((Node) key) }); 285 toret.add(marker); 286 if (key instanceof FilterNode) { 287 try { 289 Method m = FilterNode.class.getDeclaredMethod("getOriginal", new Class [] { }); 290 m.setAccessible(true); 291 try { 292 Node orig = (Node) m.invoke(key, new Object [] { }); 293 AbstractNode marker2 = new AbstractNode(new Children.Array()) { 294 public HelpCtx getHelpCtx() { 295 return new HelpCtx("org.netbeans.modules.apisupport.beanbrowser"); 296 } 297 }; 298 marker2.setName("The original from the filter node:"); 299 marker2.setIconBaseWithExtension("org/netbeans/modules/apisupport/beanbrowser/BeanBrowserIcon.gif"); 300 marker2.getChildren().add(new Node[] { PropSetKids.makeObjectNode(orig) }); 301 toret.add(marker2); 302 } finally { 303 m.setAccessible(false); 304 } 305 } catch (Exception e) { 306 toret.add(Wrapper.make(PropSetKids.makeErrorNode(e))); 307 } 308 } 309 return (Node[]) toret.toArray(new Node[toret.size()]); 310 } else if (key instanceof Container ) { 312 Children kids = new ContainerKids((Container ) key); 314 AbstractNode n = new AbstractNode(kids) { 315 public HelpCtx getHelpCtx() { 316 return new HelpCtx("org.netbeans.modules.apisupport.beanbrowser"); 317 } 318 }; 319 n.setName("Components..."); 320 n.setIconBaseWithExtension("org/netbeans/modules/apisupport/beanbrowser/BeanBrowserIcon.gif"); 321 return new Node[] { n }; 322 } else if (key instanceof FileSystem) { 323 try { 325 Node fsn = new RefinedBeanNode(((FileSystem) key).getRoot()); 326 fsn.setDisplayName("[root] " + fsn.getDisplayName()); 327 return new Node[] { Wrapper.make(fsn) }; 328 } catch (IntrospectionException e) { 329 return new Node[] { Wrapper.make(PropSetKids.makeErrorNode(e)) }; 330 } 331 } else if (key instanceof FileObject) { 332 FileObject fo = (FileObject)key; 333 List l = new LinkedList (); try { 338 Node fsn = new RefinedBeanNode(DataObject.find(fo)); 339 fsn.setDisplayName("[data object] " + fsn.getDisplayName()); 340 l.add(Wrapper.make(fsn)); 341 } catch (Exception e) { l.add(Wrapper.make(PropSetKids.makeErrorNode(e))); 343 } 344 Children kids = new FileAttrKids(fo); 345 AbstractNode attrnode = new AbstractNode(kids) { 346 public HelpCtx getHelpCtx() { 347 return new HelpCtx("org.netbeans.modules.apisupport.beanbrowser"); 348 } 349 }; 350 attrnode.setName("Attributes..."); 351 attrnode.setIconBaseWithExtension("org/netbeans/modules/apisupport/beanbrowser/BeanBrowserIcon.gif"); 352 l.add(attrnode); 353 try { 354 FileSystem apparentFS = fo.getFileSystem(); 355 if (apparentFS instanceof MultiFileSystem) { 356 FileSystem fs = apparentFS; 358 FileObject workingFO = fo; 359 boolean project = false; 360 while (fs instanceof MultiFileSystem) { 361 if (fs.getClass().getName().equals("org.netbeans.core.projects.FilterFileSystem")) { 362 project = true; 365 break; 366 } 367 Method m = MultiFileSystem.class.getDeclaredMethod("findSystem", new Class [] {FileObject.class}); 368 m.setAccessible(true); 369 try { 370 FileSystem foundFS = (FileSystem)m.invoke(fs, new Object [] {workingFO}); 372 if (foundFS == fs) { 373 break; 376 } else { 377 Method m2 = MultiFileSystem.class.getDeclaredMethod("findResourceOn", new Class [] {FileSystem.class, String .class}); 378 m2.setAccessible(true); 379 try { 380 FileObject newFO = (FileObject)m2.invoke(fs, new Object [] {foundFS, workingFO.getPath()}); 381 if (newFO != null) { 382 fs = foundFS; 384 workingFO = newFO; 385 } else { 386 } 388 } finally { 389 m2.setAccessible(false); 390 } 391 } 392 } finally { 393 m.setAccessible(false); 394 } 395 } 396 if (project || fs != apparentFS) { 397 String provenance = null; 398 if (project) { 399 provenance = "project"; 400 } else if (fs instanceof LocalFileSystem) { 401 File dir = ((LocalFileSystem)fs).getRootDirectory(); 402 StringTokenizer tok = new StringTokenizer (System.getProperty("netbeans.dirs", ""), File.pathSeparator); 404 while (tok.hasMoreTokens()) { 405 File system = new File (new File (tok.nextToken()), "system"); if (dir.equals(system)) { 407 provenance = "NetBeans installation"; 408 break; 409 } 410 } 411 if (provenance == null) { 412 File system1 = new File (new File (System.getProperty("netbeans.home")), "system"); 413 File system2 = new File (new File (System.getProperty("netbeans.user")), "system"); 414 if (dir.equals(system1)) { 415 provenance = "NetBeans installation"; 416 } else if (dir.equals(system2)) { 417 provenance = "user directory"; 418 } 419 } 420 } else if (fs instanceof XMLFileSystem) { 421 provenance = "module"; 424 } 425 if (provenance != null) { 426 l.add(PropSetKids.makePlainNode("Provenance: " + provenance)); 428 } else { 429 Node rfsn = new RefinedBeanNode(fs); 431 rfsn.setDisplayName("[original file system] " + rfsn.getDisplayName()); 432 l.add(Wrapper.make(rfsn)); 433 } 434 } 435 } 436 } catch (Exception e) { 437 l.add(Wrapper.make(PropSetKids.makeErrorNode(e))); 438 } 439 return (Node[])l.toArray(new Node[l.size()]); 440 } else if (key instanceof Clipboard ) { 441 Children kids = new ClipboardKids((Clipboard ) key); 442 AbstractNode n = new AbstractNode(kids) { 443 public HelpCtx getHelpCtx() { 444 return new HelpCtx("org.netbeans.modules.apisupport.beanbrowser"); 445 } 446 }; 447 n.setName("Transferables..."); 448 n.setIconBaseWithExtension("org/netbeans/modules/apisupport/beanbrowser/BeanBrowserIcon.gif"); 449 return new Node[] { n }; 450 } else if (key instanceof LookupProviderKey) { Node n = LookupNode.localLookupNode(Lookups.proxy(((LookupProviderKey) key).p)); 452 n.setDisplayName("Cookies..."); 453 return new Node[] { n }; 454 } else { 455 throw new RuntimeException ("Weird key: " + key); 456 } 457 } 458 459 } 460 | Popular Tags |