1 19 20 package org.netbeans.modules.enode; 21 22 import java.util.ArrayList ; 23 import java.util.HashSet ; 24 import java.util.Iterator ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 import java.util.Set ; 28 29 import org.openide.ErrorManager; 30 import org.openide.util.Lookup; 31 import org.openide.util.Lookup.Template; 32 import org.openide.util.WeakListeners; 33 import org.openide.util.lookup.AbstractLookup; 34 import org.openide.util.lookup.InstanceContent; 35 import org.openide.util.lookup.ProxyLookup; 36 37 import org.netbeans.api.enode.ExtensibleNode; 38 import org.netbeans.spi.enode.LookupContentFactory; 39 import org.netbeans.api.registry.*; 40 41 46 public class ExtensibleLookupImpl extends ProxyLookup { 47 48 private static ErrorManager log = ErrorManager.getDefault().getInstance(SubMenuCache.class.getName()); 49 private static boolean LOGGABLE = log.isLoggable(ErrorManager.INFORMATIONAL); 50 51 52 private ExtensibleNode enode; 53 54 56 private InstanceContent content; 57 58 62 private List candidates; 63 64 65 private Object lock = new Object (); 66 67 68 private boolean settingLookups = false; 69 70 74 private Listener listener; 75 78 private boolean listenersAttached = false; 79 80 86 private Set listenersAttachedTo = new HashSet (); 87 88 92 public ExtensibleLookupImpl() { 93 super(new Lookup[0]); 94 } 95 96 100 public final void setExtensibleNode(ExtensibleNode en) { 101 this.enode = en; 102 Lookup instances = new AbstractLookup(content = new InstanceContent()); 103 setLookups(new Lookup[] { instances }); 104 } 105 106 109 protected void beforeLookup (Template template) { 110 super.beforeLookup(template); 111 112 if (settingLookups) { 113 if (LOGGABLE) { 114 log.log(this + " beforeLookup exiting because settingLookups == true"); Thread.dumpStack(); 116 } 117 return; 118 } 119 120 if (LOGGABLE) log.log("beforeLookup " + template.getType().getName()); 121 Iterator c = getCandidates(); 122 123 while (c.hasNext()) { 124 Object o = c.next(); 125 if (LOGGABLE) log.log("candidate " + o); 126 if (o instanceof LookupContentFactory) { 127 LookupContentFactory lcf = (LookupContentFactory)o; 128 if (lcf instanceof FactoryWrapper) { 129 FactoryWrapper impl = (FactoryWrapper)lcf; 132 if (! impl.matches(template)) { 133 if (LOGGABLE) log.log("continue"); 134 continue; 135 } 136 } 137 synchronized (lock) { 139 if (candidates != null) { 143 candidates.remove(o); 144 } 145 } 146 147 Object resObject = lcf.create(enode); 148 Lookup resLookup = lcf.createLookup(enode); 149 if (resLookup != null) { 150 if (LOGGABLE) log.log("adding lookup " + resLookup); 151 addLookup(resLookup); 152 } 153 if (resObject != null) { 154 if (LOGGABLE) log.log("adding " + resObject); 155 content.add(resObject); 156 } 157 } else { 158 if (! (o instanceof Context)) { ErrorManager.getDefault().log(ErrorManager.WARNING, 160 "For " + enode + " ExtensibleNodeLookup found an object that is not LookupContentFactory : " + o); } 163 } 164 } 165 } 166 167 170 private void addLookup(Lookup l) { 171 Lookup []old = getLookups(); 172 for (int i = 0; i < old.length; i++) { 173 if (old[i] == l) { 174 return; 176 } 177 } 178 Lookup []newL = new Lookup[old.length + 1]; 179 System.arraycopy(old, 0, newL, 0, old.length); 180 newL[old.length] = l; 181 try { 182 settingLookups = true; 183 setLookups(newL); 184 } finally { 185 settingLookups = false; 186 } 187 } 188 189 195 private Iterator getCandidates() { 196 List c = null; 197 if (candidates == null) { 198 c = new LinkedList (); 200 String [] whereToSearch = enode.getPaths(); 201 for (int i = 0; i < whereToSearch.length; i++) { 202 computeCandidates(whereToSearch[i], c); 203 } 204 listenersAttached = true; 205 } 206 207 synchronized (lock) { 208 if (candidates == null) { 209 candidates = c; 210 } 211 List result = new ArrayList (candidates); 213 return result.iterator(); 214 } 215 } 216 217 220 private void computeCandidates(String name, List result) { 221 String path = ExtensibleNode.E_NODE_LOOKUP + name; 222 try { 223 boolean exists = true; 224 Context con = Context.getDefault().getSubcontext(path); 225 if (con == null) { 226 con = findExistingContext(path); 227 exists = false; 228 } 229 if (!listenersAttached) { 230 ContextListener l1 = getContextListener(con); 231 con.addContextListener(l1); 232 listenersAttachedTo.add(con); 233 } 234 if (exists) { 235 List objects = con.getOrderedObjects(); 236 result.addAll(objects); 237 } 238 } catch (Exception ce) { 239 ErrorManager.getDefault().getInstance("org.netbeans.modules.enode").notify(ErrorManager.INFORMATIONAL, ce); } 241 } 242 243 249 private ContextListener getContextListener(Object source) { 250 if (listener == null) { 251 listener = new Listener(); 252 } 253 return (ContextListener)WeakListeners.create(ContextListener.class, listener, source); 254 } 255 256 260 private void changeContent() { 261 synchronized (lock) { 262 candidates = null; 263 } 264 Lookup instances = new AbstractLookup(content = new InstanceContent()); 265 setLookups(new Lookup[] { instances }); 266 } 267 268 272 private class Listener implements ContextListener { 273 public void attributeChanged(AttributeEvent evt) { 274 changeContent(); 275 } 276 277 public void bindingChanged(BindingEvent evt) { 278 changeContent(); 279 } 280 281 public void subcontextChanged(SubcontextEvent evt) { 282 changeContent(); 283 } 284 } 285 286 291 static Context findExistingContext(String path) { 292 String result = path; 293 Context con = Context.getDefault().getSubcontext(result); 294 while (con == null) { 295 int slash = result.lastIndexOf('/'); 296 if (slash < 0) { 297 if (LOGGABLE) log.log("Cound not find proper context for " + path); return Context.getDefault(); 299 } 300 result = result.substring(0, slash); 301 con = Context.getDefault().getSubcontext(result); 302 } 303 return con; 304 } 305 } 306 | Popular Tags |