jtulach@9
|
1 |
/*
|
jtulach@302
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
jtulach@189
|
3 |
*
|
mzlamal@829
|
4 |
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
|
jtulach@189
|
5 |
*
|
jtulach@302
|
6 |
* The contents of this file are subject to the terms of either the GNU
|
jtulach@302
|
7 |
* General Public License Version 2 only ("GPL") or the Common
|
jtulach@302
|
8 |
* Development and Distribution License("CDDL") (collectively, the
|
jtulach@302
|
9 |
* "License"). You may not use this file except in compliance with the
|
jtulach@302
|
10 |
* License. You can obtain a copy of the License at
|
jtulach@302
|
11 |
* http://www.netbeans.org/cddl-gplv2.html
|
jtulach@302
|
12 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
|
jtulach@302
|
13 |
* specific language governing permissions and limitations under the
|
jtulach@302
|
14 |
* License. When distributing the software, include this License Header
|
jtulach@302
|
15 |
* Notice in each file and include the License file at
|
jtulach@302
|
16 |
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
|
jtulach@302
|
17 |
* particular file as subject to the "Classpath" exception as provided
|
jtulach@302
|
18 |
* by Sun in the GPL Version 2 section of the License file that
|
jtulach@302
|
19 |
* accompanied this code. If applicable, add the following below the
|
jtulach@302
|
20 |
* License Header, with the fields enclosed by brackets [] replaced by
|
jtulach@302
|
21 |
* your own identifying information:
|
jtulach@189
|
22 |
* "Portions Copyrighted [year] [name of copyright owner]"
|
jtulach@189
|
23 |
*
|
jtulach@302
|
24 |
* Contributor(s):
|
jtulach@302
|
25 |
*
|
jtulach@189
|
26 |
* The Original Software is NetBeans. The Initial Developer of the Original
|
jtulach@189
|
27 |
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
|
jtulach@9
|
28 |
* Microsystems, Inc. All Rights Reserved.
|
jtulach@302
|
29 |
*
|
jtulach@302
|
30 |
* If you wish your version of this file to be governed by only the CDDL
|
jtulach@302
|
31 |
* or only the GPL Version 2, indicate your decision by adding
|
jtulach@302
|
32 |
* "[Contributor] elects to include this software in this distribution
|
jtulach@302
|
33 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a
|
jtulach@302
|
34 |
* single choice of license, a recipient has the option to distribute
|
jtulach@302
|
35 |
* your version of this file under either the CDDL, the GPL Version 2 or
|
jtulach@302
|
36 |
* to extend the choice of license to its licensees as provided above.
|
jtulach@302
|
37 |
* However, if you add GPL Version 2 code and therefore, elected the GPL
|
jtulach@302
|
38 |
* Version 2 license, then the option applies only if the new code is
|
jtulach@302
|
39 |
* made subject to such option by the copyright holder.
|
jtulach@9
|
40 |
*/
|
jtulach@9
|
41 |
|
jtulach@9
|
42 |
package org.openide.util.lookup;
|
jtulach@9
|
43 |
|
jtulach@545
|
44 |
import java.util.concurrent.ExecutionException;
|
jtulach@9
|
45 |
|
jtulach@9
|
46 |
import java.lang.ref.WeakReference;
|
jtulach@9
|
47 |
import java.util.*;
|
jtulach@545
|
48 |
import java.util.concurrent.Executors;
|
jtulach@545
|
49 |
import java.util.concurrent.TimeUnit;
|
jtulach@9
|
50 |
import org.netbeans.junit.*;
|
jtulach@550
|
51 |
import org.openide.util.Lookup;
|
jtulach@359
|
52 |
import org.openide.util.lookup.AbstractLookup.Pair;
|
jtulach@9
|
53 |
|
jglick@833
|
54 |
@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
|
jtulach@9
|
55 |
public class AbstractLookupTest extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
|
jtulach@9
|
56 |
public AbstractLookupTest(java.lang.String testName) {
|
jtulach@9
|
57 |
super(testName, null);
|
jtulach@9
|
58 |
}
|
jtulach@189
|
59 |
|
jtulach@189
|
60 |
//
|
jtulach@9
|
61 |
// Impl of AbstractLookupBaseHid.Impl
|
jtulach@189
|
62 |
//
|
jtulach@189
|
63 |
|
jtulach@9
|
64 |
/** Creates the initial abstract lookup.
|
jtulach@9
|
65 |
*/
|
jtulach@9
|
66 |
public Lookup createInstancesLookup (InstanceContent ic) {
|
jtulach@9
|
67 |
return new AbstractLookup (ic, new InheritanceTree ());
|
jtulach@9
|
68 |
}
|
jtulach@9
|
69 |
|
jtulach@9
|
70 |
/** Creates an lookup for given lookup. This class just returns
|
jtulach@9
|
71 |
* the object passed in, but subclasses can be different.
|
jtulach@9
|
72 |
* @param lookup in lookup
|
jtulach@9
|
73 |
* @return a lookup to use
|
jtulach@9
|
74 |
*/
|
jtulach@9
|
75 |
public Lookup createLookup (Lookup lookup) {
|
jtulach@9
|
76 |
return lookup;
|
jtulach@9
|
77 |
}
|
jtulach@9
|
78 |
|
jtulach@9
|
79 |
public void clearCaches () {
|
jtulach@9
|
80 |
}
|
jtulach@9
|
81 |
|
jtulach@9
|
82 |
public static void main(java.lang.String[] args) {
|
jtulach@9
|
83 |
junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupTest.class));
|
jtulach@9
|
84 |
}
|
jtulach@9
|
85 |
|
jtulach@9
|
86 |
static class LkpResultCanBeGargageCollectedAndClearsTheResult extends AbstractLookup {
|
jtulach@9
|
87 |
public int cleared;
|
jtulach@9
|
88 |
public int dirty;
|
jtulach@9
|
89 |
|
jglick@833
|
90 |
synchronized @Override boolean cleanUpResult(Template t) {
|
jtulach@9
|
91 |
boolean res = super.cleanUpResult (t);
|
jtulach@9
|
92 |
if (res) {
|
jtulach@9
|
93 |
cleared++;
|
jtulach@9
|
94 |
} else {
|
jtulach@9
|
95 |
dirty++;
|
jtulach@9
|
96 |
}
|
jtulach@9
|
97 |
|
jtulach@9
|
98 |
notifyAll ();
|
jtulach@9
|
99 |
|
jtulach@9
|
100 |
return res;
|
jtulach@9
|
101 |
}
|
jtulach@9
|
102 |
}
|
jtulach@9
|
103 |
public void testResultCanBeGargageCollectedAndClearsTheResult () throws Exception {
|
jtulach@9
|
104 |
LkpResultCanBeGargageCollectedAndClearsTheResult lkp = new LkpResultCanBeGargageCollectedAndClearsTheResult ();
|
jtulach@9
|
105 |
assertSize ("24 for AbstractLookup, 8 for two ints", 32, lkp);
|
jtulach@9
|
106 |
synchronized (lkp) {
|
jtulach@9
|
107 |
Lookup.Result res = lkp.lookup (new Lookup.Template (getClass ()));
|
jtulach@9
|
108 |
res.allItems();
|
jtulach@9
|
109 |
|
jtulach@9
|
110 |
WeakReference ref = new WeakReference (res);
|
jtulach@9
|
111 |
res = null;
|
jtulach@9
|
112 |
assertGC ("Reference can get cleared", ref);
|
jtulach@9
|
113 |
|
jtulach@9
|
114 |
// wait till we
|
jtulach@9
|
115 |
while (lkp.cleared == 0 && lkp.dirty == 0) {
|
jtulach@9
|
116 |
lkp.wait ();
|
jtulach@9
|
117 |
}
|
jtulach@9
|
118 |
|
jtulach@9
|
119 |
assertEquals ("No dirty cleanups", 0, lkp.dirty);
|
jtulach@9
|
120 |
assertEquals ("One final cleanup", 1, lkp.cleared);
|
jtulach@9
|
121 |
}
|
jtulach@9
|
122 |
//assertSize ("Everything has been cleaned to original size", 32, lkp);
|
jtulach@9
|
123 |
|
jtulach@9
|
124 |
}
|
jtulach@9
|
125 |
|
jtulach@9
|
126 |
public void testPairCannotBeUsedInMoreThanOneLookupAtOnce () throws Exception {
|
jtulach@9
|
127 |
/** Simple pair with no data */
|
jtulach@9
|
128 |
class EmptyPair extends AbstractLookup.Pair {
|
jtulach@9
|
129 |
protected boolean creatorOf(Object obj) { return false; }
|
jtulach@9
|
130 |
public String getDisplayName() { return "Empty"; }
|
jtulach@9
|
131 |
public String getId() { return "empty"; }
|
jtulach@9
|
132 |
public Object getInstance() { return null; }
|
jtulach@9
|
133 |
public Class getType() { return Object.class; }
|
jtulach@9
|
134 |
protected boolean instanceOf(Class c) { return c == getType (); }
|
jtulach@9
|
135 |
} // end of EmptyPair
|
jtulach@9
|
136 |
|
jtulach@9
|
137 |
AbstractLookup.Content c1 = new AbstractLookup.Content ();
|
jtulach@9
|
138 |
AbstractLookup.Content c2 = new AbstractLookup.Content ();
|
jtulach@9
|
139 |
AbstractLookup l1 = new AbstractLookup (c1);
|
jtulach@9
|
140 |
AbstractLookup l2 = new AbstractLookup (c2);
|
jtulach@9
|
141 |
|
jtulach@9
|
142 |
EmptyPair empty = new EmptyPair ();
|
jtulach@9
|
143 |
c1.addPair (empty);
|
jtulach@9
|
144 |
Lookup.Result res = l1.lookup (new Lookup.Template (Object.class));
|
jtulach@9
|
145 |
assertEquals (
|
jtulach@9
|
146 |
"Pair is really found", empty,
|
jtulach@9
|
147 |
res.allItems ().iterator().next ()
|
jtulach@9
|
148 |
);
|
jtulach@9
|
149 |
try {
|
jtulach@9
|
150 |
c2.addPair (empty);
|
jtulach@9
|
151 |
fail ("It should not be possible to add pair to two lookups");
|
jtulach@9
|
152 |
} catch (IllegalStateException ex) {
|
jtulach@9
|
153 |
// ok, exception is fine
|
jtulach@9
|
154 |
}
|
jtulach@9
|
155 |
assertEquals (
|
jtulach@9
|
156 |
"L2 is still empty", Collections.EMPTY_LIST,
|
jtulach@9
|
157 |
new ArrayList (l2.lookup (new Lookup.Template (Object.class)).allItems ())
|
jtulach@9
|
158 |
);
|
jtulach@9
|
159 |
}
|
jtulach@9
|
160 |
|
jtulach@9
|
161 |
public void testInitializationCanBeDoneFromAnotherThread () {
|
jtulach@9
|
162 |
class MyLkp extends AbstractLookup implements Runnable {
|
jtulach@9
|
163 |
private InstanceContent ic;
|
jtulach@9
|
164 |
private boolean direct;
|
jtulach@9
|
165 |
|
jtulach@9
|
166 |
public MyLkp (boolean direct) {
|
jtulach@9
|
167 |
this (direct, new InstanceContent ());
|
jtulach@9
|
168 |
}
|
jtulach@9
|
169 |
|
jtulach@9
|
170 |
private MyLkp (boolean direct, InstanceContent ic) {
|
jtulach@9
|
171 |
super (ic);
|
jtulach@9
|
172 |
this.direct = direct;
|
jtulach@9
|
173 |
this.ic = ic;
|
jtulach@9
|
174 |
}
|
jtulach@9
|
175 |
|
jglick@833
|
176 |
protected @Override void initialize() {
|
jtulach@9
|
177 |
if (direct) {
|
jtulach@9
|
178 |
run ();
|
jtulach@9
|
179 |
} else {
|
jtulach@545
|
180 |
try {
|
jtulach@545
|
181 |
Executors.newSingleThreadScheduledExecutor().schedule(this, 0, TimeUnit.MICROSECONDS).get();
|
jtulach@545
|
182 |
} catch (InterruptedException ex) {
|
jtulach@545
|
183 |
ex.printStackTrace();
|
jtulach@545
|
184 |
} catch (ExecutionException ex) {
|
jtulach@545
|
185 |
ex.printStackTrace();
|
jtulach@545
|
186 |
}
|
jtulach@9
|
187 |
}
|
jtulach@9
|
188 |
}
|
jtulach@9
|
189 |
|
jtulach@9
|
190 |
public void run () {
|
jtulach@9
|
191 |
ic.add (this);
|
jtulach@9
|
192 |
ic.remove (this);
|
jtulach@9
|
193 |
ic.set (Collections.nCopies(10, this), null);
|
jtulach@9
|
194 |
ic.set (Collections.EMPTY_LIST, null);
|
jtulach@9
|
195 |
ic.add (AbstractLookupTest.this);
|
jtulach@9
|
196 |
}
|
jtulach@9
|
197 |
}
|
jtulach@9
|
198 |
|
jtulach@9
|
199 |
assertEquals ("The test should be there", this, new MyLkp (true).lookup (Object.class));
|
jtulach@9
|
200 |
assertEquals ("and in async mode as well", this, new MyLkp (false).lookup (Object.class));
|
jtulach@9
|
201 |
}
|
jtulach@9
|
202 |
|
jtulach@9
|
203 |
public void testBeforeLookupIsCalled () {
|
jtulach@9
|
204 |
class BeforeL extends AbstractLookup {
|
jtulach@9
|
205 |
public ArrayList list = new ArrayList ();
|
jtulach@9
|
206 |
public String toAdd;
|
jtulach@9
|
207 |
public InstanceContent ic;
|
jtulach@9
|
208 |
|
jtulach@9
|
209 |
public BeforeL () {
|
jtulach@9
|
210 |
this (new InstanceContent ());
|
jtulach@9
|
211 |
}
|
jtulach@9
|
212 |
|
jtulach@9
|
213 |
private BeforeL (InstanceContent c) {
|
jtulach@9
|
214 |
super (c);
|
jtulach@9
|
215 |
this.ic = c;
|
jtulach@9
|
216 |
}
|
jtulach@9
|
217 |
|
jglick@833
|
218 |
protected @Override void beforeLookup(Template t) {
|
jtulach@9
|
219 |
if (toAdd != null) {
|
jtulach@9
|
220 |
list.add (0, new SerialPair (toAdd));
|
jtulach@9
|
221 |
setPairs (list);
|
jtulach@9
|
222 |
} else {
|
jtulach@9
|
223 |
ic.add (new Integer (1));
|
jtulach@9
|
224 |
}
|
jtulach@9
|
225 |
}
|
jtulach@9
|
226 |
}
|
jtulach@9
|
227 |
|
jtulach@9
|
228 |
BeforeL lookup = new BeforeL ();
|
jtulach@9
|
229 |
|
jtulach@9
|
230 |
lookup.toAdd = "First";
|
jtulach@9
|
231 |
assertEquals ("First if found", "First", lookup.lookup (String.class));
|
jtulach@9
|
232 |
|
jtulach@9
|
233 |
lookup.toAdd = "2";
|
jtulach@9
|
234 |
assertEquals ("2 is not first", "2", lookup.lookup (String.class));
|
jtulach@9
|
235 |
|
jtulach@9
|
236 |
Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
|
jtulach@9
|
237 |
for (int i = 3; i < 20; i++) {
|
jtulach@9
|
238 |
lookup.toAdd = String.valueOf (i);
|
jtulach@9
|
239 |
assertEquals (i + " items are now there", i, res.allInstances ().size ());
|
jtulach@9
|
240 |
}
|
jtulach@9
|
241 |
for (int i = 20; i < 35; i++) {
|
jtulach@9
|
242 |
lookup.toAdd = String.valueOf (i);
|
jtulach@9
|
243 |
assertEquals (i + " items are now there", i, res.allItems ().size ());
|
jtulach@9
|
244 |
}
|
jtulach@9
|
245 |
|
jtulach@9
|
246 |
assertEquals ("Just strings are there now", 1, res.allClasses ().size ());
|
jtulach@9
|
247 |
lookup.toAdd = null; // this will add integer
|
jtulach@9
|
248 |
assertEquals ("Two classes now", 2, res.allClasses ().size ());
|
jtulach@9
|
249 |
}
|
jtulach@130
|
250 |
|
jtulach@130
|
251 |
public void testInconsistentAfterDeserIssue71744() throws Exception {
|
jtulach@130
|
252 |
InheritanceTree inhTree = new InheritanceTree();
|
jtulach@130
|
253 |
|
jtulach@130
|
254 |
AbstractLookup al = new AbstractLookup(new AbstractLookup.Content(), inhTree);
|
jtulach@130
|
255 |
{
|
jtulach@130
|
256 |
|
jtulach@130
|
257 |
Collection r = al.lookup(new Lookup.Template(Integer.class)).allInstances();
|
jtulach@130
|
258 |
assertEquals("None", 0, r.size());
|
jtulach@130
|
259 |
}
|
jtulach@130
|
260 |
|
jtulach@130
|
261 |
ICP item = new ICP(new Integer(10));
|
jtulach@130
|
262 |
al.addPair(item);
|
jtulach@130
|
263 |
al.removePair(item);
|
jtulach@130
|
264 |
|
jtulach@551
|
265 |
AbstractLookup newLookup = (AbstractLookup)reserialize(al);
|
jtulach@130
|
266 |
|
jtulach@130
|
267 |
newLookup.lookup(Number.class);
|
jtulach@130
|
268 |
|
jtulach@130
|
269 |
|
jtulach@130
|
270 |
newLookup.addPair(new ICP(new Long(20)));
|
jtulach@130
|
271 |
|
jtulach@130
|
272 |
{
|
jtulach@130
|
273 |
|
jtulach@130
|
274 |
Collection r = newLookup.lookup(new Lookup.Template(Number.class)).allInstances();
|
jtulach@130
|
275 |
assertEquals("one", 1, r.size());
|
jtulach@130
|
276 |
/*
|
jtulach@130
|
277 |
Iterator it = r.iterator();
|
jtulach@130
|
278 |
assertEquals(new Integer(10), it.next());
|
jtulach@130
|
279 |
assertEquals(new Long(20), it.next());*/
|
jtulach@130
|
280 |
}
|
jtulach@130
|
281 |
}
|
jtulach@130
|
282 |
|
jtulach@359
|
283 |
public void testMatchesIssue130673() {
|
jtulach@359
|
284 |
class BrokenPairReturningNullID extends Pair<Object> {
|
jtulach@359
|
285 |
@Override
|
jtulach@359
|
286 |
protected boolean instanceOf(Class<?> c) {
|
jtulach@359
|
287 |
return false;
|
jtulach@359
|
288 |
}
|
jtulach@359
|
289 |
|
jtulach@359
|
290 |
@Override
|
jtulach@359
|
291 |
protected boolean creatorOf(Object obj) {
|
jtulach@359
|
292 |
return false;
|
jtulach@359
|
293 |
}
|
jtulach@359
|
294 |
|
jtulach@359
|
295 |
@Override
|
jtulach@359
|
296 |
public Object getInstance() {
|
jtulach@359
|
297 |
return null;
|
jtulach@359
|
298 |
}
|
jtulach@359
|
299 |
|
jtulach@359
|
300 |
@Override
|
jtulach@359
|
301 |
public Class<? extends Object> getType() {
|
jtulach@359
|
302 |
return null;
|
jtulach@359
|
303 |
}
|
jtulach@359
|
304 |
|
jtulach@359
|
305 |
@Override
|
jtulach@359
|
306 |
public String getId() {
|
jtulach@359
|
307 |
return null;
|
jtulach@359
|
308 |
}
|
jtulach@359
|
309 |
|
jtulach@359
|
310 |
@Override
|
jtulach@359
|
311 |
public String getDisplayName() {
|
jtulach@359
|
312 |
return null;
|
jtulach@359
|
313 |
}
|
jtulach@359
|
314 |
}
|
jtulach@359
|
315 |
BrokenPairReturningNullID broken = new BrokenPairReturningNullID();
|
jtulach@359
|
316 |
|
jtulach@359
|
317 |
|
jtulach@359
|
318 |
Lookup.Template<String> t = new Lookup.Template<String>(String.class, "ID", null);
|
jtulach@359
|
319 |
boolean not = AbstractLookup.matches(t, broken, true);
|
jtulach@359
|
320 |
assertFalse("Does not match the template, but throws no exception", not);
|
jtulach@359
|
321 |
}
|
jtulach@359
|
322 |
|
jtulach@130
|
323 |
private static final class ICP extends AbstractLookup.Pair {
|
jtulach@130
|
324 |
private Number s;
|
jtulach@130
|
325 |
|
jtulach@130
|
326 |
public ICP (Number s) {
|
jtulach@130
|
327 |
this.s = s;
|
jtulach@130
|
328 |
}
|
jtulach@130
|
329 |
|
jtulach@130
|
330 |
|
jtulach@130
|
331 |
protected boolean instanceOf(Class c) {
|
jtulach@130
|
332 |
return c.isInstance(s);
|
jtulach@130
|
333 |
}
|
jtulach@130
|
334 |
|
jtulach@130
|
335 |
protected boolean creatorOf(Object obj) {
|
jtulach@130
|
336 |
return s == obj;
|
jtulach@130
|
337 |
}
|
jtulach@130
|
338 |
|
jtulach@130
|
339 |
public Object getInstance() {
|
jtulach@130
|
340 |
return s;
|
jtulach@130
|
341 |
}
|
jtulach@130
|
342 |
|
jtulach@130
|
343 |
public Class getType() {
|
jtulach@130
|
344 |
return s.getClass();
|
jtulach@130
|
345 |
}
|
jtulach@130
|
346 |
|
jtulach@130
|
347 |
public String getId() {
|
jtulach@130
|
348 |
return s.toString();
|
jtulach@130
|
349 |
}
|
jtulach@130
|
350 |
|
jtulach@130
|
351 |
public String getDisplayName() {
|
jtulach@130
|
352 |
return getId();
|
jtulach@130
|
353 |
}
|
jtulach@130
|
354 |
|
jtulach@130
|
355 |
}
|
jtulach@9
|
356 |
}
|