Lines 64-71
import java.util.List;
Link Here
|
64 |
import java.util.List; |
64 |
import java.util.List; |
65 |
import java.util.Map; |
65 |
import java.util.Map; |
66 |
import java.util.Set; |
66 |
import java.util.Set; |
67 |
import java.util.TreeSet; |
|
|
68 |
|
67 |
|
|
|
68 |
import java.util.logging.Level; |
69 |
import java.util.logging.Logger; |
69 |
import org.netbeans.spi.debugger.ContextProvider; |
70 |
import org.netbeans.spi.debugger.ContextProvider; |
70 |
import org.openide.ErrorManager; |
71 |
import org.openide.ErrorManager; |
71 |
import org.openide.modules.ModuleInfo; |
72 |
import org.openide.modules.ModuleInfo; |
Lines 90-104
abstract class Lookup implements Context
Link Here
|
90 |
public static final String NOTIFY_UNLOAD_FIRST = "unload first"; |
91 |
public static final String NOTIFY_UNLOAD_FIRST = "unload first"; |
91 |
public static final String NOTIFY_UNLOAD_LAST = "unload last"; |
92 |
public static final String NOTIFY_UNLOAD_LAST = "unload last"; |
92 |
|
93 |
|
93 |
public Object lookupFirst (String folder, Class service) { |
94 |
public <T> T lookupFirst(String folder, Class<T> service) { |
94 |
List l = lookup (folder, service); |
95 |
List<? extends T> l = lookup(folder, service); |
95 |
synchronized (l) { |
96 |
synchronized (l) { |
96 |
if (l.isEmpty ()) return null; |
97 |
if (l.isEmpty ()) return null; |
97 |
return l.get (0); |
98 |
return l.get (0); |
98 |
} |
99 |
} |
99 |
} |
100 |
} |
100 |
|
101 |
|
101 |
public abstract List lookup (String folder, Class service); |
102 |
public abstract <T> List<? extends T> lookup(String folder, Class<T> service); |
102 |
|
103 |
|
103 |
|
104 |
|
104 |
private static boolean verbose = |
105 |
private static boolean verbose = |
Lines 112-130
abstract class Lookup implements Context
Link Here
|
112 |
this.services = services; |
113 |
this.services = services; |
113 |
} |
114 |
} |
114 |
|
115 |
|
115 |
public List lookup (String folder, Class service) { |
116 |
public <T> List<? extends T> lookup(String folder, Class<T> service) { |
116 |
ArrayList l = new ArrayList (); |
117 |
List<T> l = new ArrayList<T>(); |
117 |
int i, k = services.length; |
118 |
for (Object s : services) { |
118 |
for (i = 0; i < k; i++) |
119 |
if (service.isInstance(s)) { |
119 |
if (service.isAssignableFrom (services [i].getClass ())) { |
120 |
l.add(service.cast(s)); |
120 |
l.add (services [i]); |
|
|
121 |
if (verbose) |
121 |
if (verbose) |
122 |
System.out.println("\nR instance " + services [i] + |
122 |
System.out.println("\nR instance " + s + " found"); |
123 |
" found"); |
|
|
124 |
} |
123 |
} |
|
|
124 |
} |
125 |
return l; |
125 |
return l; |
126 |
} |
126 |
} |
127 |
|
|
|
128 |
} |
127 |
} |
129 |
|
128 |
|
130 |
static class Compound extends Lookup { |
129 |
static class Compound extends Lookup { |
Lines 137-144
abstract class Lookup implements Context
Link Here
|
137 |
setContext (this); |
136 |
setContext (this); |
138 |
} |
137 |
} |
139 |
|
138 |
|
140 |
public List lookup (String folder, Class service) { |
139 |
public <T> List<? extends T> lookup(String folder, Class<T> service) { |
141 |
return new CompoundLookupList(folder, service); |
140 |
return new CompoundLookupList<T>(folder, service); |
142 |
/*List l = new LookupList(null); |
141 |
/*List l = new LookupList(null); |
143 |
l.addAll (l1.lookup (folder, service)); |
142 |
l.addAll (l1.lookup (folder, service)); |
144 |
l.addAll (l2.lookup (folder, service)); |
143 |
l.addAll (l2.lookup (folder, service)); |
Lines 152-166
abstract class Lookup implements Context
Link Here
|
152 |
if (l2 instanceof MetaInf) ((MetaInf) l2).setContext (context); |
151 |
if (l2 instanceof MetaInf) ((MetaInf) l2).setContext (context); |
153 |
} |
152 |
} |
154 |
|
153 |
|
155 |
private class CompoundLookupList extends LookupList implements Customizer, |
154 |
private class CompoundLookupList<T> extends LookupList<T> implements Customizer, |
156 |
PropertyChangeListener { |
155 |
PropertyChangeListener { |
157 |
|
156 |
|
158 |
private String folder; |
157 |
private String folder; |
159 |
private Class service; |
158 |
private Class<T> service; |
160 |
private List<PropertyChangeListener> propertyChangeListeners; |
159 |
private List<PropertyChangeListener> propertyChangeListeners; |
161 |
private Customizer sublist1, sublist2; |
160 |
private Customizer sublist1, sublist2; |
162 |
|
161 |
|
163 |
public CompoundLookupList(String folder, Class service) { |
162 |
public CompoundLookupList(String folder, Class<T> service) { |
164 |
super(null); |
163 |
super(null); |
165 |
this.folder = folder; |
164 |
this.folder = folder; |
166 |
this.service = service; |
165 |
this.service = service; |
Lines 169-176
abstract class Lookup implements Context
Link Here
|
169 |
|
168 |
|
170 |
private synchronized void setUp() { |
169 |
private synchronized void setUp() { |
171 |
clear(); |
170 |
clear(); |
172 |
List list1 = l1.lookup (folder, service); |
171 |
List<? extends T> list1 = l1.lookup(folder, service); |
173 |
List list2 = l2.lookup (folder, service); |
172 |
List<? extends T> list2 = l2.lookup(folder, service); |
174 |
addAll (list1); |
173 |
addAll (list1); |
175 |
addAll (list2); |
174 |
addAll (list2); |
176 |
sublist1 = (list1 instanceof Customizer) ? (Customizer) list1 : null; |
175 |
sublist1 = (list1 instanceof Customizer) ? (Customizer) list1 : null; |
Lines 217-223
abstract class Lookup implements Context
Link Here
|
217 |
private static final String HIDDEN = "-hidden"; // NOI18N |
216 |
private static final String HIDDEN = "-hidden"; // NOI18N |
218 |
|
217 |
|
219 |
private String rootFolder; |
218 |
private String rootFolder; |
220 |
private HashMap registrationCache = new HashMap (); |
219 |
private Map<String,List<String>> registrationCache = new HashMap<String,List<String>>(); |
221 |
private HashMap<String, Object> instanceCache = new HashMap<String, Object>(); |
220 |
private HashMap<String, Object> instanceCache = new HashMap<String, Object>(); |
222 |
private Lookup context; |
221 |
private Lookup context; |
223 |
private org.openide.util.Lookup.Result<ModuleInfo> moduleLookupResult; |
222 |
private org.openide.util.Lookup.Result<ModuleInfo> moduleLookupResult; |
Lines 231-238
abstract class Lookup implements Context
Link Here
|
231 |
|
230 |
|
232 |
MetaInf (String rootFolder) { |
231 |
MetaInf (String rootFolder) { |
233 |
this.rootFolder = rootFolder; |
232 |
this.rootFolder = rootFolder; |
234 |
moduleLookupResult = org.openide.util.Lookup.getDefault ().lookup( |
233 |
moduleLookupResult = org.openide.util.Lookup.getDefault().lookupResult(ModuleInfo.class); |
235 |
new org.openide.util.Lookup.Template(ModuleInfo.class)); |
|
|
236 |
//System.err.println("\nModules = "+moduleLookupResult.allInstances().size()+"\n"); |
234 |
//System.err.println("\nModules = "+moduleLookupResult.allInstances().size()+"\n"); |
237 |
modulesChangeListener = new ModuleChangeListener(null); |
235 |
modulesChangeListener = new ModuleChangeListener(null); |
238 |
moduleLookupResult.addLookupListener( |
236 |
moduleLookupResult.addLookupListener( |
Lines 245-268
abstract class Lookup implements Context
Link Here
|
245 |
this.context = context; |
243 |
this.context = context; |
246 |
} |
244 |
} |
247 |
|
245 |
|
248 |
public List lookup (String folder, Class service) { |
246 |
public <T> List<? extends T> lookup(String folder, Class<T> service) { |
249 |
MetaInfLookupList mll = new MetaInfLookupList(folder, service); |
247 |
MetaInfLookupList<T> mll = new MetaInfLookupList<T>(folder, service); |
250 |
synchronized (lookupLists) { |
248 |
synchronized (lookupLists) { |
251 |
lookupLists.add(mll); |
249 |
lookupLists.add(mll); |
252 |
} |
250 |
} |
253 |
return mll; |
251 |
return mll; |
254 |
} |
252 |
} |
255 |
|
253 |
|
256 |
private List list (String folder, Class service) { |
254 |
private List<String> list(String folder, Class<?> service) { |
257 |
String name = service.getName (); |
255 |
String name = service.getName (); |
258 |
String resourceName = "META-INF/debugger/" + |
256 |
String resourceName = "META-INF/debugger/" + |
259 |
((rootFolder == null) ? "" : rootFolder + "/") + |
257 |
((rootFolder == null) ? "" : rootFolder + "/") + |
260 |
((folder == null) ? "" : folder + "/") + |
258 |
((folder == null) ? "" : folder + "/") + |
261 |
name; |
259 |
name; |
262 |
synchronized(registrationCache) { |
260 |
synchronized(registrationCache) { |
263 |
if (!registrationCache.containsKey (resourceName)) |
261 |
List<String> l = registrationCache.get(resourceName); |
264 |
registrationCache.put (resourceName, loadMetaInf (resourceName)); |
262 |
if (l == null) { |
265 |
return (List) registrationCache.get (resourceName); |
263 |
l = loadMetaInf(resourceName); |
|
|
264 |
registrationCache.put(resourceName, l); |
265 |
} |
266 |
return l; |
266 |
} |
267 |
} |
267 |
} |
268 |
} |
268 |
|
269 |
|
Lines 285-302
abstract class Lookup implements Context
Link Here
|
285 |
* Loads instances of given class from META-INF/debugger from given |
286 |
* Loads instances of given class from META-INF/debugger from given |
286 |
* folder. Given context isused as the parameter to constructor. |
287 |
* folder. Given context isused as the parameter to constructor. |
287 |
*/ |
288 |
*/ |
288 |
private ArrayList loadMetaInf ( |
289 |
private List<String> loadMetaInf(String resourceName) { |
289 |
String resourceName |
290 |
List<String> l = new ArrayList<String>(); |
290 |
) { |
|
|
291 |
ArrayList l = new ArrayList (); |
292 |
try { |
291 |
try { |
293 |
ClassLoader cl = (ClassLoader) org.openide.util.Lookup. |
292 |
ClassLoader cl = org.openide.util.Lookup.getDefault().lookup(ClassLoader.class); |
294 |
getDefault ().lookup (ClassLoader.class); |
|
|
295 |
String v = "\nR lookup " + resourceName; |
293 |
String v = "\nR lookup " + resourceName; |
296 |
Enumeration e = cl.getResources (resourceName); |
294 |
Enumeration<URL> e = cl.getResources(resourceName); |
297 |
HashSet urls = new HashSet(); |
295 |
Set<URL> urls = new HashSet<URL>(); |
298 |
while (e.hasMoreElements ()) { |
296 |
while (e.hasMoreElements ()) { |
299 |
URL url = (URL) e.nextElement(); |
297 |
URL url = e.nextElement(); |
300 |
// Ignore duplicated URLs, necessary because of tests |
298 |
// Ignore duplicated URLs, necessary because of tests |
301 |
if (urls.contains(url)) continue; |
299 |
if (urls.contains(url)) continue; |
302 |
urls.add(url); |
300 |
urls.add(url); |
Lines 325-332
abstract class Lookup implements Context
Link Here
|
325 |
|
323 |
|
326 |
private Object createInstance (String service) { |
324 |
private Object createInstance (String service) { |
327 |
try { |
325 |
try { |
328 |
ClassLoader cl = (ClassLoader) org.openide.util.Lookup. |
326 |
ClassLoader cl = org.openide.util.Lookup.getDefault().lookup(ClassLoader.class); |
329 |
getDefault ().lookup (ClassLoader.class); |
|
|
330 |
String method = null; |
327 |
String method = null; |
331 |
if (service.endsWith("()")) { |
328 |
if (service.endsWith("()")) { |
332 |
int lastdot = service.lastIndexOf('.'); |
329 |
int lastdot = service.lastIndexOf('.'); |
Lines 571-604
abstract class Lookup implements Context
Link Here
|
571 |
* The refreshing is performed under a lock on this list object so that |
568 |
* The refreshing is performed under a lock on this list object so that |
572 |
* clients have consistent data under synchronization on this. |
569 |
* clients have consistent data under synchronization on this. |
573 |
*/ |
570 |
*/ |
574 |
private final class MetaInfLookupList extends LookupList implements Customizer { |
571 |
private final class MetaInfLookupList<T> extends LookupList<T> implements Customizer { |
575 |
|
572 |
|
576 |
private String folder; |
573 |
private String folder; |
577 |
private Class service; |
574 |
private final Class<T> service; |
578 |
private List<PropertyChangeListener> propertyChangeListeners; |
575 |
private List<PropertyChangeListener> propertyChangeListeners; |
579 |
public int notifyLoadOrder = 0; |
576 |
public int notifyLoadOrder = 0; |
580 |
public int notifyUnloadOrder = 0; |
577 |
public int notifyUnloadOrder = 0; |
581 |
|
578 |
|
582 |
public MetaInfLookupList(String folder, Class service) { |
579 |
public MetaInfLookupList(String folder, Class<T> service) { |
583 |
this(list (folder, service)); |
580 |
this(list(folder, service), service); |
584 |
this.folder = folder; |
581 |
this.folder = folder; |
585 |
this.service = service; |
|
|
586 |
} |
582 |
} |
587 |
|
583 |
|
588 |
private MetaInfLookupList(List l) { |
584 |
private MetaInfLookupList(List<String> l, Class<T> service) { |
589 |
this(l, getHiddenClassNames(l)); |
585 |
this(l, getHiddenClassNames(l), service); |
590 |
} |
586 |
} |
591 |
|
587 |
|
592 |
private MetaInfLookupList(List l, Set<String> s) { |
588 |
private MetaInfLookupList(List<String> l, Set<String> s, Class<T> service) { |
593 |
super(s); |
589 |
super(s); |
|
|
590 |
assert service != null; |
591 |
this.service = service; |
594 |
fillInstances(l, s); |
592 |
fillInstances(l, s); |
595 |
listenOnDisabledModules(); |
593 |
listenOnDisabledModules(); |
596 |
} |
594 |
} |
597 |
|
595 |
|
598 |
private void fillInstances(List l, Set<String> s) { |
596 |
private void fillInstances(List<String> l, Set<String> s) { |
599 |
int i, k = l.size (); |
597 |
for (String className : l) { |
600 |
for (i = 0; i < k; i++) { |
|
|
601 |
String className = (String) l.get (i); |
602 |
if (className.endsWith(HIDDEN)) continue; |
598 |
if (className.endsWith(HIDDEN)) continue; |
603 |
if (s != null && s.contains (className)) continue; |
599 |
if (s != null && s.contains (className)) continue; |
604 |
Object instance = null; |
600 |
Object instance = null; |
Lines 610-616
abstract class Lookup implements Context
Link Here
|
610 |
} |
606 |
} |
611 |
} |
607 |
} |
612 |
if (instance != null) { |
608 |
if (instance != null) { |
613 |
add (instance, className); |
609 |
try { |
|
|
610 |
add(service.cast(instance), className); |
611 |
} catch (ClassCastException cce) { |
612 |
Logger.getLogger(Lookup.class.getName()).log(Level.WARNING, null, cce); |
613 |
} |
614 |
listenOn(instance.getClass().getClassLoader()); |
614 |
listenOn(instance.getClass().getClassLoader()); |
615 |
} |
615 |
} |
616 |
} |
616 |
} |
Lines 620-626
abstract class Lookup implements Context
Link Here
|
620 |
// Perform changes under a lock so that iterators reading this list |
620 |
// Perform changes under a lock so that iterators reading this list |
621 |
// can sync on it |
621 |
// can sync on it |
622 |
clear(); |
622 |
clear(); |
623 |
List l = list (folder, service); |
623 |
List<String> l = list(folder, service); |
624 |
Set<String> s = getHiddenClassNames(l); |
624 |
Set<String> s = getHiddenClassNames(l); |
625 |
hiddenClassNames = s; |
625 |
hiddenClassNames = s; |
626 |
fillInstances(l, s); |
626 |
fillInstances(l, s); |
Lines 686-709
abstract class Lookup implements Context
Link Here
|
686 |
* A special List implementation, which ensures that hidden elements |
686 |
* A special List implementation, which ensures that hidden elements |
687 |
* are removed when adding items into the list. |
687 |
* are removed when adding items into the list. |
688 |
*/ |
688 |
*/ |
689 |
private static class LookupList extends ArrayList<Object> { |
689 |
private static class LookupList<T> extends ArrayList<T> { |
690 |
|
690 |
|
691 |
protected Set<String> hiddenClassNames; |
691 |
protected Set<String> hiddenClassNames; |
692 |
private LinkedHashMap<Object, String> instanceClassNames = new LinkedHashMap<Object, String>(); |
692 |
private LinkedHashMap<T, String> instanceClassNames = new LinkedHashMap<T, String>(); |
693 |
|
693 |
|
694 |
public LookupList(Set<String> hiddenClassNames) { |
694 |
public LookupList(Set<String> hiddenClassNames) { |
695 |
this.hiddenClassNames = hiddenClassNames; |
695 |
this.hiddenClassNames = hiddenClassNames; |
696 |
} |
696 |
} |
697 |
|
697 |
|
698 |
void add(Object instance, String className) { |
698 |
void add(T instance, String className) { |
699 |
super.add(instance); |
699 |
super.add(instance); |
700 |
instanceClassNames.put(instance, className); |
700 |
instanceClassNames.put(instance, className); |
701 |
} |
701 |
} |
702 |
|
702 |
|
703 |
@Override |
703 |
@Override |
704 |
public boolean addAll(Collection c) { |
704 |
public boolean addAll(Collection<? extends T> c) { |
705 |
if (c instanceof LookupList) { |
705 |
if (c instanceof LookupList) { |
706 |
LookupList ll = (LookupList) c; |
706 |
@SuppressWarnings("unchecked") // XXX possible to remove using more clever pattern with Class.cast |
|
|
707 |
LookupList<? extends T> ll = (LookupList<? extends T>) c; |
707 |
synchronized (ll) { |
708 |
synchronized (ll) { |
708 |
synchronized (this) { |
709 |
synchronized (this) { |
709 |
Set<String> newHiddenClassNames = ll.hiddenClassNames; |
710 |
Set<String> newHiddenClassNames = ll.hiddenClassNames; |
Lines 731-738
abstract class Lookup implements Context
Link Here
|
731 |
} |
732 |
} |
732 |
ensureCapacity(size() + ll.size()); |
733 |
ensureCapacity(size() + ll.size()); |
733 |
boolean addedAnything = false; |
734 |
boolean addedAnything = false; |
734 |
for (Iterator it = ll.iterator(); it.hasNext(); ) { |
735 |
for (T instance : ll) { |
735 |
Object instance = it.next(); |
|
|
736 |
String className = ll.instanceClassNames.get(instance); |
736 |
String className = ll.instanceClassNames.get(instance); |
737 |
if (hiddenClassNames == null || !hiddenClassNames.contains(className)) { |
737 |
if (hiddenClassNames == null || !hiddenClassNames.contains(className)) { |
738 |
add(instance, className); |
738 |
add(instance, className); |