Lines 53-59
Link Here
|
53 |
// empty result |
53 |
// empty result |
54 |
return Lookup.EMPTY.lookup (template); |
54 |
return Lookup.EMPTY.lookup (template); |
55 |
} |
55 |
} |
56 |
return new R (delegate.lookup (template)); |
56 |
return new R (template.getType (), delegate.lookup (template)); |
57 |
} |
57 |
} |
58 |
|
58 |
|
59 |
public Object lookup(Class clazz) { |
59 |
public Object lookup(Class clazz) { |
Lines 62-92
Link Here
|
62 |
} |
62 |
} |
63 |
|
63 |
|
64 |
Object res = delegate.lookup (clazz); |
64 |
Object res = delegate.lookup (clazz); |
65 |
if (res == null) { |
65 |
if (isObjectAccessible (clazz, res, 0)) { |
|
|
66 |
return res; |
67 |
} else { |
66 |
return null; |
68 |
return null; |
67 |
} |
69 |
} |
68 |
|
|
|
69 |
Class[] arr = classes(); |
70 |
for (int i = 0; i < arr.length; i++) { |
71 |
if (arr[i].isInstance (res)) { |
72 |
return null; |
73 |
} |
74 |
} |
75 |
return res; |
76 |
} |
70 |
} |
77 |
|
71 |
|
78 |
public org.openide.util.Lookup.Item lookupItem (org.openide.util.Lookup.Template template) { |
72 |
public org.openide.util.Lookup.Item lookupItem (org.openide.util.Lookup.Template template) { |
|
|
73 |
if (areSubclassesOfThisClassAlwaysExcluded (template.getType ())) { |
74 |
return null; |
75 |
} |
79 |
org.openide.util.Lookup.Item retValue = delegate.lookupItem (template); |
76 |
org.openide.util.Lookup.Item retValue = delegate.lookupItem (template); |
80 |
if (retValue == null) return null; |
77 |
if (isObjectAccessible (template.getType (), retValue, 2)) { |
81 |
|
78 |
return retValue; |
82 |
Class[] arr = classes(); |
79 |
} else { |
83 |
for (int i = 0; i < arr.length; i++) { |
80 |
return null; |
84 |
if (acceptFilter (arr[i], retValue, 2)) { |
|
|
85 |
return null; |
86 |
} |
87 |
} |
81 |
} |
88 |
|
|
|
89 |
return retValue; |
90 |
} |
82 |
} |
91 |
|
83 |
|
92 |
/** @return true if the instance of class c shall never be returned from this lookup |
84 |
/** @return true if the instance of class c shall never be returned from this lookup |
Lines 103-109
Link Here
|
103 |
|
95 |
|
104 |
/** Returns the array of classes this lookup filters. |
96 |
/** Returns the array of classes this lookup filters. |
105 |
*/ |
97 |
*/ |
106 |
private Class[] classes () { |
98 |
final Class[] classes () { |
107 |
if (classes instanceof Class[]) { |
99 |
if (classes instanceof Class[]) { |
108 |
return (Class[])classes; |
100 |
return (Class[])classes; |
109 |
} else { |
101 |
} else { |
Lines 111-125
Link Here
|
111 |
} |
103 |
} |
112 |
} |
104 |
} |
113 |
|
105 |
|
|
|
106 |
/** Does a check whether two classes are accessible (in the super/sub class) |
107 |
* releation ship without walking thru any of the classes mentioned in the |
108 |
* barrier. |
109 |
*/ |
110 |
private static boolean isAccessible (Class[] barriers, Class from, Class to) { |
111 |
if (to == null || !from.isAssignableFrom (to)) { |
112 |
// no way to reach each other by walking up |
113 |
return false; |
114 |
} |
115 |
|
116 |
for (int i = 0; i < barriers.length; i++) { |
117 |
if (to == barriers[i]) { |
118 |
return false; |
119 |
} |
120 |
} |
121 |
|
122 |
if (from == to) { |
123 |
return true; |
124 |
} |
125 |
|
126 |
// |
127 |
// depth first search |
128 |
// |
129 |
|
130 |
if (isAccessible (barriers, from, to.getSuperclass ())) { |
131 |
return true; |
132 |
} |
133 |
|
134 |
Class[] interfaces = to.getInterfaces (); |
135 |
for (int i = 0; i < interfaces.length; i++) { |
136 |
if (isAccessible (barriers, from, interfaces[i])) { |
137 |
return true; |
138 |
} |
139 |
} |
140 |
|
141 |
return false; |
142 |
} |
143 |
|
114 |
/** based on type decides whether the class accepts or not anObject |
144 |
/** based on type decides whether the class accepts or not anObject |
|
|
145 |
* @param from the base type of the query |
146 |
* @param to depending on value of type either Object, Class or Item |
147 |
* @param type 0,1,2 for Object, Class or Item |
148 |
* @return true if we can access the to from from by walking around the bariers |
115 |
*/ |
149 |
*/ |
116 |
static boolean acceptFilter (Class filter, Object anObject, int type) { |
150 |
private final boolean isObjectAccessible (Class from, Object to, int type) { |
|
|
151 |
if (to == null) { |
152 |
return false; |
153 |
} |
154 |
return isObjectAccessible (classes(), from, to, type); |
155 |
} |
156 |
|
157 |
/** based on type decides whether the class accepts or not anObject |
158 |
* @param barriers classes to avoid when testing reachability |
159 |
* @param from the base type of the query |
160 |
* @param to depending on value of type either Object, Class or Item |
161 |
* @param type 0,1,2 for Object, Class or Item |
162 |
* @return true if we can access the to from from by walking around the bariers |
163 |
*/ |
164 |
static final boolean isObjectAccessible (Class[] barriers, Class from, Object to, int type) { |
165 |
if (to == null) { |
166 |
return false; |
167 |
} |
168 |
|
117 |
switch (type) { |
169 |
switch (type) { |
118 |
case 0: return filter.isInstance (anObject); |
170 |
case 0: return isAccessible (barriers, from, to.getClass ()); |
119 |
case 1: return filter.isAssignableFrom ((Class)anObject); |
171 |
case 1: return isAccessible (barriers, from, (Class)to); |
120 |
case 2: { |
172 |
case 2: { |
121 |
Item item = (Item)anObject; |
173 |
Item item = (Item)to; |
122 |
return filter.isAssignableFrom (item.getType ()); |
174 |
return isAccessible (barriers, from, item.getType ()); |
123 |
} |
175 |
} |
124 |
default: throw new IllegalStateException ("Type: " + type); |
176 |
default: throw new IllegalStateException ("Type: " + type); |
125 |
} |
177 |
} |
Lines 127-153
Link Here
|
127 |
|
179 |
|
128 |
/** Filters collection accroding to set of given filters. |
180 |
/** Filters collection accroding to set of given filters. |
129 |
*/ |
181 |
*/ |
130 |
static java.util.Collection filter (Class[] arr, java.util.Collection c, int type) { |
182 |
final java.util.Collection filter (Class[] arr, Class from, java.util.Collection c, int type) { |
131 |
java.util.Collection ret = null; |
183 |
java.util.Collection ret = null; |
132 |
|
184 |
|
|
|
185 |
// optimistic strategy expecting we will not need to filter |
133 |
TWICE: for (;;) { |
186 |
TWICE: for (;;) { |
134 |
Iterator it = c.iterator (); |
187 |
Iterator it = c.iterator (); |
135 |
BIG: while (it.hasNext ()) { |
188 |
BIG: while (it.hasNext ()) { |
136 |
Object res = it.next (); |
189 |
Object res = it.next (); |
137 |
for (int i = 0; i < arr.length; i++) { |
190 |
if (!isObjectAccessible (arr, from, res, type)) { |
138 |
if (acceptFilter (arr[i], res, type)) { |
191 |
if (ret == null) { |
139 |
if (ret == null) { |
192 |
// we need to restart the scanning again |
140 |
// we need to restart the scanning again |
193 |
// as there is an active filter |
141 |
// as there is an active filter |
194 |
if (type == 1) { |
142 |
if (type == 1) { |
195 |
ret = new java.util.HashSet (); |
143 |
ret = new java.util.HashSet (); |
196 |
} else { |
144 |
} else { |
197 |
ret = new ArrayList (c.size ()); |
145 |
ret = new ArrayList (c.size ()); |
|
|
146 |
} |
147 |
continue TWICE; |
148 |
} |
198 |
} |
149 |
continue BIG; |
199 |
continue TWICE; |
150 |
} |
200 |
} |
|
|
201 |
continue BIG; |
151 |
} |
202 |
} |
152 |
if (ret != null) { |
203 |
if (ret != null) { |
153 |
// if we are running the second round from TWICE |
204 |
// if we are running the second round from TWICE |
Lines 167-174
Link Here
|
167 |
private final class R extends WaitableResult implements LookupListener { |
218 |
private final class R extends WaitableResult implements LookupListener { |
168 |
private Result result; |
219 |
private Result result; |
169 |
private Object listeners; |
220 |
private Object listeners; |
|
|
221 |
private Class from; |
170 |
|
222 |
|
171 |
R (Result delegate) { |
223 |
R (Class from, Result delegate) { |
|
|
224 |
this.from = from; |
172 |
this.result = delegate; |
225 |
this.result = delegate; |
173 |
} |
226 |
} |
174 |
|
227 |
|
Lines 201-215
Link Here
|
201 |
} |
254 |
} |
202 |
|
255 |
|
203 |
public java.util.Collection allInstances() { |
256 |
public java.util.Collection allInstances() { |
204 |
return filter (classes (), result.allInstances (), 0); |
257 |
return filter (classes (), from, result.allInstances (), 0); |
205 |
} |
258 |
} |
206 |
|
259 |
|
207 |
public Set allClasses () { |
260 |
public Set allClasses () { |
208 |
return (Set)filter (classes (), result.allClasses (), 1); |
261 |
return (Set)filter (classes (), from, result.allClasses (), 1); |
209 |
} |
262 |
} |
210 |
|
263 |
|
211 |
public Collection allItems () { |
264 |
public Collection allItems () { |
212 |
return filter (classes (), result.allItems (), 2); |
265 |
return filter (classes (), from, result.allItems (), 2); |
213 |
} |
266 |
} |
214 |
|
267 |
|
215 |
public void resultChanged (org.openide.util.LookupEvent ev) { |
268 |
public void resultChanged (org.openide.util.LookupEvent ev) { |