Merge with default branch separate-lookup-170056
authorJaroslav Tulach <jtulach@netbeans.org>
Mon, 14 Dec 2009 20:58:39 +0100
branchseparate-lookup-170056
changeset 86729040c9b3c97
parent 866 571882a2e8c7
parent 864 589b8a8b8f4c
child 868 82301246576a
Merge with default branch
openide.util.lookup/src/org/netbeans/modules/openide/util/NamedServicesProvider.java
openide.util/src/org/netbeans/modules/openide/util/AbstractServiceProviderProcessor.java
openide.util/src/org/netbeans/modules/openide/util/ActiveQueue.java
openide.util/src/org/netbeans/modules/openide/util/NamedServicesProvider.java
openide.util/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java
openide.util/src/org/openide/util/Lookup.java
openide.util/src/org/openide/util/LookupEvent.java
openide.util/src/org/openide/util/LookupListener.java
openide.util/src/org/openide/util/lookup/ALPairComparator.java
openide.util/src/org/openide/util/lookup/AbstractLookup.java
openide.util/src/org/openide/util/lookup/ArrayStorage.java
openide.util/src/org/openide/util/lookup/DelegatingStorage.java
openide.util/src/org/openide/util/lookup/ExcludingLookup.java
openide.util/src/org/openide/util/lookup/InheritanceTree.java
openide.util/src/org/openide/util/lookup/InstanceContent.java
openide.util/src/org/openide/util/lookup/Lookups.java
openide.util/src/org/openide/util/lookup/MetaInfServicesLookup.java
openide.util/src/org/openide/util/lookup/ProxyLookup.java
openide.util/src/org/openide/util/lookup/ServiceProvider.java
openide.util/src/org/openide/util/lookup/ServiceProviders.java
openide.util/src/org/openide/util/lookup/SimpleLookup.java
openide.util/src/org/openide/util/lookup/SimpleProxyLookup.java
openide.util/src/org/openide/util/lookup/SingletonLookup.java
openide.util/src/org/openide/util/lookup/WaitableResult.java
openide.util/src/org/openide/util/lookup/doc-files/index.html
openide.util/src/org/openide/util/lookup/doc-files/lookup-api.html
openide.util/src/org/openide/util/lookup/doc-files/lookup-spi.html
openide.util/src/org/openide/util/lookup/package.html
openide.util/test/unit/src/org/bar/Comparator2.java
openide.util/test/unit/src/org/bar/Comparator3.java
openide.util/test/unit/src/org/bar/Implementation2.java
openide.util/test/unit/src/org/bar/Iterator2.java
openide.util/test/unit/src/org/foo/Interface.java
openide.util/test/unit/src/org/foo/impl/Comparator1.java
openide.util/test/unit/src/org/foo/impl/Implementation1.java
openide.util/test/unit/src/org/foo/impl/Iterator1.java
openide.util/test/unit/src/org/foo/impl/Runnable1.java
openide.util/test/unit/src/org/netbeans/modules/openide/util/ServiceProviderProcessorTest.java
openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupArrayStorageTest.java
openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupAsynchExecutorTest.java
openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java
openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupExecutorTest.java
openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupMemoryTest.java
openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/InheritanceTreeTest.java
openide.util/test/unit/src/org/openide/util/lookup/InitializationBug44134Test.java
openide.util/test/unit/src/org/openide/util/lookup/KomrskaLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/LookupBugTest.java
openide.util/test/unit/src/org/openide/util/lookup/LookupsProxyTest.java
openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.java
openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.txt
openide.util/test/unit/src/org/openide/util/lookup/NamedServicesLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/PathInLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/PrefixServicesLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/ProxyLookup173975Test.java
openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupEventIssue136866Test.java
openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/SimpleLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/SimpleProxyLookupIssue42244Test.java
openide.util/test/unit/src/org/openide/util/lookup/SimpleProxyLookupSpeedIssue42244Test.java
openide.util/test/unit/src/org/openide/util/lookup/SimpleProxyLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/SingletonLookupTest.java
openide.util/test/unit/src/org/openide/util/lookup/problem100320.txt
openide.util/test/unit/src/org/openide/util/lookup/services-jar-1.txt
openide.util/test/unit/src/org/openide/util/lookup/services-jar-2.txt
openide.util/test/unit/src/org/openide/util/test/AnnotationProcessorTestUtils.java
openide.util/test/unit/src/org/openide/util/test/MockLookup.java
openide.util/test/unit/src/org/openide/util/test/MockLookupTest.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/openide.util.lookup/apichanges.xml	Mon Dec 14 20:58:39 2009 +0100
     1.3 @@ -0,0 +1,448 @@
     1.4 +<?xml version="1.0" encoding="UTF-8"?>
     1.5 +<!--
     1.6 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.7 +
     1.8 +Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
     1.9 +
    1.10 +
    1.11 +The contents of this file are subject to the terms of either the GNU
    1.12 +General Public License Version 2 only ("GPL") or the Common
    1.13 +Development and Distribution License("CDDL") (collectively, the
    1.14 +"License"). You may not use this file except in compliance with the
    1.15 +License. You can obtain a copy of the License at
    1.16 +http://www.netbeans.org/cddl-gplv2.html
    1.17 +or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    1.18 +specific language governing permissions and limitations under the
    1.19 +License.  When distributing the software, include this License Header
    1.20 +Notice in each file and include the License file at
    1.21 +nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    1.22 +particular file as subject to the "Classpath" exception as provided
    1.23 +by Sun in the GPL Version 2 section of the License file that
    1.24 +accompanied this code. If applicable, add the following below the
    1.25 +License Header, with the fields enclosed by brackets [] replaced by
    1.26 +your own identifying information:
    1.27 +"Portions Copyrighted [year] [name of copyright owner]"
    1.28 +
    1.29 +Contributor(s):
    1.30 +
    1.31 +The Original Software is NetBeans. The Initial Developer of the Original
    1.32 +Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
    1.33 +Microsystems, Inc. All Rights Reserved.
    1.34 +
    1.35 +If you wish your version of this file to be governed by only the CDDL
    1.36 +or only the GPL Version 2, indicate your decision by adding
    1.37 +"[Contributor] elects to include this software in this distribution
    1.38 +under the [CDDL or GPL Version 2] license." If you do not indicate a
    1.39 +single choice of license, a recipient has the option to distribute
    1.40 +your version of this file under either the CDDL, the GPL Version 2 or
    1.41 +to extend the choice of license to its licensees as provided above.
    1.42 +However, if you add GPL Version 2 code and therefore, elected the GPL
    1.43 +Version 2 license, then the option applies only if the new code is
    1.44 +made subject to such option by the copyright holder.
    1.45 +-->
    1.46 +<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
    1.47 +<apichanges>
    1.48 +<apidefs>
    1.49 +    <apidef name="lookup">Lookup API</apidef>
    1.50 +</apidefs>
    1.51 +<changes>
    1.52 +    <change id="org.openide.util.Lookup.paths">
    1.53 +        <api name="lookup"/>
    1.54 +        <summary>Added
    1.55 +            <code>org.openide.util.Lookup.paths</code> property
    1.56 +        </summary>
    1.57 +        <version major="7" minor="24"/>
    1.58 +        <date day="19" month="6" year="2009"/>
    1.59 +        <author login="jtulach"/>
    1.60 +        <compatibility addition="yes"/>
    1.61 +        <description>
    1.62 +            <p>
    1.63 +                 Better way to integrate Lookup.getDefault() and system filesystem.
    1.64 +            </p>
    1.65 +        </description>
    1.66 +        <class package="org.openide.util" name="Lookup"/>
    1.67 +        <issue number="166782"/>
    1.68 +    </change>
    1.69 +    <change id="ServiceProvider">
    1.70 +        <api name="lookup"/>
    1.71 +        <summary>Added <code>ServiceProvider</code> annotation</summary>
    1.72 +        <version major="7" minor="20"/>
    1.73 +        <date day="1" month="11" year="2008"/>
    1.74 +        <author login="jglick"/>
    1.75 +        <compatibility addition="yes">
    1.76 +            <p>
    1.77 +                Modules registering services using <code>META-INF/services</code>
    1.78 +                files in the source tree are encouraged to switch to the annotation.
    1.79 +            </p>
    1.80 +        </compatibility>
    1.81 +        <description>
    1.82 +            <p>
    1.83 +                Added annotations <code>ServiceProvider</code> and <code>ServiceProviders</code>
    1.84 +                to simplify registration of global singleton services.
    1.85 +            </p>
    1.86 +        </description>
    1.87 +        <class package="org.openide.util.lookup" name="ServiceProvider"/>
    1.88 +        <class package="org.openide.util.lookup" name="ServiceProviders"/>
    1.89 +        <issue number="150447"/>
    1.90 +    </change>
    1.91 +    <change id="Lookup.asynchronous">
    1.92 +        <api name="lookup"/>
    1.93 +        <summary>AbstractLookup and ProxyLookup fire changes asynchronously</summary>
    1.94 +        <version major="7" minor="16"/>
    1.95 +        <date day="27" month="6" year="2008"/>
    1.96 +        <author login="jtulach"/>
    1.97 +        <compatibility addition="yes" binary="compatible" semantic="compatible"/>
    1.98 +        <description>
    1.99 +            <p>
   1.100 +                All modification methods in <code>AbstractLookup</code> and <code>ProxyLookup</code>
   1.101 +                were extended to accept an 
   1.102 +                <a href="@JDK@/java/util/concurrent/Executor.html">Executor</a>.
   1.103 +                If not null, it is used to dispatch events to listeners sometime
   1.104 +                "later". Also the <code>AbstractLookup.Content</code> 
   1.105 +                and <code>InstanceContent</code> constructors
   1.106 +                have been extended to accept such <code>Executor</code>s.
   1.107 +            </p>
   1.108 +        </description> 
   1.109 +        <class package="org.openide.util.lookup" name="AbstractLookup"/>
   1.110 +        <class package="org.openide.util.lookup" name="ProxyLookup"/>
   1.111 +        <class package="org.openide.util.lookup" name="InstanceContent"/>
   1.112 +        <issue number="134297"/>
   1.113 +    </change>
   1.114 +
   1.115 +    <change id="Lookups.forPath">
   1.116 +        <api name="lookup"/>
   1.117 +        <summary>Added simplified support for named lookups <code>Lookups.forPath</code></summary>
   1.118 +        <version major="7" minor="9"/>
   1.119 +        <date day="17" month="4" year="2007"/>
   1.120 +        <author login="jtulach"/>
   1.121 +        <compatibility addition="yes"/>
   1.122 +        <description>
   1.123 +            <p>
   1.124 +                New method <a href="@TOP@/org/openide/util/lookup/Lookups.html#forPath(java.lang.String)">Lookups.forPath(String)</a>
   1.125 +                has been added to replace now deprecated <a href="@org-openide-loaders@/org/openide/loaders/FolderLookup.html">FolderLookup</a>
   1.126 +                and allow modules who wants to read settings from layers
   1.127 +                to do so with a simpler code, without dependency on DataSystems API.
   1.128 +            </p>
   1.129 +        </description>
   1.130 +        <class package="org.openide.util.lookup" name="Lookups"/>
   1.131 +        <issue number="98426"/>
   1.132 +    </change>
   1.133 +    
   1.134 +    <change id="lookupAll-lookupResult">
   1.135 +        <api name="lookup"/>
   1.136 +        <summary>Convenience methods added to <code>Lookup</code></summary>
   1.137 +        <version major="6" minor="10"/>
   1.138 +        <date day="3" month="4" year="2006"/>
   1.139 +        <author login="jglick"/>
   1.140 +        <compatibility addition="yes" binary="compatible" source="incompatible">
   1.141 +            <p>
   1.142 +                Could conceivably conflict with existing subclass method with same signature
   1.143 +                with different semantics or return type.
   1.144 +            </p>
   1.145 +        </compatibility>
   1.146 +        <description>
   1.147 +            <p>
   1.148 +                Two methods, <code>lookupResult</code> and <code>lookupAll</code>, were
   1.149 +                added to <code>Lookup</code> to encapsulate the most common usage patterns
   1.150 +                with less typing, and more importantly avoiding the need to explicitly
   1.151 +                make a <code>Lookup.Template</code> object.
   1.152 +            </p>
   1.153 +        </description>
   1.154 +        <class package="org.openide.util" name="Lookup"/>
   1.155 +        <issue number="73848"/>
   1.156 +    </change>
   1.157 +    <change id="less-events-from-proxylookup" >
   1.158 +      <api name="lookup"/>
   1.159 +      <summary>Less change notifications from ProxyLookup</summary>
   1.160 +      <version major="6" minor="7"/>
   1.161 +      <date day="11" month="11" year="2005"/>
   1.162 +      <author login="jtulach"/>
   1.163 +      <compatibility addition="no" modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no"/>
   1.164 +      <description>
   1.165 +        <a href="@TOP@/org/openide/util/lookup/ProxyLookup.html">ProxyLookup.setLookups</a>
   1.166 +        used to fire <a href="@TOP@/org/openide/util/LookupEvent.html">LookupEvent</a> every 
   1.167 +        time it was called. Now it always checks whether there was a change to the
   1.168 +        previous state. This will reduce the number of events delivered when a small
   1.169 +        change is made. Also results from both 
   1.170 +        <a href="@TOP@/org/openide/util/lookup/ProxyLookup.html">ProxyLookup</a>
   1.171 +        and <a href="@TOP@/org/openide/util/lookup/AbstractLookup.html">AbstractLookup</a>
   1.172 +        were modified to return immutable <code>Collection</code>s. 
   1.173 +        So do not try to modify them. It was always documented that the
   1.174 +        results, are immutable and also it was never said that a change is
   1.175 +        delivered when there is no change in the result, so this is considered
   1.176 +        compatible change, even it is know that at least one piece of code 
   1.177 +        in NetBeans relied on this behaviour.
   1.178 +      </description>
   1.179 +      <class package="org.openide.util.lookup" name="ProxyLookup"/>
   1.180 +      <class package="org.openide.util.lookup" name="AbstractLookup"/>
   1.181 +      <issue number="68031"/>
   1.182 +    </change>
   1.183 +    
   1.184 +
   1.185 +    <change id="excluding-lookup">
   1.186 +      <api name="lookup"/>
   1.187 +      <summary>
   1.188 +<code>Lookups.exclude</code> added to simplify writing of lookups that filter content of other lookups</summary>
   1.189 +      <version major="5" minor="4"/>
   1.190 +      <date day="14" month="1" year="2005"/>
   1.191 +      <author login="jtulach"/>
   1.192 +      <compatibility binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no" modification="no"/>
   1.193 +      <description>
   1.194 +        <p>New method that takes lookup and set of classes and return new lookup 
   1.195 +        which contains everything from the original one except instances of 
   1.196 +        the specified classes has been added.
   1.197 +        </p>
   1.198 +      </description>
   1.199 +      <class package="org.openide.util.lookup" name="Lookups"/>
   1.200 +      <issue number="53058"/>
   1.201 +    </change>
   1.202 +    <change>
   1.203 +        <api name="lookup"/>
   1.204 +        <summary>Added ability to order items in META-INF/services/ lookup</summary>
   1.205 +        <version major="4" minor="34"/>
   1.206 +        <date day="9" month="5" year="2004"/>
   1.207 +        <author login="dkonecny"/>
   1.208 +        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.209 +        <description>
   1.210 +            Items in META-INF/services/ lookup can be followed by advisory
   1.211 +            "position" attribute. The resulting lookup will list first items with lower
   1.212 +            position value. Items without position attribute will be listed 
   1.213 +            last. See documentation for more details on format.
   1.214 +        </description>
   1.215 +        <class package="org.openide.util.lookup" name="Lookups"/>
   1.216 +        <issue number="41606"/>
   1.217 +    </change>
   1.218 +    <change>
   1.219 +     <api name="lookup"/>
   1.220 +     <summary>New <code>lookupItem()</code> method in Lookups</summary>
   1.221 +     <version major="4" minor="8"/>
   1.222 +     <date day="9" month="7" year="2003"/>
   1.223 +     <author login="vstejskal"/>
   1.224 +     <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.225 +     <description>
   1.226 +       New method that returns Lookup.Item implementation for given instance and key identifying
   1.227 +       that instance in the lookup. This method is useful when writing Looks which need to
   1.228 +       return some cookies (Collection of Lookup.Items).
   1.229 +     </description>
   1.230 +     <class package="org.openide.util.lookup" name="Lookups"/>
   1.231 +    </change>
   1.232 +    <change>
   1.233 +        <api name="lookup"/>
   1.234 +        <summary>New method Lookups.metaInfServices</summary>
   1.235 +        <version major="3" minor="35"/>
   1.236 +        <date day="5" month="2" year="2003"/>
   1.237 +        <author login="dstrupl"/>
   1.238 +        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.239 +        <description>
   1.240 +            A lookup that implements the JDK1.3 JAR services mechanism and delegates
   1.241 +            to META-INF/services/name.of.class files. This lookup was (is) used by core
   1.242 +            and the core had to use reflection to create an instance. Moreover can
   1.243 +            be usefull for module authors and in standalone library.
   1.244 +        </description>
   1.245 +        <class package="org.openide.util.lookup" name="Lookups"/>
   1.246 +        <issue number="29126"/>
   1.247 +    </change>
   1.248 +    <change>
   1.249 +        <api name="lookup"/>
   1.250 +        <summary>New method Lookups.proxy</summary>
   1.251 +        <version major="3" minor="9"/>
   1.252 +        <date day="20" month="9" year="2002"/>
   1.253 +        <author login="dstrupl"/>
   1.254 +        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.255 +        <description>
   1.256 +            Creates a lookup that delegates to another one but that one can change
   1.257 +            from time to time. The returned lookup checks every time somebody calls
   1.258 +            lookup or lookupItem method whether the provider still returns
   1.259 +            the same lookup. If not, it updates state of all Lookup.Results
   1.260 +            that it created (and that still exists).
   1.261 +        </description>
   1.262 +        <class package="org.openide.util.lookup" name="Lookups"/>
   1.263 +        <issue number="27425"/>
   1.264 +    </change>
   1.265 +    <change id="meta-inf-services">
   1.266 +        <api name="lookup"/>
   1.267 +        <summary>Modules can specify the content of Lookup.getDefault
   1.268 +        in META-INF/services</summary>
   1.269 +        <version major="3" minor="3"/>
   1.270 +        <date day="22" month="7" year="2002"/>
   1.271 +        <author login="jtulach"/>
   1.272 +        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.273 +        <description>
   1.274 +          The content of <code>Lookup.getDefault()</code> can be specified
   1.275 +          by a standard JDK registration mechanism, using JARs'
   1.276 +          <a href="http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html#Service%20Provider" shape="rect">
   1.277 +            META-INF/services
   1.278 +          </a>
   1.279 +          directory. This is suitable for services that do not change,
   1.280 +          do not require user modification and that need to be ready
   1.281 +          soon during initialization of the system. 
   1.282 +        </description>
   1.283 +    </change>
   1.284 +    <change>
   1.285 +         <api name="lookup"/>
   1.286 +         <summary>Added org.openide.util.lookup.Lookups</summary>
   1.287 +         <version major="2" minor="21"/>
   1.288 +         <date day="28" month="5" year="2002"/>
   1.289 +         <author login="dstrupl"/>
   1.290 +         <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.291 +         <description>New utility class added. The class cannot be instantiated
   1.292 +           and contains following static methods:
   1.293 +        <pre xml:space="preserve">
   1.294 +<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Lookup</span> <span class="function-name">singleton</span>(<span class="type">Object</span> <span class="variable-name">objectToLookup</span>);
   1.295 +<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Lookup</span> <span class="function-name">fixed</span>(<span class="type">Object</span>[] <span class="variable-name">objectsToLookup</span>);
   1.296 +<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Lookup</span> <span class="function-name">fixed</span>(<span class="type">Object</span>[] <span class="variable-name">keys</span>, <span class="type">InstanceContent.Convertor</span> <span class="variable-name">convertor</span>);
   1.297 +</pre>
   1.298 +           The methods return an instance of simple lookup implementation
   1.299 +           that holds the objects passed a parameter.
   1.300 +         </description>
   1.301 +         <class package="org.openide.util.lookup" name="Lookups"/>
   1.302 +         <issue number="20550"/>
   1.303 +    </change>
   1.304 +    <change id="AbstractLookup.Content-ProxyLookup.beforeLookup">
   1.305 +      <api name="lookup"/>
   1.306 +      <summary>Enhanced usage of ProxyLookup &amp; AbstractLookup.Content</summary>
   1.307 +      <version major="1" minor="31"/>
   1.308 +      <date day="18" month="8" year="2001"/>
   1.309 +      <author login="jtulach"/>
   1.310 +      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.311 +      <description>
   1.312 +        <code>AbstractLookup.Content</code> made public to allow its usage 
   1.313 +        for objects that do not subclass AbstractLookup. <code>ProxyLookup.beforeLookup</code>
   1.314 +        added so subclasses can update themselves (call setLookups (...)) before the actual lookup is
   1.315 +        performed.
   1.316 +      </description>
   1.317 +      <class package="org.openide.util.lookup" name="AbstractLookup"/>
   1.318 +      <class package="org.openide.util.lookup" name="ProxyLookup"/>
   1.319 +    </change>
   1.320 +    <change>
   1.321 +      <api name="lookup"/>
   1.322 +      <summary>Instance content simplifies creation of lookups</summary>
   1.323 +      <version major="1" minor="25"/>
   1.324 +      <!-- XXX date unknown -->
   1.325 +      <author login="jtulach"/>
   1.326 +      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.327 +      <description>
   1.328 +        Added <code>AbstractLookup.Content</code> which can be passed to an
   1.329 +        abstract lookup in its constructor and used to control the contents
   1.330 +        easily. Also <code>InstanceLookup</code> provides the common easy
   1.331 +        implementation.
   1.332 +      </description>
   1.333 +      <class package="org.openide.util.lookup" name="AbstractLookup"/>
   1.334 +      <class package="org.openide.util.lookup" name="InstanceContent"/>
   1.335 +    </change>
   1.336 +    <change>
   1.337 +      <api name="lookup"/>
   1.338 +      <summary>Folder lookup may be serialized</summary>
   1.339 +      <version major="3" minor="27"/>
   1.340 +      <date day="7" month="1" year="2003"/>
   1.341 +      <author login="jglick"/>
   1.342 +      <compatibility modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no">
   1.343 +        Modules which rely on a data object under <samp>Services/</samp> gaining
   1.344 +        or losing <code>InstanceCookie</code> between sessions may not work
   1.345 +        correctly with the cache. This is probably very rare.
   1.346 +      </compatibility>
   1.347 +      <description>
   1.348 +        To implement lookup caching, some lookup implementations are now
   1.349 +        serializable: <code>AbstractLookup</code> as well as
   1.350 +        <code>FolderLookup</code>'s lookup. <code>ProxyLookup</code> has a
   1.351 +        protected subclass constructor permitting subclasses to be serializable.
   1.352 +      </description>
   1.353 +      <class package="org.openide.util.lookup" name="AbstractLookup"/>
   1.354 +      <class package="org.openide.util.lookup" name="ProxyLookup"/>
   1.355 +      <issue number="20190"/>
   1.356 +    </change>
   1.357 +    <change>
   1.358 +      <api name="lookup"/>
   1.359 +      <summary>Changes in access protection of proxy lookup</summary>
   1.360 +      <version major="1" minor="19"/>
   1.361 +      <date day="8" month="7" year="2001"/>
   1.362 +      <compatibility modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no">
   1.363 +        Changes to newly added feature.
   1.364 +      </compatibility>
   1.365 +      <description>
   1.366 +        <code>ProxyLookup.setLookups</code> made protected instead of public so
   1.367 +        nobody can misuse the method except the creator of the object and
   1.368 +        <code>ProxyLookup.getLookups</code> added. <code>ProxyLookup</code> made
   1.369 +        non final.
   1.370 +      </description>
   1.371 +      <class package="org.openide.util.lookup" name="ProxyLookup"/>
   1.372 +    </change>
   1.373 +    <change>
   1.374 +      <api name="lookup"/>
   1.375 +      <summary>Lookup service providers package created</summary>
   1.376 +      <version major="1" minor="9"/>
   1.377 +      <date day="1" month="6" year="2001"/>
   1.378 +      <author login="jtulach"/>
   1.379 +      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.380 +      <description>
   1.381 +        Package <code>org.openide.util.lookup</code> created, should hold SPI
   1.382 +        interfaces for lookup. Initially filled with <code>AbstractLookup</code>
   1.383 +        which introduces <code>AbstractLookup.Pair</code> and with
   1.384 +        <code>ProxyLookup</code>.
   1.385 +      </description>
   1.386 +      <class package="org.openide.util.lookup" name="AbstractLookup"/>
   1.387 +      <class package="org.openide.util.lookup" name="ProxyLookup"/>
   1.388 +      <package name="org.openide.util.lookup"/>
   1.389 +    </change>
   1.390 +    <change>
   1.391 +      <api name="lookup"/>
   1.392 +      <summary>Added lookup items and support APIs</summary>
   1.393 +      <version major="1" minor="8"/>
   1.394 +      <date day="25" month="5" year="2001"/>
   1.395 +      <author login="jtulach"/>
   1.396 +      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.397 +      <description>
   1.398 +        <code>Lookup</code> enhanced. Interface <code>Lookup.Item</code> and
   1.399 +        additional methods to access it also added.
   1.400 +      </description>
   1.401 +      <class package="org.openide.util" name="Lookup"/>
   1.402 +    </change>
   1.403 +    <change>
   1.404 +      <api name="lookup"/>
   1.405 +      <summary>Lookup system introduced</summary>
   1.406 +      <date day="1" month="3" year="2001"/>
   1.407 +      <author login="jtulach"/>
   1.408 +      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
   1.409 +      <description>
   1.410 +        Better version of <code>Lookup</code> introduced. There is a
   1.411 +        <code>org.openide.util.Lookup</code> with bunch of inner classes and
   1.412 +        <code>org.openide.util.LookupListener</code> and
   1.413 +        <code>org.openide.util.LookupEvent</code>.
   1.414 +      </description>
   1.415 +      <class package="org.openide.util" name="Lookup"/>
   1.416 +      <class package="org.openide.util" name="LookupEvent"/>
   1.417 +      <class package="org.openide.util" name="LookupListener"/>
   1.418 +    </change>
   1.419 +</changes>
   1.420 +<htmlcontents>
   1.421 +<head>
   1.422 +<title>Change History for the Lookup API</title>
   1.423 +<link rel="stylesheet" href="prose.css" type="text/css"/>
   1.424 +</head>
   1.425 +<body>
   1.426 +<p class="overviewlink">
   1.427 +<a href="overview-summary.html">Overview</a>
   1.428 +</p>
   1.429 +<h1>Introduction</h1>
   1.430 +<h2>What do the Dates Mean?</h2>
   1.431 +<p>The supplied dates indicate when the API change was made, on the CVS
   1.432 +trunk. From this you can generally tell whether the change should be
   1.433 +present in a given build or not; for trunk builds, simply whether it
   1.434 +was made before or after the change; for builds on a stabilization
   1.435 +branch, whether the branch was made before or after the given date. In
   1.436 +some cases corresponding API changes have been made both in the trunk
   1.437 +and in an in-progress stabilization branch, if they were needed for a
   1.438 +bug fix; this ought to be marked in this list.</p>
   1.439 +<ul>
   1.440 +<li>The <code>release41</code> branch was made on Apr 03 '05 for use in the NetBeans 4.1 release.
   1.441 +Specification versions: 6.0 begins after this point.</li>
   1.442 +<li>The <code>release40</code> branch was made on Nov 01 '04 for use in the NetBeans 4.0 release.
   1.443 +Specification versions: 5.0 begins after this point.</li>
   1.444 +</ul>
   1.445 +<hr/>
   1.446 +<standard-changelists module-code-name="$codebase"/>
   1.447 +<hr/>
   1.448 +<p>@FOOTER@</p>
   1.449 +</body>
   1.450 +</htmlcontents>
   1.451 +</apichanges>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/openide.util.lookup/arch.xml	Mon Dec 14 20:58:39 2009 +0100
     2.3 @@ -0,0 +1,827 @@
     2.4 +<?xml version="1.0" encoding="UTF-8"?>
     2.5 +<!--
     2.6 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     2.7 +
     2.8 +Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
     2.9 +
    2.10 +
    2.11 +The contents of this file are subject to the terms of either the GNU
    2.12 +General Public License Version 2 only ("GPL") or the Common
    2.13 +Development and Distribution License("CDDL") (collectively, the
    2.14 +"License"). You may not use this file except in compliance with the
    2.15 +License. You can obtain a copy of the License at
    2.16 +http://www.netbeans.org/cddl-gplv2.html
    2.17 +or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    2.18 +specific language governing permissions and limitations under the
    2.19 +License.  When distributing the software, include this License Header
    2.20 +Notice in each file and include the License file at
    2.21 +nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    2.22 +particular file as subject to the "Classpath" exception as provided
    2.23 +by Sun in the GPL Version 2 section of the License file that
    2.24 +accompanied this code. If applicable, add the following below the
    2.25 +License Header, with the fields enclosed by brackets [] replaced by
    2.26 +your own identifying information:
    2.27 +"Portions Copyrighted [year] [name of copyright owner]"
    2.28 +
    2.29 +Contributor(s):
    2.30 +
    2.31 +The Original Software is NetBeans. The Initial Developer of the Original
    2.32 +Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
    2.33 +Microsystems, Inc. All Rights Reserved.
    2.34 +
    2.35 +If you wish your version of this file to be governed by only the CDDL
    2.36 +or only the GPL Version 2, indicate your decision by adding
    2.37 +"[Contributor] elects to include this software in this distribution
    2.38 +under the [CDDL or GPL Version 2] license." If you do not indicate a
    2.39 +single choice of license, a recipient has the option to distribute
    2.40 +your version of this file under either the CDDL, the GPL Version 2 or
    2.41 +to extend the choice of license to its licensees as provided above.
    2.42 +However, if you add GPL Version 2 code and therefore, elected the GPL
    2.43 +Version 2 license, then the option applies only if the new code is
    2.44 +made subject to such option by the copyright holder.
    2.45 +-->
    2.46 +<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" "../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
    2.47 +  <!ENTITY api-questions SYSTEM "../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
    2.48 +]>
    2.49 +
    2.50 +<api-answers
    2.51 +  question-version="1.25"
    2.52 +  author="jtulach@netbeans.org"
    2.53 +>
    2.54 +
    2.55 +  &api-questions;
    2.56 +
    2.57 + <answer id="arch-overall">
    2.58 +  <p>
    2.59 +    Also this module defines the <a href="@TOP@/org/openide/util/Lookup.html">
    2.60 +    Lookup</a> which is the NetBeans way for dynamic registration
    2.61 +    and lookup of 
    2.62 +    components in our modularized component system. It allows lookup and discovery 
    2.63 +    of features by description of their interfaces. The classes are devided 
    2.64 +    into two parts. The 
    2.65 +    <api group="java" name="LookupAPI" type="export" category="official" url="@TOP@/org/openide/util/lookup/doc-files/lookup-api.html">
    2.66 +    allows the discovery</api> and the 
    2.67 +    <api group="java" name="LookupSPI" type="export" category="official" url="@TOP@/org/openide/util/lookup/doc-files/lookup-spi.html">
    2.68 +    simplifies creation and registration of own lookup objects</api>.
    2.69 +  </p>
    2.70 + </answer>
    2.71 +
    2.72 +
    2.73 + <answer id="arch-quality">
    2.74 +  <p>
    2.75 +   There is a lot of unit tests in 
    2.76 +   <a href="http://hg.netbeans.org/main-golden/openide.util.lookup/test/unit/src/">version control</a>
    2.77 +   system.
    2.78 +  </p>
    2.79 + </answer>
    2.80 +
    2.81 + <answer id="arch-time">
    2.82 +  <p>
    2.83 +   The module has been around since 1997 and is continously being improved
    2.84 +   from time to time.
    2.85 +  </p>
    2.86 + </answer>
    2.87 +
    2.88 +
    2.89 +
    2.90 + <answer id="arch-usecases">
    2.91 +  
    2.92 +    There is a great introduction to Lookup and its usage in its 
    2.93 +    <a href="@TOP@/org/openide/util/Lookup.html">javadoc</a>. Here is just
    2.94 +    a list of frequently asked or interesting questions slowly expanding as
    2.95 +    people ask them:
    2.96 +    
    2.97 +    <h3>Lookup faq:</h3>
    2.98 +    
    2.99 +    <usecase id="lookup-on-certain-platform" name="How to specify that a service in Lookup should be available only on Windows?" >
   2.100 +<em><b>Q:</b>
   2.101 +Most of the time I specify interfaces that I want to add to the Lookup class in the layer.xml file. 
   2.102 +But, let's say I have a platform-specific interface (something on Windows only, for instance).</em>
   2.103 +<p>
   2.104 +<em>
   2.105 +How can I specify (in the xml, or programmatically) that this service should only be added to the Lookup if the platform is Windows?
   2.106 +</em>>
   2.107 +</p>
   2.108 +In general there are three ways to achieve this.
   2.109 +<ul>
   2.110 +    <li><p>It is possible to write a specific module and enable it only on windows.
   2.111 +    See <a href="@org-openide-modules@/org/openide/modules/doc-files/api.html#how-os-specific">os specific modules</a> documentation.
   2.112 +    Then you can put a registration of your instance into your module's 
   2.113 +    <a href="@org-openide-util@/org/openide/util/doc-files/api.html#service-lookup">META-INF/services</a> directory and it
   2.114 +    will be available only on Windows.</p>
   2.115 +    </li>
   2.116 +    
   2.117 +    <li><p>Another possibility that does not require new module, but which executes 
   2.118 +    a code on startup (which may have performance implications) is to use <code>methodvalue</code>
   2.119 +    attribute. Register your instance in layer using <code>your-Object.instance</code> file
   2.120 +    as described at 
   2.121 +    <a href="@org-openide-util@/org/openide/util/doc-files/api.html#ido-methodvalue">services
   2.122 +    </a> documentation and in your factory method either return the instance 
   2.123 +    your want or <code>null</code> depending on result of <a href="@org-openide-util@/org/openide/util/Utilities.html#isWindows()">
   2.124 +    Utilities.isWindows()</a> call.</p>
   2.125 +    </li>
   2.126 +                <li>
   2.127 +                    <p>
   2.128 +                        In some cases, the interface for which you will register an implementation permits a
   2.129 +                        no-operation semantics. For example, <code>InstalledFileLocator.locate(...)</code> can
   2.130 +                        return a valid <code>File</code>, or null. You could always register an
   2.131 +                        <code>InstalledFileLocator</code> instance yet disable it on non-Windows platforms
   2.132 +                        (always returning null).
   2.133 +                    </p>
   2.134 +                </li>
   2.135 +</ul>
   2.136 +
   2.137 +    </usecase>
   2.138 +    
   2.139 +    <usecase id="lookup-extension-point" name="How shall I write an extension point for my module?" >
   2.140 +    <p>
   2.141 +        <em><b>Q:</b>
   2.142 +        I have more modules one of them providing the core functionality and
   2.143 +        few more that wish to extend it. What is the right way to do it?
   2.144 +        How does the Netbeans platform declare such extension point? 
   2.145 +        </em>
   2.146 +    </p>
   2.147 +
   2.148 +    <p>
   2.149 +    
   2.150 +    Start with declaring an extension interface in your
   2.151 +    core module and put it into the module's <em>public packages</em>. Imagine
   2.152 +    for example that the core module is in JAR file <code>org-my-netbeans-coremodule.jar</code>
   2.153 +    and already contains in manifests line like 
   2.154 +    <code>OpenIDE-Module: org.my.netbeans.coremodule/1</code> and wants 
   2.155 +    to display various tips of the day provided by other modules and thus defines:
   2.156 +    </p><pre> 
   2.157 +<span class="java-keywords">package</span> <span class="java-identifier">org</span><span class="java-operators">.</span><span class="java-identifier">my</span><span class="java-operators">.</span><span class="java-identifier">netbeans</span><span class="java-operators">.</span><span class="java-identifier">coremodule</span><span class="java-operators">;</span>
   2.158 +
   2.159 +<span class="java-keywords">public</span> <span class="java-keywords">interface</span> <span class="java-identifier">TipsOfTheDayProvider</span> <span class="java-operators">{</span>
   2.160 +    <span class="java-keywords">public</span> <span class="java-identifier">String</span> <span class="java-layer-method">provideTipOfTheDay</span> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">;</span>
   2.161 +<span class="java-operators">}</span>
   2.162 +</pre><p>
   2.163 +    And in its manifest adds line 
   2.164 +    <code>OpenIDE-Module-Public-Packages: org.my.netbeans.coremodule.*</code>
   2.165 +    to specify that this package contains exported API and shall be 
   2.166 +    accessible to other modules.
   2.167 +    </p>
   2.168 +    <p>
   2.169 +    When the core module is about to display the tip of the day it can ask
   2.170 +    the system for all registered instances of the <code>TipsOfTheDayProvider</code>,
   2.171 +    randomly select one of them:
   2.172 +    </p><pre>
   2.173 +<span class="java-keywords">import</span> <span class="java-identifier">java</span><span class="java-operators">.</span><span class="java-identifier">util</span><span class="java-operators">.</span><span class="java-identifier">Collection</span><span class="java-operators">;</span>
   2.174 +<span class="java-keywords">import</span> <span class="java-identifier">java</span><span class="java-operators">.</span><span class="java-identifier">util</span><span class="java-operators">.</span><span class="java-identifier">Collections</span><span class="java-operators">;</span>
   2.175 +<span class="java-keywords">import</span> <span class="java-identifier">org</span><span class="java-operators">.</span><span class="java-identifier">openide</span><span class="java-operators">.</span><span class="java-identifier">util</span><span class="java-operators">.</span><span class="java-identifier">Lookup</span><span class="java-operators">;</span>
   2.176 +
   2.177 +<a href="@TOP@org/openide/util/Lookup.Result.html"><span class="java-identifier">Lookup</span><span class="java-operators">.</span><span class="java-identifier">Result</span></a> <span class="java-identifier">result</span> <span class="java-operators">=</span> <a href="@TOP@org/openide/util/Lookup.html"><span class="java-identifier">Lookup</span></a><span class="java-operators">.</span><span class="java-layer-method">getDefault</span> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">.</span><span class="java-layer-method">lookup</span> <span class="java-operators">(</span><span class="java-keywords">new</span> <a href="@TOP@org/openide/util/Lookup.Template.html"><span class="java-identifier">Lookup</span><span class="java-operators">.</span><span class="java-layer-method">Template</span></a> <span class="java-operators">(</span><span class="java-identifier">TipsOfTheDayProvider</span><span class="java-operators">.</span><span class="java-keywords">class</span><span class="java-operators">)</span><span class="java-operators">)</span><span class="java-operators">;</span>
   2.178 +<span class="java-identifier">Collection</span> <span class="java-identifier">c</span> <span class="java-operators">=</span> <span class="java-identifier">result</span><span class="java-operators">.</span><a href="@TOP@org/openide/util/Lookup.Result.html#allInstances()"><span class="java-layer-method">allInstances</span></a> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">;</span>
   2.179 +<span class="java-identifier">Collections</span><span class="java-operators">.</span><span class="java-layer-method">shuffle</span> <span class="java-operators">(</span><span class="java-identifier">c</span><span class="java-operators">)</span><span class="java-operators">;</span>
   2.180 +<span class="java-identifier">TipsOfTheDayProvider</span> <span class="java-identifier">selected</span> <span class="java-operators">=</span> <span class="java-operators">(</span><span class="java-identifier">TipsOfTheDayProvider</span><span class="java-operators">)</span><span class="java-identifier">c</span><span class="java-operators">.</span><span class="java-layer-method">iterator</span> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">.</span><span class="java-layer-method">next</span> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">;</span>
   2.181 +</pre><p>    
   2.182 +    and then display the tip. Simple, trivial, just by the usage of 
   2.183 +    <a href="@TOP@org/openide/util/Lookup.html">Lookup</a> interface once 
   2.184 +    creates a registry that other modules can enhance. But such enhancing 
   2.185 +    of course requires work on the other side. Each module that would like
   2.186 +    to register its <code>TipsOfTheDayProvider</code> needs to depend on the 
   2.187 +    core module - add 
   2.188 +    <code>OpenIDE-Module-Module-Dependencies: org.my.netbeans.coremodule/1</code>
   2.189 +    into its manifest and write a class with its own implementation of the
   2.190 +    provider:</p><pre>
   2.191 +<span class="java-keywords">package</span> <span class="java-identifier">org</span><span class="java-operators">.</span><span class="java-identifier">my</span><span class="java-operators">.</span><span class="java-identifier">netbeans</span><span class="java-operators">.</span><span class="java-identifier">extramodule</span><span class="java-operators">;</span>
   2.192 +
   2.193 +<span class="java-keywords">class</span> <span class="java-identifier">ExtraTip</span> <span class="java-keywords">implements</span> <span class="java-identifier">TipsOfTheDayProvider</span> <span class="java-operators">{</span>
   2.194 +    <span class="java-keywords">public</span> <span class="java-identifier">String</span> <span class="java-layer-method">provideTipOfTheDay</span> <span class="java-operators">(</span><span class="java-operators">)</span> <span class="java-operators">{</span>
   2.195 +        <span class="java-keywords">return</span> <span class="java-string-literal">"Do you know that in order to write extension point you should use Lookup?"</span><span class="java-operators">;</span>
   2.196 +    <span class="java-operators">}</span>
   2.197 +<span class="java-operators">}</span>
   2.198 +</pre><p>
   2.199 +    Then, the only necessary thing is to register such class by using the 
   2.200 +    J2SE standard <api name="ProviderRegistrationMechanism"
   2.201 +  type="import"
   2.202 +  category="standard"
   2.203 +  group="java" /> into plain text file
   2.204 +    <code>META-INF/services/org.my.netbeans.coremodule.TipsOfTheDayProvider</code>
   2.205 +    in the module JAR containing just one line: </p><pre>
   2.206 +org.my.netbeans.extramodule.ExtraTip
   2.207 +</pre><p>    
   2.208 +    and your modules are now ready to communicate
   2.209 +    using your own <em>extension point</em>.
   2.210 +    </p>
   2.211 +    
   2.212 +    </usecase>
   2.213 + </answer>
   2.214 +
   2.215 +
   2.216 +
   2.217 + <answer id="arch-what">
   2.218 +  <p>
   2.219 +    Described in the <a href="@TOP@/architecture-summary.html#answer-arch-overall">overall</a> answer.
   2.220 +  </p>
   2.221 + </answer>
   2.222 +
   2.223 +
   2.224 +
   2.225 + <answer id="compat-standards">
   2.226 +  <p>
   2.227 +    The default lookup registration follows the JDK's 
   2.228 +    <api name="ProviderRegistrationMechanism"
   2.229 +      type="import"
   2.230 +      category="standard"
   2.231 +      url="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Provider%20Configuration%20File"
   2.232 +      group="java" 
   2.233 +    />
   2.234 +    but enhances it to also support the 
   2.235 +    <api 
   2.236 +      name="ProviderRegistrationRemoval" 
   2.237 +      type="export" 
   2.238 +      category="devel" 
   2.239 +      url="@org-openide-util@/org/openide/util/doc-files/api.html#service-lookup"
   2.240 +      group="java" 
   2.241 +    />. 
   2.242 +  </p>
   2.243 + </answer>
   2.244 +
   2.245 + <answer id="compat-version">
   2.246 +  <p>
   2.247 +   This module has no settings. 
   2.248 +  </p>
   2.249 + </answer>
   2.250 +
   2.251 +
   2.252 +
   2.253 + <answer id="dep-jre">
   2.254 +  <p>
   2.255 +   Currently JRE 1.5 is needed.
   2.256 +  </p>
   2.257 + </answer>
   2.258 +
   2.259 +
   2.260 +
   2.261 + <answer id="dep-jrejdk">
   2.262 +  <p>
   2.263 +   JRE is enough.
   2.264 +  </p>
   2.265 + </answer>
   2.266 +
   2.267 +
   2.268 + <answer id="dep-nb">
   2.269 +     <p>N/A</p>
   2.270 + </answer>
   2.271 +
   2.272 + <answer id="dep-platform">
   2.273 +  <p>
   2.274 +   Platform independent.
   2.275 +  </p>
   2.276 + </answer>
   2.277 +
   2.278 +
   2.279 + <answer id="deploy-dependencies">
   2.280 +  <p>
   2.281 +  Nothing.
   2.282 +  </p>
   2.283 + </answer>
   2.284 +
   2.285 +
   2.286 +
   2.287 + <answer id="deploy-jar">
   2.288 +  <p>
   2.289 +   <api category="devel" group="java.io.File" name="FileLocation" type="export" >
   2.290 +   the JAR file is located in platform cluster under <code>lib/org-openide-util-lookup.jar</code>
   2.291 +   </api>.
   2.292 +  </p>
   2.293 + </answer>
   2.294 +
   2.295 + <answer id="deploy-shared">
   2.296 +  <p>
   2.297 +   Module is on real java classpath and as such it has to be in the shared directory.
   2.298 +  </p>
   2.299 + </answer>
   2.300 +
   2.301 +
   2.302 + <answer id="exec-ant-tasks">
   2.303 +  <p>
   2.304 +   No.
   2.305 +  </p>
   2.306 + </answer>
   2.307 +
   2.308 +
   2.309 +
   2.310 + <answer id="exec-classloader">
   2.311 +  <p>
   2.312 +   No, we do not create own classloader.
   2.313 +  </p>
   2.314 + </answer>
   2.315 +
   2.316 +
   2.317 +
   2.318 +<answer id="exec-privateaccess">
   2.319 +  <p>
   2.320 +  No.
   2.321 +  </p>
   2.322 + </answer>
   2.323 +
   2.324 + <answer id="exec-process">
   2.325 +  <p>
   2.326 +   No external processes executed.
   2.327 +  </p>
   2.328 + </answer>
   2.329 +
   2.330 +
   2.331 + <answer id="exec-property">
   2.332 +  <ul>
   2.333 +    <li>
   2.334 +    <api type="export" group="property" name="org.openide.util.Lookup" category="devel">
   2.335 +        checked by the initialization of the 
   2.336 +        <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
   2.337 +        and can
   2.338 +        contain name of a class that extends <code>org.openide.util.Lookup</code> and
   2.339 +        has public constructor, that should be instantiated and returned from 
   2.340 +        <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
   2.341 +        the class will be loaded by 
   2.342 +        <a href="@JDK@/java/lang/Thread.html#getContextClassLoader()">
   2.343 +        Thread.currentThread().getContextClassLoader()</a>
   2.344 +        classloader the first time <code>Lookup.getDefault</code> is invoked.
   2.345 +        <p/>
   2.346 +        The property can also contain value <code>"-"</code> which means to completely
   2.347 +        disable the lookup instantiation and return <a href="@TOP@/org/openide/util/Lookup.html#EMPTY">Lookup.EMPTY</a>
   2.348 +        from <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>.
   2.349 +        <p/>
   2.350 +        If the property is unspecified, the default <code>MetaInfServicesLookup</code>
   2.351 +        is constructed for <code>Thread.currentThread().getContextclassLoader()</code>
   2.352 +        that implements the <a href="architecture-summary.html#answer-compat-standards">JDK's standard</a>. If, by 
   2.353 +        a chance an instance of 
   2.354 +        <a href="@TOP@/org/openide/util/Lookup.Provider.html">Lookup.Provider</a>
   2.355 +        is found
   2.356 +        in there, its lookup is returned as result. Otherwise the <code>MetaInfServicesLookup</code>
   2.357 +        is the result of <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>.
   2.358 +    </api>
   2.359 +    </li>
   2.360 +
   2.361 +    <li>
   2.362 +    <api type="export" group="property" name="org.openide.util.Lookup.paths" category="devel">
   2.363 +        Sometimes it may be useful for the Lookup to contains objects from
   2.364 +        some system file system folder. This can be done with
   2.365 +        <code>org.openide.util.Lookup.paths=Folder1:Folder2:Folder3</code>.
   2.366 +        If this property is set prior to first call to
   2.367 +        <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>,
   2.368 +        it is split into pieces (separator is <code>':'</code>) and individual
   2.369 +        parts are then used to construct <code>Lookups.forPath("Folder1")</code>,
   2.370 +        etc. All these lookups then become part of the
   2.371 +        <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
   2.372 +        one. This property works since version 7.24
   2.373 +    </api>
   2.374 +    </li>
   2.375 +    
   2.376 +  </ul>
   2.377 + </answer>
   2.378 +
   2.379 +
   2.380 +
   2.381 + <answer id="exec-reflection">
   2.382 +  <p>
   2.383 +   <api category="devel" group="java" name="Lookups.metaInfServices" type="export" url="@TOP@/org/openide/util/lookup/Lookups.html#metaInfServices(java.lang.ClassLoader)">
   2.384 +   calls constructor of registered classes using reflection
   2.385 +   </api>. 
   2.386 +   <api category="friend" group="java" name="Lookup.resetDefaultLookup" type="export">
   2.387 +    There is a static private method <code>Lookup.resetDefaultLookup</code> that 
   2.388 +    is called by NbJUnit's <code>MockServices</code> to properly reset default
   2.389 +    lookup and fire changes to all registred listeners.
   2.390 +   </api>. 
   2.391 +
   2.392 +  </p>
   2.393 + </answer>
   2.394 +
   2.395 + <answer id="exec-threading">
   2.396 +  <p>
   2.397 +   Everything is synchronous, except pluggable use of <code>java.util.concurrent.Executor</code>
   2.398 +   that allows to make calls asynchronous. The default implementation only delivers
   2.399 +   changes from <a href="@TOP@/org/openide/util/lookup/Lookups.html#metaInfServices(java.lang.ClassLoader)">metaInfServices</a>
   2.400 +   lookup in asynchronous thread.
   2.401 +  </p>
   2.402 + </answer>
   2.403 +
   2.404 +
   2.405 +
   2.406 + <answer id="format-clipboard">
   2.407 +  <p>
   2.408 +      Not used.
   2.409 +  </p>
   2.410 + </answer>
   2.411 +
   2.412 +
   2.413 +
   2.414 + <answer id="format-dnd">
   2.415 +  <p>
   2.416 +  The same as for clipboard.
   2.417 +  </p>
   2.418 + </answer>
   2.419 +
   2.420 + <answer id="format-types">
   2.421 +  <p>
   2.422 +      No.
   2.423 +  </p>
   2.424 + </answer>
   2.425 +
   2.426 +
   2.427 +
   2.428 + <answer id="lookup-lookup">
   2.429 +    <ul>
   2.430 +    <li><api name="LookupInitializationLookup" category="devel" group="lookup" type="export" url="#property-org.openide.util.Lookup">
   2.431 +    during 
   2.432 +    initialization of the <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
   2.433 +    the <a href="@TOP@/org/openide/util/Lookup.Provider.html">Lookup.Provider</a>
   2.434 +    is being searched</api>.
   2.435 +    </li>
   2.436 +    
   2.437 +    <li><api name="LookupSharedClassObject" category="devel" group="lookup" type="export">
   2.438 +    singleton subclasses of <a href="@org-openide-util@/org/openide/util/SharedClassObject.html">SharedClassObject</a>
   2.439 +    are searched for using Lookup.
   2.440 +    </api>.</li>
   2.441 +            
   2.442 +    <li><api name="LookupClassLoader" category="devel" group="lookup" type="export">
   2.443 +    Nearly all resource looking functions and reflective code
   2.444 +    uses <a href="@JDK@/java/lang/ClassLoader.html">ClassLoader</a>
   2.445 +    obtained from <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
   2.446 +    for loading system wide resources.
   2.447 +    </api>.</li>
   2.448 +    
   2.449 +    </ul>
   2.450 + </answer>
   2.451 +
   2.452 +
   2.453 +
   2.454 + <answer id="lookup-register">
   2.455 +  <p>
   2.456 +   No.
   2.457 +  </p>
   2.458 + </answer>
   2.459 +
   2.460 +
   2.461 +
   2.462 +<!--
   2.463 +        <question id="lookup-remove" when="final">
   2.464 +            Do you remove entries of other modules from lookup?
   2.465 +            <hint>
   2.466 +            Why? Of course, that is possible, but it can be dangerous. Is the module
   2.467 +            your are masking resource from aware of what you are doing?
   2.468 +            </hint>
   2.469 +        </question>
   2.470 +-->
   2.471 + <answer id="lookup-remove">
   2.472 +  <p>
   2.473 +   No.
   2.474 +  </p>
   2.475 + </answer>
   2.476 +
   2.477 +
   2.478 +
   2.479 +<!--
   2.480 +        <question id="perf-exit" when="final">
   2.481 +            Does your module run any code on exit?
   2.482 +        </question>
   2.483 +-->
   2.484 + <answer id="perf-exit">
   2.485 +  <p>
   2.486 +   Nothing.
   2.487 +  </p>
   2.488 + </answer>
   2.489 +
   2.490 +
   2.491 +
   2.492 +<!--
   2.493 +        <question id="perf-huge_dialogs" when="final">
   2.494 +            Does your module contain any dialogs or wizards with a large number of
   2.495 +            GUI controls such as combo boxes, lists, trees, or text areas?
   2.496 +        </question>
   2.497 +-->
   2.498 + <answer id="perf-huge_dialogs">
   2.499 +  <p>
   2.500 +   No.
   2.501 +  </p>
   2.502 + </answer>
   2.503 +
   2.504 +
   2.505 +
   2.506 +<!--
   2.507 +        <question id="perf-limit" when="init">
   2.508 +            Are there any hard-coded or practical limits in the number or size of
   2.509 +            elements your code can handle?
   2.510 +        </question>
   2.511 +-->
   2.512 + <answer id="perf-limit">
   2.513 +  <p>
   2.514 +    The default implementation of the <code>MetaInfServicesLookup</code> just 
   2.515 +    keeps hashmap between queried classes and their implementations. The amount
   2.516 +    of memory is linear to amount of registered classes, but of course we 
   2.517 +    are not counting the memory occupied by the instances which the lookup 
   2.518 +    creates, that can be arbitrary.
   2.519 +  </p>
   2.520 + </answer>
   2.521 +
   2.522 +
   2.523 +
   2.524 +<!--
   2.525 +        <question id="perf-mem" when="final">
   2.526 +            How much memory does your component consume? Estimate
   2.527 +            with a relation to the number of windows, etc.
   2.528 +        </question>
   2.529 +-->
   2.530 + <answer id="perf-mem">
   2.531 +  <p>
   2.532 +   There are no big data structures. The amount of memory occupied by
   2.533 +   instances of <a href="@TOP@/org/openide/util/lookup/AbstractLookup.html">AbstractLookup</a> 
   2.534 +   is measured by unit tests.
   2.535 +  </p>
   2.536 + </answer>
   2.537 +
   2.538 +
   2.539 +
   2.540 +<!--
   2.541 +        <question id="perf-menus" when="final">
   2.542 +            Does your module use dynamically updated context menus, or
   2.543 +            context-sensitive actions with complicated and slow enablement logic?
   2.544 +            <hint>
   2.545 +                If you do a lot of tricks when adding actions to regular or context menus, you can significantly
   2.546 +                slow down display of the menu, even when the user is not using your action. Pay attention to
   2.547 +                actions you add to the main menu bar, and to context menus of foreign nodes or components. If
   2.548 +                the action is conditionally enabled, or changes its display dynamically, you need to check the
   2.549 +                impact on performance. In some cases it may be more appropriate to make a simple action that is
   2.550 +                always enabled but does more detailed checks in a dialog if it is actually run.
   2.551 +            </hint>
   2.552 +        </question>
   2.553 +-->
   2.554 + <answer id="perf-menus">
   2.555 +  <p>
   2.556 +   There are no menus.
   2.557 +  </p>
   2.558 + </answer>
   2.559 +
   2.560 +
   2.561 +
   2.562 +<!--
   2.563 +        <question id="perf-progress" when="final">
   2.564 +            Does your module execute any long-running tasks?
   2.565 +            
   2.566 +            <hint>Long running tasks should never block 
   2.567 +            AWT thread as it badly hurts the UI
   2.568 +            <a href="http://performance.netbeans.org/responsiveness/issues.html">
   2.569 +            responsiveness</a>.
   2.570 +            Tasks like connecting over
   2.571 +            network, computing huge amount of data, compilation
   2.572 +            be done asynchronously (for example
   2.573 +            using <code>RequestProcessor</code>), definitively it should 
   2.574 +            not block AWT thread.
   2.575 +            </hint>
   2.576 +        </question>
   2.577 +-->
   2.578 + <answer id="perf-progress">
   2.579 +  <p>
   2.580 +      No.
   2.581 +  </p>
   2.582 + </answer>
   2.583 +
   2.584 +
   2.585 +
   2.586 +<!--
   2.587 +        <question id="perf-scale" when="init">
   2.588 +            Which external criteria influence the performance of your
   2.589 +            program (size of file in editor, number of files in menu, 
   2.590 +            in source directory, etc.) and how well your code scales?
   2.591 +            <hint>
   2.592 +            Please include some estimates, there are other more detailed 
   2.593 +            questions to answer in later phases of implementation. 
   2.594 +            </hint>
   2.595 +        </question>
   2.596 +-->
   2.597 + <answer id="perf-scale">
   2.598 +  <p>
   2.599 +   Lookup code scales linearily.
   2.600 +  </p>
   2.601 + </answer>
   2.602 +
   2.603 +
   2.604 +
   2.605 +<!--
   2.606 +        <question id="perf-spi" when="init">
   2.607 +            How the performance of the plugged in code will be enforced?
   2.608 +            <hint>
   2.609 +            If you allow foreign code to be plugged into your own module, how
   2.610 +            do you enforce that it will behave correctly and quickly and will not
   2.611 +            negatively influence the performance of your own module?
   2.612 +            </hint>
   2.613 +        </question>
   2.614 +-->
   2.615 + <answer id="perf-spi">
   2.616 +  <p>
   2.617 +   No enforcing is done.
   2.618 +  </p>
   2.619 + </answer>
   2.620 +
   2.621 +
   2.622 +
   2.623 +<!--
   2.624 +        <question id="perf-startup" when="final">
   2.625 +            Does your module run any code on startup?
   2.626 +        </question>
   2.627 +-->
   2.628 + <answer id="perf-startup">
   2.629 +  <p>
   2.630 +   No.
   2.631 +  </p>
   2.632 + </answer>
   2.633 +
   2.634 +
   2.635 +
   2.636 +<!--
   2.637 +        <question id="perf-wakeup" when="final">
   2.638 +            Does any piece of your code wake up periodically and do something
   2.639 +            even when the system is otherwise idle (no user interaction)?
   2.640 +        </question>
   2.641 +-->
   2.642 + <answer id="perf-wakeup">
   2.643 +  <p>
   2.644 +   No. 
   2.645 +  </p>
   2.646 + </answer>
   2.647 +
   2.648 +
   2.649 +
   2.650 +<!--
   2.651 +        <question id="resources-file" when="final">
   2.652 +            Does your module use <code>java.io.File</code> directly?
   2.653 +            
   2.654 +            <hint>
   2.655 +            NetBeans provide a logical wrapper over plain files called 
   2.656 +            <code>org.openide.filesystems.FileObject</code> that
   2.657 +            provides uniform access to such resources and is the preferred
   2.658 +            way that should be used. But of course there can be situations when
   2.659 +            this is not suitable.
   2.660 +            </hint>
   2.661 +        </question>
   2.662 +-->
   2.663 + <answer id="resources-file">
   2.664 +  <p>
   2.665 +   No.
   2.666 +  </p>
   2.667 + </answer>
   2.668 +
   2.669 +
   2.670 +
   2.671 +<!--
   2.672 +        <question id="resources-layer" when="final">
   2.673 +            Does your module provide own layer? Does it create any files or
   2.674 +            folders in it? What it is trying to communicate by that and with which 
   2.675 +            components?
   2.676 +            
   2.677 +            <hint>
   2.678 +            NetBeans allows automatic and declarative installation of resources 
   2.679 +            by module layers. Module register files into appropriate places
   2.680 +            and other components use that information to perform their task
   2.681 +            (build menu, toolbar, window layout, list of templates, set of
   2.682 +            options, etc.). 
   2.683 +            </hint>
   2.684 +        </question>
   2.685 +-->
   2.686 + <answer id="resources-layer">
   2.687 +  <p>
   2.688 +   No.
   2.689 +  </p>
   2.690 + </answer>
   2.691 +
   2.692 +
   2.693 +
   2.694 +<!--
   2.695 +        <question id="resources-mask" when="final">
   2.696 +            Does your module mask/hide/override any resources provided by other modules in
   2.697 +            their layers?
   2.698 +            
   2.699 +            <hint>
   2.700 +            If you mask a file provided by another module, you probably depend
   2.701 +            on that and do not want the other module to (for example) change
   2.702 +            the file's name. That module shall thus make that file available as an API
   2.703 +            of some stability category.
   2.704 +            </hint>
   2.705 +        </question>
   2.706 +-->
   2.707 + <answer id="resources-mask">
   2.708 +  <p>
   2.709 +   No.
   2.710 +  </p>
   2.711 + </answer>
   2.712 +
   2.713 +
   2.714 +
   2.715 +<!--
   2.716 +        <question id="resources-read" when="final">
   2.717 +            Does your module read any resources from layers? For what purpose?
   2.718 +            
   2.719 +            <hint>
   2.720 +            As this is some kind of intermodule dependency, it is a kind of API.
   2.721 +            Please describe it and classify according to 
   2.722 +            <a href="http://openide.netbeans.org/tutorial/api-design.html#categories">
   2.723 +            common stability categories</a>.
   2.724 +            </hint>
   2.725 +        </question>
   2.726 +-->
   2.727 + <answer id="resources-read">
   2.728 +  <p>
   2.729 +   No.
   2.730 +  </p>
   2.731 + </answer>
   2.732 +
   2.733 +
   2.734 +
   2.735 +<!--
   2.736 +        <question id="security-grant" when="final">
   2.737 +            Does your code grant additional rights to some other code?
   2.738 +            <hint>Avoid using a class loader that adds extra
   2.739 +            permissions to loaded code unless really necessary.
   2.740 +            Also note that your API implementation
   2.741 +            can also expose unneeded permissions to enemy code by
   2.742 +            calling AccessController.doPrivileged().</hint>
   2.743 +        </question>
   2.744 +-->
   2.745 + <answer id="security-grant">
   2.746 +  <p>
   2.747 +   No security permitions manipulated.
   2.748 +  </p>
   2.749 + </answer>
   2.750 +
   2.751 +
   2.752 +
   2.753 +<!--
   2.754 +        <question id="security-policy" when="final">
   2.755 +            Does your functionality require modifications to the standard policy file?
   2.756 +            <hint>Your code might pass control to third-party code not
   2.757 +            coming from trusted domains. This could be code downloaded over the
   2.758 +            network or code coming from libraries that are not bundled
   2.759 +            with NetBeans. Which permissions need to be granted to which domains?</hint>
   2.760 +        </question>
   2.761 +-->
   2.762 + <answer id="security-policy">
   2.763 +  <p>
   2.764 +   No security permissions manipulated.
   2.765 +  </p>
   2.766 + </answer>
   2.767 +
   2.768 +
   2.769 +
   2.770 +
   2.771 +<!--
   2.772 +        <question id="arch-where" when="init">
   2.773 +            Where one can find sources for your module?
   2.774 +            <hint>
   2.775 +                Please provide link to the CVS web client at
   2.776 +                http://www.netbeans.org/download/source_browse.html
   2.777 +                or just use tag defaultanswer generate='here'
   2.778 +            </hint>
   2.779 +        </question>
   2.780 +-->
   2.781 + <answer id="arch-where">
   2.782 +  <defaultanswer generate='here' />
   2.783 + </answer>
   2.784 +
   2.785 +
   2.786 +
   2.787 +
   2.788 +<!--
   2.789 +        <question id="compat-deprecation" when="init">
   2.790 +            How the introduction of your project influences functionality
   2.791 +            provided by previous version of the product?
   2.792 +            <hint>
   2.793 +            If you are planning to deprecate/remove/change any existing APIs,
   2.794 +            list them here accompanied with the reason explaining why you
   2.795 +            are doing so.
   2.796 +            </hint>
   2.797 +        </question>
   2.798 +-->
   2.799 + <answer id="compat-deprecation">
   2.800 +  <p>
   2.801 +   XXX no answer for compat-deprecation
   2.802 +  </p>
   2.803 + </answer>
   2.804 +
   2.805 +
   2.806 +
   2.807 +<!--
   2.808 +        <question id="resources-preferences" when="final">
   2.809 +            Does your module uses preferences via Preferences API? Does your module use NbPreferences or
   2.810 +            or regular JDK Preferences ? Does it read, write or both ? 
   2.811 +            Does it share preferences with other modules ? If so, then why ?
   2.812 +            <hint>
   2.813 +                You may use
   2.814 +                    &lt;api type="export" group="preferences"
   2.815 +                    name="preference node name" category="private"&gt;
   2.816 +                    description of individual keys, where it is used, what it
   2.817 +                    influences, whether the module reads/write it, etc.
   2.818 +                    &lt;/api&gt;
   2.819 +                Due to XML ID restrictions, rather than /org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
   2.820 +                Note that if you use NbPreferences this name will then be the same as the code name base of the module.
   2.821 +            </hint>
   2.822 +        </question>
   2.823 +-->
   2.824 + <answer id="resources-preferences">
   2.825 +  <p>
   2.826 +   XXX no answer for resources-preferences
   2.827 +  </p>
   2.828 + </answer>
   2.829 +
   2.830 +</api-answers>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/openide.util.lookup/build.xml	Mon Dec 14 20:58:39 2009 +0100
     3.3 @@ -0,0 +1,5 @@
     3.4 +<?xml version="1.0" encoding="UTF-8"?>
     3.5 +<project basedir="." default="netbeans" name="openide.util.lookup">
     3.6 +    <description>Builds, tests, and runs the project org.openide.util.lookup</description>
     3.7 +    <import file="../nbbuild/templates/projectized.xml"/>
     3.8 +</project>
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/openide.util.lookup/manifest.mf	Mon Dec 14 20:58:39 2009 +0100
     4.3 @@ -0,0 +1,5 @@
     4.4 +Manifest-Version: 1.0
     4.5 +OpenIDE-Module: org.openide.util.lookup
     4.6 +OpenIDE-Module-Implementation-Version: 1
     4.7 +OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties
     4.8 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/openide.util.lookup/nbproject/project.properties	Mon Dec 14 20:58:39 2009 +0100
     5.3 @@ -0,0 +1,47 @@
     5.4 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.5 +#
     5.6 +# Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
     5.7 +#
     5.8 +# The contents of this file are subject to the terms of either the GNU
     5.9 +# General Public License Version 2 only ("GPL") or the Common
    5.10 +# Development and Distribution License("CDDL") (collectively, the
    5.11 +# "License"). You may not use this file except in compliance with the
    5.12 +# License. You can obtain a copy of the License at
    5.13 +# http://www.netbeans.org/cddl-gplv2.html
    5.14 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    5.15 +# specific language governing permissions and limitations under the
    5.16 +# License.  When distributing the software, include this License Header
    5.17 +# Notice in each file and include the License file at
    5.18 +# nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    5.19 +# particular file as subject to the "Classpath" exception as provided
    5.20 +# by Sun in the GPL Version 2 section of the License file that
    5.21 +# accompanied this code. If applicable, add the following below the
    5.22 +# License Header, with the fields enclosed by brackets [] replaced by
    5.23 +# your own identifying information:
    5.24 +# "Portions Copyrighted [year] [name of copyright owner]"
    5.25 +#
    5.26 +# Contributor(s):
    5.27 +#
    5.28 +# The Original Software is NetBeans. The Initial Developer of the Original
    5.29 +# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
    5.30 +# Microsystems, Inc. All Rights Reserved.
    5.31 +#
    5.32 +# If you wish your version of this file to be governed by only the CDDL
    5.33 +# or only the GPL Version 2, indicate your decision by adding
    5.34 +# "[Contributor] elects to include this software in this distribution
    5.35 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
    5.36 +# single choice of license, a recipient has the option to distribute
    5.37 +# your version of this file under either the CDDL, the GPL Version 2 or
    5.38 +# to extend the choice of license to its licensees as provided above.
    5.39 +# However, if you add GPL Version 2 code and therefore, elected the GPL
    5.40 +# Version 2 license, then the option applies only if the new code is
    5.41 +# made subject to such option by the copyright holder.
    5.42 +
    5.43 +module.jar.dir=lib
    5.44 +javac.source=1.5
    5.45 +javac.compilerargs=-Xlint -Xlint:-serial
    5.46 +spec.version.base=8.0.0
    5.47 +
    5.48 +
    5.49 +javadoc.arch=${basedir}/arch.xml
    5.50 +javadoc.apichanges=${basedir}/apichanges.xml
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/openide.util.lookup/nbproject/project.xml	Mon Dec 14 20:58:39 2009 +0100
     6.3 @@ -0,0 +1,28 @@
     6.4 +<?xml version="1.0" encoding="UTF-8"?>
     6.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
     6.6 +    <type>org.netbeans.modules.apisupport.project</type>
     6.7 +    <configuration>
     6.8 +        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
     6.9 +            <code-name-base>org.openide.util.lookup</code-name-base>
    6.10 +            <module-dependencies/>
    6.11 +            <test-dependencies>
    6.12 +                <test-type>
    6.13 +                    <name>unit</name>
    6.14 +                    <test-dependency>
    6.15 +                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
    6.16 +                        <compile-dependency/>
    6.17 +                    </test-dependency>
    6.18 +                    <test-dependency>
    6.19 +                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
    6.20 +                        <recursive/>
    6.21 +                        <compile-dependency/>
    6.22 +                    </test-dependency>
    6.23 +                </test-type>
    6.24 +            </test-dependencies>
    6.25 +            <public-packages>
    6.26 +                <package>org.openide.util</package>
    6.27 +                <package>org.openide.util.lookup</package>
    6.28 +            </public-packages>
    6.29 +        </data>
    6.30 +    </configuration>
    6.31 +</project>
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/openide.util.lookup/src/META-INF/services/javax.annotation.processing.Processor	Mon Dec 14 20:58:39 2009 +0100
     7.3 @@ -0,0 +1,1 @@
     7.4 +org.netbeans.modules.openide.util.ServiceProviderProcessor
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/AbstractServiceProviderProcessor.java	Mon Dec 14 20:58:39 2009 +0100
     8.3 @@ -0,0 +1,289 @@
     8.4 +/*
     8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     8.6 + *
     8.7 + * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
     8.8 + *
     8.9 + * The contents of this file are subject to the terms of either the GNU
    8.10 + * General Public License Version 2 only ("GPL") or the Common
    8.11 + * Development and Distribution License("CDDL") (collectively, the
    8.12 + * "License"). You may not use this file except in compliance with the
    8.13 + * License. You can obtain a copy of the License at
    8.14 + * http://www.netbeans.org/cddl-gplv2.html
    8.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    8.16 + * specific language governing permissions and limitations under the
    8.17 + * License.  When distributing the software, include this License Header
    8.18 + * Notice in each file and include the License file at
    8.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    8.20 + * particular file as subject to the "Classpath" exception as provided
    8.21 + * by Sun in the GPL Version 2 section of the License file that
    8.22 + * accompanied this code. If applicable, add the following below the
    8.23 + * License Header, with the fields enclosed by brackets [] replaced by
    8.24 + * your own identifying information:
    8.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    8.26 + *
    8.27 + * If you wish your version of this file to be governed by only the CDDL
    8.28 + * or only the GPL Version 2, indicate your decision by adding
    8.29 + * "[Contributor] elects to include this software in this distribution
    8.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    8.31 + * single choice of license, a recipient has the option to distribute
    8.32 + * your version of this file under either the CDDL, the GPL Version 2 or
    8.33 + * to extend the choice of license to its licensees as provided above.
    8.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    8.35 + * Version 2 license, then the option applies only if the new code is
    8.36 + * made subject to such option by the copyright holder.
    8.37 + *
    8.38 + * Contributor(s):
    8.39 + *
    8.40 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
    8.41 + */
    8.42 +
    8.43 +package org.netbeans.modules.openide.util;
    8.44 +
    8.45 +import java.io.BufferedReader;
    8.46 +import java.io.FileNotFoundException;
    8.47 +import java.io.IOException;
    8.48 +import java.io.InputStream;
    8.49 +import java.io.InputStreamReader;
    8.50 +import java.io.OutputStream;
    8.51 +import java.io.OutputStreamWriter;
    8.52 +import java.io.PrintWriter;
    8.53 +import java.lang.annotation.Annotation;
    8.54 +import java.util.ArrayList;
    8.55 +import java.util.HashMap;
    8.56 +import java.util.List;
    8.57 +import java.util.Map;
    8.58 +import java.util.Set;
    8.59 +import java.util.WeakHashMap;
    8.60 +import javax.annotation.processing.AbstractProcessor;
    8.61 +import javax.annotation.processing.ProcessingEnvironment;
    8.62 +import javax.annotation.processing.RoundEnvironment;
    8.63 +import javax.lang.model.element.AnnotationMirror;
    8.64 +import javax.lang.model.element.AnnotationValue;
    8.65 +import javax.lang.model.element.Element;
    8.66 +import javax.lang.model.element.ExecutableElement;
    8.67 +import javax.lang.model.element.Modifier;
    8.68 +import javax.lang.model.element.TypeElement;
    8.69 +import javax.lang.model.type.TypeMirror;
    8.70 +import javax.lang.model.util.ElementFilter;
    8.71 +import javax.tools.Diagnostic.Kind;
    8.72 +import javax.tools.FileObject;
    8.73 +import javax.tools.StandardLocation;
    8.74 +
    8.75 +/**
    8.76 + * Infrastructure for generating {@code META-INF/services/*} and
    8.77 + * {@code META-INF/namedservices/*} registrations from annotations.
    8.78 + */
    8.79 +public abstract class AbstractServiceProviderProcessor extends AbstractProcessor {
    8.80 +
    8.81 +    private final Map<ProcessingEnvironment,Map<String,List<String>>> outputFilesByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<String>>>();
    8.82 +    private final Map<ProcessingEnvironment,Map<String,List<Element>>> originatingElementsByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<Element>>>();
    8.83 +    private final Map<TypeElement,Boolean> verifiedClasses = new WeakHashMap<TypeElement,Boolean>();
    8.84 +
    8.85 +    /** For access by subclasses. */
    8.86 +    protected AbstractServiceProviderProcessor() {}
    8.87 +
    8.88 +    public @Override final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    8.89 +        if (roundEnv.errorRaised()) {
    8.90 +            return false;
    8.91 +        }
    8.92 +        if (roundEnv.processingOver()) {
    8.93 +            writeServices();
    8.94 +            outputFilesByProcessor.clear();
    8.95 +            originatingElementsByProcessor.clear();
    8.96 +            return true;
    8.97 +        } else {
    8.98 +            return handleProcess(annotations, roundEnv);
    8.99 +        }
   8.100 +    }
   8.101 +
   8.102 +    /**
   8.103 +     * The regular body of {@link #process}.
   8.104 +     * Called during regular rounds if there are no outstanding errors.
   8.105 +     * In the last round, one of the processors will write out generated registrations.
   8.106 +     * @param annotations as in {@link #process}
   8.107 +     * @param roundEnv as in {@link #process}
   8.108 +     * @return as in {@link #process}
   8.109 +     */
   8.110 +    protected abstract boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv);
   8.111 +
   8.112 +    /**
   8.113 +     * Register a service.
   8.114 +     * If the class does not have an appropriate signature, an error will be printed and the registration skipped.
   8.115 +     * @param clazz the service implementation type
   8.116 +     * @param annotation the (top-level) annotation registering the service, for diagnostic purposes
   8.117 +     * @param type the type to which the implementation must be assignable
   8.118 +     * @param path a path under which to register, or "" if inapplicable
   8.119 +     * @param position a position at which to register, or {@link Integer#MAX_VALUE} to skip
   8.120 +     * @param supersedes possibly empty list of implementation to supersede
   8.121 +     */
   8.122 +    protected final void register(TypeElement clazz, Class<? extends Annotation> annotation,
   8.123 +            TypeMirror type, String path, int position, String[] supersedes) {
   8.124 +        Boolean verify = verifiedClasses.get(clazz);
   8.125 +        if (verify == null) {
   8.126 +            verify = verifyServiceProviderSignature(clazz, annotation);
   8.127 +            verifiedClasses.put(clazz, verify);
   8.128 +        }
   8.129 +        if (!verify) {
   8.130 +            return;
   8.131 +        }
   8.132 +        String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString();
   8.133 +        String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString();
   8.134 +        if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) {
   8.135 +            AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
   8.136 +            processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface,
   8.137 +                    clazz, ann, findAnnotationValue(ann, "service"));
   8.138 +            return;
   8.139 +        }
   8.140 +        processingEnv.getMessager().printMessage(Kind.NOTE,
   8.141 +                impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : ""));
   8.142 +        String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface;
   8.143 +        {
   8.144 +            Map<String,List<Element>> originatingElements = originatingElementsByProcessor.get(processingEnv);
   8.145 +            if (originatingElements == null) {
   8.146 +                originatingElements = new HashMap<String,List<Element>>();
   8.147 +                originatingElementsByProcessor.put(processingEnv, originatingElements);
   8.148 +            }
   8.149 +            List<Element> origEls = originatingElements.get(rsrc);
   8.150 +            if (origEls == null) {
   8.151 +                origEls = new ArrayList<Element>();
   8.152 +                originatingElements.put(rsrc, origEls);
   8.153 +            }
   8.154 +            origEls.add(clazz);
   8.155 +        }
   8.156 +        Map<String,List<String>> outputFiles = outputFilesByProcessor.get(processingEnv);
   8.157 +        if (outputFiles == null) {
   8.158 +            outputFiles = new HashMap<String,List<String>>();
   8.159 +            outputFilesByProcessor.put(processingEnv, outputFiles);
   8.160 +        }
   8.161 +        List<String> lines = outputFiles.get(rsrc);
   8.162 +        if (lines == null) {
   8.163 +            lines = new ArrayList<String>();
   8.164 +            try {
   8.165 +                try {
   8.166 +                    FileObject in = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", rsrc);
   8.167 +                    in.openInputStream().close();
   8.168 +                    processingEnv.getMessager().printMessage(Kind.ERROR,
   8.169 +                            "Cannot generate " + rsrc + " because it already exists in sources: " + in.toUri());
   8.170 +                    return;
   8.171 +                } catch (FileNotFoundException x) {
   8.172 +                    // Good.
   8.173 +                }
   8.174 +                try {
   8.175 +                    FileObject in = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", rsrc);
   8.176 +                    InputStream is = in.openInputStream();
   8.177 +                    try {
   8.178 +                        BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
   8.179 +                        String line;
   8.180 +                        while ((line = r.readLine()) != null) {
   8.181 +                            lines.add(line);
   8.182 +                        }
   8.183 +                    } finally {
   8.184 +                        is.close();
   8.185 +                    }
   8.186 +                } catch (FileNotFoundException x) {
   8.187 +                    // OK, created for the first time
   8.188 +                }
   8.189 +            } catch (IOException x) {
   8.190 +                processingEnv.getMessager().printMessage(Kind.ERROR, x.toString());
   8.191 +                return;
   8.192 +            }
   8.193 +            outputFiles.put(rsrc, lines);
   8.194 +        }
   8.195 +        int idx = lines.indexOf(impl);
   8.196 +        if (idx != -1) {
   8.197 +            lines.remove(idx);
   8.198 +            while (lines.size() > idx && lines.get(idx).matches("#position=.+|#-.+")) {
   8.199 +                lines.remove(idx);
   8.200 +            }
   8.201 +        }
   8.202 +        lines.add(impl);
   8.203 +        if (position != Integer.MAX_VALUE) {
   8.204 +            lines.add("#position=" + position);
   8.205 +        }
   8.206 +        for (String exclude : supersedes) {
   8.207 +            lines.add("#-" + exclude);
   8.208 +        }
   8.209 +    }
   8.210 +
   8.211 +    /**
   8.212 +     * @param element a source element
   8.213 +     * @param annotation a type of annotation
   8.214 +     * @return the instance of that annotation on the element, or null if not found
   8.215 +     */
   8.216 +    private AnnotationMirror findAnnotationMirror(Element element, Class<? extends Annotation> annotation) {
   8.217 +        for (AnnotationMirror ann : element.getAnnotationMirrors()) {
   8.218 +            if (processingEnv.getElementUtils().getBinaryName((TypeElement) ann.getAnnotationType().asElement()).
   8.219 +                    contentEquals(annotation.getName())) {
   8.220 +                return ann;
   8.221 +            }
   8.222 +        }
   8.223 +        return null;
   8.224 +    }
   8.225 +
   8.226 +    /**
   8.227 +     * @param annotation an annotation instance (null permitted)
   8.228 +     * @param name the name of an attribute of that annotation
   8.229 +     * @return the corresponding value if found
   8.230 +     */
   8.231 +    private AnnotationValue findAnnotationValue(AnnotationMirror annotation, String name) {
   8.232 +        if (annotation != null) {
   8.233 +            for (Map.Entry<? extends ExecutableElement,? extends AnnotationValue> entry : annotation.getElementValues().entrySet()) {
   8.234 +                if (entry.getKey().getSimpleName().contentEquals(name)) {
   8.235 +                    return entry.getValue();
   8.236 +                }
   8.237 +            }
   8.238 +        }
   8.239 +        return null;
   8.240 +    }
   8.241 +
   8.242 +    private final boolean verifyServiceProviderSignature(TypeElement clazz, Class<? extends Annotation> annotation) {
   8.243 +        AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
   8.244 +        if (!clazz.getModifiers().contains(Modifier.PUBLIC)) {
   8.245 +            processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must be public", clazz, ann);
   8.246 +            return false;
   8.247 +        }
   8.248 +        if (clazz.getModifiers().contains(Modifier.ABSTRACT)) {
   8.249 +            processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must not be abstract", clazz, ann);
   8.250 +            return false;
   8.251 +        }
   8.252 +        {
   8.253 +            boolean hasDefaultCtor = false;
   8.254 +            for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
   8.255 +                if (constructor.getModifiers().contains(Modifier.PUBLIC) && constructor.getParameters().isEmpty()) {
   8.256 +                    hasDefaultCtor = true;
   8.257 +                    break;
   8.258 +                }
   8.259 +            }
   8.260 +            if (!hasDefaultCtor) {
   8.261 +                processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must have a public no-argument constructor", clazz, ann);
   8.262 +                return false;
   8.263 +            }
   8.264 +        }
   8.265 +        return true;
   8.266 +    }
   8.267 +
   8.268 +    private void writeServices() {
   8.269 +        for (Map.Entry<ProcessingEnvironment,Map<String,List<String>>> outputFiles : outputFilesByProcessor.entrySet()) {
   8.270 +            for (Map.Entry<String, List<String>> entry : outputFiles.getValue().entrySet()) {
   8.271 +                try {
   8.272 +                    FileObject out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", entry.getKey(),
   8.273 +                            originatingElementsByProcessor.get(outputFiles.getKey()).get(entry.getKey()).toArray(new Element[0]));
   8.274 +                    OutputStream os = out.openOutputStream();
   8.275 +                    try {
   8.276 +                        PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
   8.277 +                        for (String line : entry.getValue()) {
   8.278 +                            w.println(line);
   8.279 +                        }
   8.280 +                        w.flush();
   8.281 +                        w.close();
   8.282 +                    } finally {
   8.283 +                        os.close();
   8.284 +                    }
   8.285 +                } catch (IOException x) {
   8.286 +                    processingEnv.getMessager().printMessage(Kind.ERROR, "Failed to write to " + entry.getKey() + ": " + x.toString());
   8.287 +                }
   8.288 +            }
   8.289 +        }
   8.290 +    }
   8.291 +
   8.292 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/ActiveQueue.java	Mon Dec 14 20:58:39 2009 +0100
     9.3 @@ -0,0 +1,108 @@
     9.4 +package org.netbeans.modules.openide.util;
     9.5 +
     9.6 +import java.lang.ref.Reference;
     9.7 +import java.lang.ref.ReferenceQueue;
     9.8 +import java.util.logging.Level;
     9.9 +import java.util.logging.Logger;
    9.10 +
    9.11 +/**
    9.12 + * Implementation of the active reference queue.
    9.13 + */
    9.14 +public final class ActiveQueue extends ReferenceQueue<Object> implements Runnable {
    9.15 +
    9.16 +    private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
    9.17 +    private static ActiveQueue activeReferenceQueue;
    9.18 +    
    9.19 +    /** number of known outstanding references */
    9.20 +    private int count;
    9.21 +    private boolean deprecated;
    9.22 +
    9.23 +    ActiveQueue(boolean deprecated) {
    9.24 +        super();
    9.25 +        this.deprecated = deprecated;
    9.26 +    }
    9.27 +
    9.28 +    public static synchronized ReferenceQueue<Object> queue() {
    9.29 +        if (activeReferenceQueue == null) {
    9.30 +            activeReferenceQueue = new ActiveQueue(false);
    9.31 +        }
    9.32 +
    9.33 +        activeReferenceQueue.ping();
    9.34 +
    9.35 +        return activeReferenceQueue;
    9.36 +    }
    9.37 +
    9.38 +    @Override
    9.39 +    public Reference<Object> poll() {
    9.40 +        throw new UnsupportedOperationException();
    9.41 +    }
    9.42 +
    9.43 +    @Override
    9.44 +    public Reference<Object> remove(long timeout) throws IllegalArgumentException, InterruptedException {
    9.45 +        throw new InterruptedException();
    9.46 +    }
    9.47 +
    9.48 +    @Override
    9.49 +    public Reference<Object> remove() throws InterruptedException {
    9.50 +        throw new InterruptedException();
    9.51 +    }
    9.52 +
    9.53 +    public void run() {
    9.54 +        while (true) {
    9.55 +            try {
    9.56 +                Reference<?> ref = super.remove(0);
    9.57 +                LOGGER.finer("dequeued reference");
    9.58 +                if (!(ref instanceof Runnable)) {
    9.59 +                    LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass());
    9.60 +                    continue;
    9.61 +                }
    9.62 +                if (deprecated) {
    9.63 +                    LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue");
    9.64 +                }
    9.65 +                // do the cleanup
    9.66 +                try {
    9.67 +                    ((Runnable) ref).run();
    9.68 +                } catch (ThreadDeath td) {
    9.69 +                    throw td;
    9.70 +                } catch (Throwable t) {
    9.71 +                    // Should not happen.
    9.72 +                    // If it happens, it is a bug in client code, notify!
    9.73 +                    LOGGER.log(Level.WARNING, null, t);
    9.74 +                } finally {
    9.75 +                    // to allow GC
    9.76 +                    ref = null;
    9.77 +                }
    9.78 +            } catch (InterruptedException ex) {
    9.79 +                // Can happen during VM shutdown, it seems. Ignore.
    9.80 +                continue;
    9.81 +            }
    9.82 +            synchronized (this) {
    9.83 +                assert count > 0;
    9.84 +                count--;
    9.85 +                if (count == 0) {
    9.86 +                    // We have processed all we have to process (for now at least).
    9.87 +                    // Could be restarted later if ping() called again.
    9.88 +                    // This could also happen in case someone called queue() once and tried
    9.89 +                    // to use it for several references; in that case run() might never be called on
    9.90 +                    // the later ones to be collected. Can't really protect against that situation.
    9.91 +                    // See issue #86625 for details.
    9.92 +                    LOGGER.fine("stopping thread");
    9.93 +                    break;
    9.94 +                }
    9.95 +            }
    9.96 +        }
    9.97 +    }
    9.98 +
    9.99 +    synchronized void ping() {
   9.100 +        if (count == 0) {
   9.101 +            Thread t = new Thread(this, "Active Reference Queue Daemon");
   9.102 +            t.setPriority(Thread.MIN_PRIORITY);
   9.103 +            t.setDaemon(true);
   9.104 +            t.start();
   9.105 +            LOGGER.fine("starting thread");
   9.106 +        } else {
   9.107 +            LOGGER.finer("enqueuing reference");
   9.108 +        }
   9.109 +        count++;
   9.110 +    }
   9.111 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/NamedServicesProvider.java	Mon Dec 14 20:58:39 2009 +0100
    10.3 @@ -0,0 +1,81 @@
    10.4 +/*
    10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 + *
    10.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    10.8 + *
    10.9 + * The contents of this file are subject to the terms of either the GNU
   10.10 + * General Public License Version 2 only ("GPL") or the Common
   10.11 + * Development and Distribution License("CDDL") (collectively, the
   10.12 + * "License"). You may not use this file except in compliance with the
   10.13 + * License. You can obtain a copy of the License at
   10.14 + * http://www.netbeans.org/cddl-gplv2.html
   10.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   10.16 + * specific language governing permissions and limitations under the
   10.17 + * License.  When distributing the software, include this License Header
   10.18 + * Notice in each file and include the License file at
   10.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   10.20 + * particular file as subject to the "Classpath" exception as provided
   10.21 + * by Sun in the GPL Version 2 section of the License file that
   10.22 + * accompanied this code. If applicable, add the following below the
   10.23 + * License Header, with the fields enclosed by brackets [] replaced by
   10.24 + * your own identifying information:
   10.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   10.26 + *
   10.27 + * Contributor(s):
   10.28 + *
   10.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   10.30 + * Software is Sun Microsystems, Inc.
   10.31 + *
   10.32 + * Portions Copyrighted 2006 Sun Microsystems, Inc.
   10.33 + */
   10.34 +
   10.35 +package org.netbeans.modules.openide.util;
   10.36 +
   10.37 +import java.lang.ref.Reference;
   10.38 +import java.lang.ref.WeakReference;
   10.39 +import java.util.Collections;
   10.40 +import java.util.HashMap;
   10.41 +import java.util.Map;
   10.42 +import org.openide.util.Lookup;
   10.43 +import org.openide.util.lookup.Lookups;
   10.44 +
   10.45 +/** Interface for core/startup and core/settings
   10.46 + * to provide lookup over system filesystem.
   10.47 + *
   10.48 + * @author Jaroslav Tulach
   10.49 + */
   10.50 +public abstract class NamedServicesProvider {
   10.51 +
   10.52 +    private static final Map<String,Reference<Lookup>> map = Collections.synchronizedMap(new HashMap<String,Reference<Lookup>>());
   10.53 +    
   10.54 +    public abstract Lookup create(String path);
   10.55 +    
   10.56 +    public static Lookup find(String path) {
   10.57 +        if (!path.endsWith("/")) {
   10.58 +            path = path + "/";
   10.59 +        }
   10.60 +        
   10.61 +        Reference<Lookup> ref = map.get(path);
   10.62 +        Lookup lkp = ref == null ? null : ref.get();
   10.63 +        if (lkp != null) {
   10.64 +            return lkp;
   10.65 +        }
   10.66 +        NamedServicesProvider prov = Lookup.getDefault().lookup(NamedServicesProvider.class);
   10.67 +        if (prov != null && /* avoid stack overflow during initialization */ !path.startsWith(URLStreamHandlerRegistrationProcessor.REGISTRATION_PREFIX)) {
   10.68 +            lkp = prov.create(path);
   10.69 +        } else {
   10.70 +            ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
   10.71 +            if (l == null) {
   10.72 +                l = Thread.currentThread().getContextClassLoader();
   10.73 +                if (l == null) {
   10.74 +                    l = NamedServicesProvider.class.getClassLoader();
   10.75 +                }
   10.76 +            }
   10.77 +            lkp = Lookups.metaInfServices(l, "META-INF/namedservices/" + path);
   10.78 +        }
   10.79 +        
   10.80 +        map.put(path, new WeakReference<Lookup>(lkp));
   10.81 +        return lkp;
   10.82 +    }
   10.83 +    
   10.84 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java	Mon Dec 14 20:58:39 2009 +0100
    11.3 @@ -0,0 +1,173 @@
    11.4 +/*
    11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.6 + *
    11.7 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    11.8 + *
    11.9 + * The contents of this file are subject to the terms of either the GNU
   11.10 + * General Public License Version 2 only ("GPL") or the Common
   11.11 + * Development and Distribution License("CDDL") (collectively, the
   11.12 + * "License"). You may not use this file except in compliance with the
   11.13 + * License. You can obtain a copy of the License at
   11.14 + * http://www.netbeans.org/cddl-gplv2.html
   11.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   11.16 + * specific language governing permissions and limitations under the
   11.17 + * License.  When distributing the software, include this License Header
   11.18 + * Notice in each file and include the License file at
   11.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   11.20 + * particular file as subject to the "Classpath" exception as provided
   11.21 + * by Sun in the GPL Version 2 section of the License file that
   11.22 + * accompanied this code. If applicable, add the following below the
   11.23 + * License Header, with the fields enclosed by brackets [] replaced by
   11.24 + * your own identifying information:
   11.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   11.26 + *
   11.27 + * If you wish your version of this file to be governed by only the CDDL
   11.28 + * or only the GPL Version 2, indicate your decision by adding
   11.29 + * "[Contributor] elects to include this software in this distribution
   11.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   11.31 + * single choice of license, a recipient has the option to distribute
   11.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   11.33 + * to extend the choice of license to its licensees as provided above.
   11.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   11.35 + * Version 2 license, then the option applies only if the new code is
   11.36 + * made subject to such option by the copyright holder.
   11.37 + *
   11.38 + * Contributor(s):
   11.39 + *
   11.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   11.41 + */
   11.42 +
   11.43 +package org.netbeans.modules.openide.util;
   11.44 +
   11.45 +import java.lang.annotation.Annotation;
   11.46 +import java.util.Arrays;
   11.47 +import java.util.Collection;
   11.48 +import java.util.Collections;
   11.49 +import java.util.HashSet;
   11.50 +import java.util.LinkedList;
   11.51 +import java.util.List;
   11.52 +import java.util.Set;
   11.53 +import javax.annotation.processing.Completion;
   11.54 +import javax.annotation.processing.RoundEnvironment;
   11.55 +import javax.annotation.processing.SupportedSourceVersion;
   11.56 +import javax.lang.model.SourceVersion;
   11.57 +import javax.lang.model.element.AnnotationMirror;
   11.58 +import javax.lang.model.element.Element;
   11.59 +import javax.lang.model.element.ExecutableElement;
   11.60 +import javax.lang.model.element.TypeElement;
   11.61 +import javax.lang.model.type.MirroredTypeException;
   11.62 +import javax.lang.model.type.TypeKind;
   11.63 +import javax.lang.model.type.TypeMirror;
   11.64 +import org.openide.util.lookup.ServiceProvider;
   11.65 +import org.openide.util.lookup.ServiceProviders;
   11.66 +
   11.67 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
   11.68 +public class ServiceProviderProcessor extends AbstractServiceProviderProcessor {
   11.69 +
   11.70 +    public @Override Set<String> getSupportedAnnotationTypes() {
   11.71 +        return new HashSet<String>(Arrays.asList(
   11.72 +            ServiceProvider.class.getCanonicalName(),
   11.73 +            ServiceProviders.class.getCanonicalName()
   11.74 +        ));
   11.75 +    }
   11.76 +
   11.77 +    /** public for ServiceLoader */
   11.78 +    public ServiceProviderProcessor() {}
   11.79 +
   11.80 +    protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   11.81 +        for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) {
   11.82 +            TypeElement clazz = (TypeElement) el;
   11.83 +            ServiceProvider sp = clazz.getAnnotation(ServiceProvider.class);
   11.84 +            register(clazz, ServiceProvider.class, sp);
   11.85 +        }
   11.86 +        for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProviders.class)) {
   11.87 +            TypeElement clazz = (TypeElement) el;
   11.88 +            ServiceProviders spp = clazz.getAnnotation(ServiceProviders.class);
   11.89 +            for (ServiceProvider sp : spp.value()) {
   11.90 +                register(clazz, ServiceProviders.class, sp);
   11.91 +            }
   11.92 +        }
   11.93 +        return true;
   11.94 +    }
   11.95 +
   11.96 +    private void register(TypeElement clazz, Class<? extends Annotation> annotation, ServiceProvider svc) {
   11.97 +        try {
   11.98 +            svc.service();
   11.99 +            assert false;
  11.100 +            return;
  11.101 +        } catch (MirroredTypeException e) {
  11.102 +            register(clazz, annotation, e.getTypeMirror(), svc.path(), svc.position(), svc.supersedes());
  11.103 +        }
  11.104 +    }
  11.105 +
  11.106 +    @Override
  11.107 +    public Iterable<? extends Completion> getCompletions(Element annotated, AnnotationMirror annotation, ExecutableElement attr, String userText) {
  11.108 +        if (processingEnv == null || annotated == null || !annotated.getKind().isClass()) {
  11.109 +            return Collections.emptyList();
  11.110 +        }
  11.111 +
  11.112 +        if (   annotation == null
  11.113 +            || !"org.openide.util.lookup.ServiceProvider".contentEquals(((TypeElement) annotation.getAnnotationType().asElement()).getQualifiedName())) {
  11.114 +            return Collections.emptyList();
  11.115 +        }
  11.116 +
  11.117 +        if (!"service".contentEquals(attr.getSimpleName())) {
  11.118 +            return Collections.emptyList();
  11.119 +        }
  11.120 +
  11.121 +        TypeElement jlObject = processingEnv.getElementUtils().getTypeElement("java.lang.Object");
  11.122 +
  11.123 +        if (jlObject == null) {
  11.124 +            return Collections.emptyList();
  11.125 +        }
  11.126 +        
  11.127 +        Collection<Completion> result = new LinkedList<Completion>();
  11.128 +        List<TypeElement> toProcess = new LinkedList<TypeElement>();
  11.129 +
  11.130 +        toProcess.add((TypeElement) annotated);
  11.131 +
  11.132 +        while (!toProcess.isEmpty()) {
  11.133 +            TypeElement c = toProcess.remove(0);
  11.134 +
  11.135 +            result.add(new TypeCompletion(c.getQualifiedName().toString() + ".class"));
  11.136 +
  11.137 +            List<TypeMirror> parents = new LinkedList<TypeMirror>();
  11.138 +
  11.139 +            parents.add(c.getSuperclass());
  11.140 +            parents.addAll(c.getInterfaces());
  11.141 +
  11.142 +            for (TypeMirror tm : parents) {
  11.143 +                if (tm == null || tm.getKind() != TypeKind.DECLARED) {
  11.144 +                    continue;
  11.145 +                }
  11.146 +
  11.147 +                TypeElement type = (TypeElement) processingEnv.getTypeUtils().asElement(tm);
  11.148 +
  11.149 +                if (!jlObject.equals(type)) {
  11.150 +                    toProcess.add(type);
  11.151 +                }
  11.152 +            }
  11.153 +        }
  11.154 +
  11.155 +        return result;
  11.156 +    }
  11.157 +
  11.158 +    private static final class TypeCompletion implements Completion {
  11.159 +
  11.160 +        private final String type;
  11.161 +
  11.162 +        public TypeCompletion(String type) {
  11.163 +            this.type = type;
  11.164 +        }
  11.165 +
  11.166 +        public String getValue() {
  11.167 +            return type;
  11.168 +        }
  11.169 +
  11.170 +        public String getMessage() {
  11.171 +            return null;
  11.172 +        }
  11.173 +        
  11.174 +    }
  11.175 +
  11.176 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/openide.util.lookup/src/org/openide/util/Lookup.java	Mon Dec 14 20:58:39 2009 +0100
    12.3 @@ -0,0 +1,544 @@
    12.4 +/*
    12.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    12.6 + *
    12.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    12.8 + *
    12.9 + * The contents of this file are subject to the terms of either the GNU
   12.10 + * General Public License Version 2 only ("GPL") or the Common
   12.11 + * Development and Distribution License("CDDL") (collectively, the
   12.12 + * "License"). You may not use this file except in compliance with the
   12.13 + * License. You can obtain a copy of the License at
   12.14 + * http://www.netbeans.org/cddl-gplv2.html
   12.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   12.16 + * specific language governing permissions and limitations under the
   12.17 + * License.  When distributing the software, include this License Header
   12.18 + * Notice in each file and include the License file at
   12.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   12.20 + * particular file as subject to the "Classpath" exception as provided
   12.21 + * by Sun in the GPL Version 2 section of the License file that
   12.22 + * accompanied this code. If applicable, add the following below the
   12.23 + * License Header, with the fields enclosed by brackets [] replaced by
   12.24 + * your own identifying information:
   12.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   12.26 + *
   12.27 + * Contributor(s):
   12.28 + *
   12.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   12.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   12.31 + * Microsystems, Inc. All Rights Reserved.
   12.32 + *
   12.33 + * If you wish your version of this file to be governed by only the CDDL
   12.34 + * or only the GPL Version 2, indicate your decision by adding
   12.35 + * "[Contributor] elects to include this software in this distribution
   12.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   12.37 + * single choice of license, a recipient has the option to distribute
   12.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   12.39 + * to extend the choice of license to its licensees as provided above.
   12.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   12.41 + * Version 2 license, then the option applies only if the new code is
   12.42 + * made subject to such option by the copyright holder.
   12.43 + */
   12.44 +
   12.45 +package org.openide.util;
   12.46 +
   12.47 +import java.util.ArrayList;
   12.48 +import java.util.Collection;
   12.49 +import java.util.Collections;
   12.50 +import java.util.Iterator;
   12.51 +import java.util.List;
   12.52 +import java.util.Set;
   12.53 +import org.openide.util.lookup.Lookups;
   12.54 +import org.openide.util.lookup.ProxyLookup;
   12.55 +import org.openide.util.lookup.ServiceProvider;
   12.56 +
   12.57 +/**
   12.58 + * A general registry permitting clients to find instances of services
   12.59 + * (implementation of a given interface).
   12.60 + * This class is inspired by the
   12.61 + * <a href="http://www.jini.org/">Jini</a>
   12.62 + * registration and lookup mechanism. The difference is that the methods do
   12.63 + * not throw checked exceptions (as they usually work only locally and not over the network)
   12.64 + * and that the Lookup API concentrates on the lookup, not on the registration
   12.65 + * (although {@link Lookup#getDefault} is strongly encouraged to support
   12.66 + * {@link Lookups#metaInfServices} for registration in addition to whatever
   12.67 + * else it decides to support).
   12.68 + * <p>
   12.69 + * For a general talk about the idea behind the lookup pattern please see
   12.70 + * <UL>
   12.71 + *      <LI><a href="lookup/doc-files/index.html">The Solution to Communication Between Components</a>
   12.72 + *      page
   12.73 + *      <LI>the introduction to the <a href="lookup/doc-files/lookup-api.html">lookup API via
   12.74 + *      use cases</a>
   12.75 + *      <LI>the examples of <a href="lookup/doc-files/lookup-spi.html">how to write your own lookup</a>
   12.76 + * </UL>
   12.77 + *
   12.78 + * @see org.openide.util.lookup.AbstractLookup
   12.79 + * @see Lookups
   12.80 + * @see LookupListener
   12.81 + * @see LookupEvent
   12.82 + * @author  Jaroslav Tulach
   12.83 + */
   12.84 +public abstract class Lookup {
   12.85 +    /** A dummy lookup that never returns any results.
   12.86 +     */
   12.87 +    public static final Lookup EMPTY = new Empty();
   12.88 +
   12.89 +    /** default instance */
   12.90 +    private static Lookup defaultLookup;
   12.91 +
   12.92 +    /** Empty constructor for use by subclasses. */
   12.93 +    public Lookup() {
   12.94 +    }
   12.95 +
   12.96 +    /** Static method to obtain the global lookup in the whole system.
   12.97 +     * The actual returned implementation can be different in different
   12.98 +     * systems, but the default one is based on
   12.99 +     * {@link org.openide.util.lookup.Lookups#metaInfServices}
  12.100 +     * with the context classloader of the first caller. Each system is
  12.101 +     * adviced to honor this and include some form of <code>metaInfServices</code>
  12.102 +     * implementation in the returned lookup as usage of <code>META-INF/services</code>
  12.103 +     * is a JDK standard.
  12.104 +     *
  12.105 +     * @return the global lookup in the system
  12.106 +     * @see ServiceProvider
  12.107 +     */
  12.108 +    public static synchronized Lookup getDefault() {
  12.109 +        if (defaultLookup != null) {
  12.110 +            return defaultLookup;
  12.111 +        }
  12.112 +
  12.113 +        // You can specify a Lookup impl using a system property if you like.
  12.114 +        String className = System.getProperty("org.openide.util.Lookup" // NOI18N
  12.115 +            );
  12.116 +
  12.117 +        if ("-".equals(className)) { // NOI18N
  12.118 +
  12.119 +            // Suppress even MetaInfServicesLookup.
  12.120 +            return EMPTY;
  12.121 +        }
  12.122 +
  12.123 +        ClassLoader l = Thread.currentThread().getContextClassLoader();
  12.124 +
  12.125 +        try {
  12.126 +            if (className != null) {
  12.127 +                defaultLookup = (Lookup) Class.forName(className, true, l).newInstance();
  12.128 +
  12.129 +                return defaultLookup;
  12.130 +            }
  12.131 +        } catch (Exception e) {
  12.132 +            // do not use ErrorManager because we are in the startup code
  12.133 +            // and ErrorManager might not be ready
  12.134 +            e.printStackTrace();
  12.135 +        }
  12.136 +
  12.137 +        // OK, none specified (successfully) in a system property.
  12.138 +        // Try MetaInfServicesLookup as a default, which may also
  12.139 +        // have a org.openide.util.Lookup line specifying the lookup.
  12.140 +        Lookup misl = Lookups.metaInfServices(l);
  12.141 +        defaultLookup = misl.lookup(Lookup.class);
  12.142 +
  12.143 +        if (defaultLookup != null) {
  12.144 +            return defaultLookup;
  12.145 +        }
  12.146 +
  12.147 +        // You may also specify a Lookup.Provider.
  12.148 +        Lookup.Provider prov = misl.lookup(Lookup.Provider.class);
  12.149 +
  12.150 +        if (prov != null) {
  12.151 +            defaultLookup = Lookups.proxy(prov);
  12.152 +
  12.153 +            return defaultLookup;
  12.154 +        }
  12.155 +
  12.156 +        DefLookup def = new DefLookup();
  12.157 +        def.init(l, misl, false);
  12.158 +        defaultLookup = def;
  12.159 +        def.init(l, misl, true);
  12.160 +        return defaultLookup;
  12.161 +    }
  12.162 +    
  12.163 +    private static final class DefLookup extends ProxyLookup {
  12.164 +        public DefLookup() {
  12.165 +            super(new Lookup[0]);
  12.166 +        }
  12.167 +        
  12.168 +        public void init(ClassLoader loader, Lookup metaInfLookup, boolean addPath) {
  12.169 +            // Had no such line, use simple impl.
  12.170 +            // It does however need to have ClassLoader available or many things will break.
  12.171 +            // Use the thread context classloader in effect now.
  12.172 +            Lookup clLookup = Lookups.singleton(loader);
  12.173 +            List<Lookup> arr = new ArrayList<Lookup>();
  12.174 +            arr.add(metaInfLookup);
  12.175 +            arr.add(clLookup);
  12.176 +            String paths = System.getProperty("org.openide.util.Lookup.paths"); // NOI18N
  12.177 +            if (addPath && paths != null) {
  12.178 +                for (String p : paths.split(":")) { // NOI18N
  12.179 +                    arr.add(Lookups.forPath(p));
  12.180 +                }
  12.181 +            }
  12.182 +            setLookups(arr.toArray(new Lookup[0]));
  12.183 +        }
  12.184 +    }
  12.185 +    
  12.186 +    /** Called from MockServices to reset default lookup in case services change
  12.187 +     */
  12.188 +    private static void resetDefaultLookup() {
  12.189 +        if (defaultLookup instanceof DefLookup) {
  12.190 +            DefLookup def = (DefLookup)defaultLookup;
  12.191 +            ClassLoader l = Thread.currentThread().getContextClassLoader();
  12.192 +            def.init(l, Lookups.metaInfServices(l), true);
  12.193 +        }
  12.194 +    }
  12.195 +
  12.196 +    /** Look up an object matching a given interface.
  12.197 +     * This is the simplest method to use.
  12.198 +     * If more than one object matches, the first will be returned.
  12.199 +     * The template class may be a class or interface; the instance is
  12.200 +     * guaranteed to be assignable to it.
  12.201 +     *
  12.202 +     * @param clazz class of the object we are searching for
  12.203 +     * @return an object implementing the given class or <code>null</code> if no such
  12.204 +     *         implementation is found
  12.205 +     */
  12.206 +    public abstract <T> T lookup(Class<T> clazz);
  12.207 +
  12.208 +    /** The general lookup method. Callers can get list of all instances and classes
  12.209 +     * that match the given <code>template</code>, request more info about
  12.210 +     * them in form of {@link Lookup.Item} and attach a listener to
  12.211 +     * this be notified about changes. The general interface does not
  12.212 +     * specify whether subsequent calls with the same template produce new
  12.213 +     * instance of the {@link Lookup.Result} or return shared instance. The
  12.214 +     * prefered behaviour however is to return shared one.
  12.215 +     *
  12.216 +     * @param template a template describing the services to look for
  12.217 +     * @return an object containing the results
  12.218 +     */
  12.219 +    public abstract <T> Result<T> lookup(Template<T> template);
  12.220 +
  12.221 +    /** Look up the first item matching a given template.
  12.222 +     * Includes not only the instance but other associated information.
  12.223 +     * @param template the template to check
  12.224 +     * @return a matching item or <code>null</code>
  12.225 +     *
  12.226 +     * @since 1.8
  12.227 +     */
  12.228 +    public <T> Item<T> lookupItem(Template<T> template) {
  12.229 +        Result<T> res = lookup(template);
  12.230 +        Iterator<? extends Item<T>> it = res.allItems().iterator();
  12.231 +        return it.hasNext() ? it.next() : null;
  12.232 +    }
  12.233 +
  12.234 +    /**
  12.235 +     * Find a result corresponding to a given class.
  12.236 +     * Equivalent to calling {@link #lookup(Lookup.Template)} but slightly more convenient.
  12.237 +     * Subclasses may override this method to produce the same semantics more efficiently.
  12.238 +     * @param clazz the supertype of the result
  12.239 +     * @return a live object representing instances of that type
  12.240 +     * @since org.openide.util 6.10
  12.241 +     */
  12.242 +    public <T> Lookup.Result<T> lookupResult(Class<T> clazz) {
  12.243 +        return lookup(new Lookup.Template<T>(clazz));
  12.244 +    }
  12.245 +
  12.246 +    /**
  12.247 +     * Find all instances corresponding to a given class.
  12.248 +     * Equivalent to calling {@link #lookupResult} and asking for {@link Lookup.Result#allInstances} but slightly more convenient.
  12.249 +     * Subclasses may override this method to produce the same semantics more efficiently.
  12.250 +     * <div class="nonnormative">
  12.251 +     * <p>Example usage:</p>
  12.252 +     * <pre>
  12.253 +     * for (MyService svc : Lookup.getDefault().lookupAll(MyService.class)) {
  12.254 +     *     svc.useMe();
  12.255 +     * }
  12.256 +     * </pre>
  12.257 +     * </div>
  12.258 +     * @param clazz the supertype of the result
  12.259 +     * @return all currently available instances of that type
  12.260 +     * @since org.openide.util 6.10
  12.261 +     */
  12.262 +    public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
  12.263 +        return lookupResult(clazz).allInstances();
  12.264 +    }
  12.265 +
  12.266 +    /**
  12.267 +     * Objects implementing interface Lookup.Provider are capable of
  12.268 +     * and willing to provide a lookup (usually bound to the object).
  12.269 +     * @since 3.6
  12.270 +     */
  12.271 +    public interface Provider {
  12.272 +        /**
  12.273 +         * Returns lookup associated with the object.
  12.274 +         * @return fully initialized lookup instance provided by this object
  12.275 +         */
  12.276 +        Lookup getLookup();
  12.277 +    }
  12.278 +
  12.279 +    /*
  12.280 +     * I expect this class to grow in the future, but for now, it is
  12.281 +     * enough to start with something simple.
  12.282 +     */
  12.283 +
  12.284 +    /** Template defining a pattern to filter instances by.
  12.285 +     */
  12.286 +    public static final class Template<T> extends Object {
  12.287 +        /** cached hash code */
  12.288 +        private int hashCode;
  12.289 +
  12.290 +        /** type of the service */
  12.291 +        private Class<T> type;
  12.292 +
  12.293 +        /** identity to search for */
  12.294 +        private String id;
  12.295 +
  12.296 +        /** instance to search for */
  12.297 +        private T instance;
  12.298 +
  12.299 +        /** General template to find all possible instances.
  12.300 +         * @deprecated Use <code>new Template (Object.class)</code> which
  12.301 +         *   is going to be better typed with JDK1.5 templates and should produce
  12.302 +         *   the same result.
  12.303 +         */
  12.304 +        @Deprecated
  12.305 +        public Template() {
  12.306 +            this(null);
  12.307 +        }
  12.308 +
  12.309 +        /** Create a simple template matching by class.
  12.310 +         * @param type the class of service we are looking for (subclasses will match)
  12.311 +         */
  12.312 +        public Template(Class<T> type) {
  12.313 +            this(type, null, null);
  12.314 +        }
  12.315 +
  12.316 +        /** Constructor to create new template.
  12.317 +         * @param type the class of service we are looking for or <code>null</code> to leave unspecified
  12.318 +         * @param id the ID of the item/service we are looking for or <code>null</code> to leave unspecified
  12.319 +         * @param instance a specific known instance to look for or <code>null</code> to leave unspecified
  12.320 +         */
  12.321 +        public Template(Class<T> type, String id, T instance) {
  12.322 +            this.type = extractType(type);
  12.323 +            this.id = id;
  12.324 +            this.instance = instance;
  12.325 +        }
  12.326 +
  12.327 +        @SuppressWarnings("unchecked")
  12.328 +        private Class<T> extractType(Class<T> type) {
  12.329 +            return (type == null) ? (Class<T>)Object.class : type;
  12.330 +        }
  12.331 +
  12.332 +        /** Get the class (or superclass or interface) to search for.
  12.333 +         * If it was not specified in the constructor, <code>Object</code> is used as
  12.334 +         * this will match any instance.
  12.335 +         * @return the class to search for
  12.336 +         */
  12.337 +        public Class<T> getType() {
  12.338 +            return type;
  12.339 +        }
  12.340 +
  12.341 +        /** Get the persistent identifier being searched for, if any.
  12.342 +         * @return the ID or <code>null</code>
  12.343 +         * @see Lookup.Item#getId
  12.344 +         *
  12.345 +         * @since 1.8
  12.346 +         */
  12.347 +        public String getId() {
  12.348 +            return id;
  12.349 +        }
  12.350 +
  12.351 +        /** Get the specific instance being searched for, if any.
  12.352 +         * Most useful for finding an <code>Item</code> when the instance
  12.353 +         * is already known.
  12.354 +         *
  12.355 +         * @return the object to find or <code>null</code>
  12.356 +         *
  12.357 +         * @since 1.8
  12.358 +         */
  12.359 +        public T getInstance() {
  12.360 +            return instance;
  12.361 +        }
  12.362 +
  12.363 +        /* Computes hashcode for this template. The hashcode is cached.
  12.364 +         * @return hashcode
  12.365 +         */
  12.366 +        @Override
  12.367 +        public int hashCode() {
  12.368 +            if (hashCode != 0) {
  12.369 +                return hashCode;
  12.370 +            }
  12.371 +
  12.372 +            hashCode = ((type == null) ? 1 : type.hashCode()) + ((id == null) ? 2 : id.hashCode()) +
  12.373 +                ((instance == null) ? 3 : 0);
  12.374 +
  12.375 +            return hashCode;
  12.376 +        }
  12.377 +
  12.378 +        /* Checks whether two templates represent the same query.
  12.379 +         * @param obj another template to check
  12.380 +         * @return true if so, false otherwise
  12.381 +         */
  12.382 +        @Override
  12.383 +        public boolean equals(Object obj) {
  12.384 +            if (!(obj instanceof Template)) {
  12.385 +                return false;
  12.386 +            }
  12.387 +
  12.388 +            Template t = (Template) obj;
  12.389 +
  12.390 +            if (hashCode() != t.hashCode()) {
  12.391 +                // this is an optimalization - the hashCodes should have been
  12.392 +                // precomputed
  12.393 +                return false;
  12.394 +            }
  12.395 +
  12.396 +            if (type != t.type) {
  12.397 +                return false;
  12.398 +            }
  12.399 +
  12.400 +            if (id == null) {
  12.401 +                if (t.id != null) {
  12.402 +                    return false;
  12.403 +                }
  12.404 +            } else {
  12.405 +                if (!id.equals(t.id)) {
  12.406 +                    return false;
  12.407 +                }
  12.408 +            }
  12.409 +
  12.410 +            if (instance == null) {
  12.411 +                return (t.instance == null);
  12.412 +            } else {
  12.413 +                return instance.equals(t.instance);
  12.414 +            }
  12.415 +        }
  12.416 +
  12.417 +        /* for debugging */
  12.418 +        @Override
  12.419 +        public String toString() {
  12.420 +            return "Lookup.Template[type=" + type + ",id=" + id + ",instance=" + instance + "]"; // NOI18N
  12.421 +        }
  12.422 +    }
  12.423 +
  12.424 +    /** Result of a lookup request.
  12.425 +     * Allows access to all matching instances at once.
  12.426 +     * Also permits listening to changes in the result.
  12.427 +     * Result can contain duplicate items.
  12.428 +     */
  12.429 +    public static abstract class Result<T> extends Object {
  12.430 +        /** Registers a listener that is invoked when there is a possible
  12.431 +         * change in this result.
  12.432 +         *
  12.433 +         * @param l the listener to add
  12.434 +         */
  12.435 +        public abstract void addLookupListener(LookupListener l);
  12.436 +
  12.437 +        /** Unregisters a listener previously added.
  12.438 +         * @param l the listener to remove
  12.439 +         */
  12.440 +        public abstract void removeLookupListener(LookupListener l);
  12.441 +
  12.442 +        /** Get all instances in the result. The return value type
  12.443 +         * should be List instead of Collection, but it is too late to change it.
  12.444 +         * @return unmodifiable collection of all instances that will never change its content
  12.445 +         */
  12.446 +        public abstract Collection<? extends T> allInstances();
  12.447 +
  12.448 +        /** Get all classes represented in the result.
  12.449 +         * That is, the set of concrete classes
  12.450 +         * used by instances present in the result.
  12.451 +         * All duplicate classes will be omitted.
  12.452 +         * @return unmodifiable set of <code>Class</code> objects that will never change its content
  12.453 +         *
  12.454 +         * @since 1.8
  12.455 +         */
  12.456 +        public Set<Class<? extends T>> allClasses() {
  12.457 +            return Collections.emptySet();
  12.458 +        }
  12.459 +
  12.460 +        /** Get all registered items.
  12.461 +         * This should include all pairs of instances together
  12.462 +         * with their classes, IDs, and so on. The return value type
  12.463 +         * should be List instead of Collection, but it is too late to change it.
  12.464 +         * @return unmodifiable collection of {@link Lookup.Item} that will never change its content
  12.465 +         *
  12.466 +         * @since 1.8
  12.467 +         */
  12.468 +        public Collection<? extends Item<T>> allItems() {
  12.469 +            return Collections.emptyList();
  12.470 +        }
  12.471 +    }
  12.472 +
  12.473 +    /** A single item in a lookup result.
  12.474 +     * This wrapper provides unified access to not just the instance,
  12.475 +     * but its class, a possible persistent identifier, and so on.
  12.476 +     *
  12.477 +     * @since 1.25
  12.478 +     */
  12.479 +    public static abstract class Item<T> extends Object {
  12.480 +        /** Get the instance itself.
  12.481 +         * @return the instance or null if the instance cannot be created
  12.482 +         */
  12.483 +        public abstract T getInstance();
  12.484 +
  12.485 +        /** Get the implementing class of the instance.
  12.486 +         * @return the class of the item
  12.487 +         */
  12.488 +        public abstract Class<? extends T> getType();
  12.489 +
  12.490 +        // XXX can it be null??
  12.491 +
  12.492 +        /** Get a persistent indentifier for the item.
  12.493 +         * This identifier should uniquely represent the item
  12.494 +         * within its containing lookup (and if possible within the
  12.495 +         * global lookup as a whole). For example, it might represent
  12.496 +         * the source of the instance as a file name. The ID may be
  12.497 +         * persisted and in a later session used to find the same instance
  12.498 +         * as was encountered earlier, by means of passing it into a
  12.499 +         * lookup template.
  12.500 +         *
  12.501 +         * @return a string ID of the item
  12.502 +         */
  12.503 +        public abstract String getId();
  12.504 +
  12.505 +        /** Get a human presentable name for the item.
  12.506 +         * This might be used when summarizing all the items found in a
  12.507 +         * lookup result in some part of a GUI.
  12.508 +         * @return the string suitable for presenting the object to a user
  12.509 +         */
  12.510 +        public abstract String getDisplayName();
  12.511 +
  12.512 +        /* show ID for debugging */
  12.513 +        @Override
  12.514 +        public String toString() {
  12.515 +            return getId();
  12.516 +        }
  12.517 +    }
  12.518 +
  12.519 +    //
  12.520 +    // Implementation of the default lookup
  12.521 +    //
  12.522 +    private static final class Empty extends Lookup {
  12.523 +        private static final Result NO_RESULT = new Result() {
  12.524 +                public void addLookupListener(LookupListener l) {
  12.525 +                }
  12.526 +
  12.527 +                public void removeLookupListener(LookupListener l) {
  12.528 +                }
  12.529 +
  12.530 +                public Collection allInstances() {
  12.531 +                    return Collections.EMPTY_SET;
  12.532 +                }
  12.533 +            };
  12.534 +
  12.535 +        Empty() {
  12.536 +        }
  12.537 +
  12.538 +        public <T> T lookup(Class<T> clazz) {
  12.539 +            return null;
  12.540 +        }
  12.541 +
  12.542 +        @SuppressWarnings("unchecked")
  12.543 +        public <T> Result<T> lookup(Template<T> template) {
  12.544 +            return NO_RESULT;
  12.545 +        }
  12.546 +    }
  12.547 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/openide.util.lookup/src/org/openide/util/LookupEvent.java	Mon Dec 14 20:58:39 2009 +0100
    13.3 @@ -0,0 +1,57 @@
    13.4 +/*
    13.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    13.6 + *
    13.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    13.8 + *
    13.9 + * The contents of this file are subject to the terms of either the GNU
   13.10 + * General Public License Version 2 only ("GPL") or the Common
   13.11 + * Development and Distribution License("CDDL") (collectively, the
   13.12 + * "License"). You may not use this file except in compliance with the
   13.13 + * License. You can obtain a copy of the License at
   13.14 + * http://www.netbeans.org/cddl-gplv2.html
   13.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   13.16 + * specific language governing permissions and limitations under the
   13.17 + * License.  When distributing the software, include this License Header
   13.18 + * Notice in each file and include the License file at
   13.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   13.20 + * particular file as subject to the "Classpath" exception as provided
   13.21 + * by Sun in the GPL Version 2 section of the License file that
   13.22 + * accompanied this code. If applicable, add the following below the
   13.23 + * License Header, with the fields enclosed by brackets [] replaced by
   13.24 + * your own identifying information:
   13.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   13.26 + *
   13.27 + * Contributor(s):
   13.28 + *
   13.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   13.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   13.31 + * Microsystems, Inc. All Rights Reserved.
   13.32 + *
   13.33 + * If you wish your version of this file to be governed by only the CDDL
   13.34 + * or only the GPL Version 2, indicate your decision by adding
   13.35 + * "[Contributor] elects to include this software in this distribution
   13.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   13.37 + * single choice of license, a recipient has the option to distribute
   13.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   13.39 + * to extend the choice of license to its licensees as provided above.
   13.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   13.41 + * Version 2 license, then the option applies only if the new code is
   13.42 + * made subject to such option by the copyright holder.
   13.43 + */
   13.44 +package org.openide.util;
   13.45 +
   13.46 +import java.util.*;
   13.47 +
   13.48 +
   13.49 +/** An event describing the change in the lookup's result.
   13.50 + *
   13.51 + * @author  Jaroslav Tulach
   13.52 + */
   13.53 +public final class LookupEvent extends EventObject {
   13.54 +    /** Create a new lookup event.
   13.55 +     * @param source the lookup result which has changed
   13.56 +     */
   13.57 +    public LookupEvent(Lookup.Result source) {
   13.58 +        super(source);
   13.59 +    }
   13.60 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/openide.util.lookup/src/org/openide/util/LookupListener.java	Mon Dec 14 20:58:39 2009 +0100
    14.3 @@ -0,0 +1,59 @@
    14.4 +/*
    14.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    14.6 + *
    14.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    14.8 + *
    14.9 + * The contents of this file are subject to the terms of either the GNU
   14.10 + * General Public License Version 2 only ("GPL") or the Common
   14.11 + * Development and Distribution License("CDDL") (collectively, the
   14.12 + * "License"). You may not use this file except in compliance with the
   14.13 + * License. You can obtain a copy of the License at
   14.14 + * http://www.netbeans.org/cddl-gplv2.html
   14.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   14.16 + * specific language governing permissions and limitations under the
   14.17 + * License.  When distributing the software, include this License Header
   14.18 + * Notice in each file and include the License file at
   14.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   14.20 + * particular file as subject to the "Classpath" exception as provided
   14.21 + * by Sun in the GPL Version 2 section of the License file that
   14.22 + * accompanied this code. If applicable, add the following below the
   14.23 + * License Header, with the fields enclosed by brackets [] replaced by
   14.24 + * your own identifying information:
   14.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   14.26 + *
   14.27 + * Contributor(s):
   14.28 + *
   14.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   14.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   14.31 + * Microsystems, Inc. All Rights Reserved.
   14.32 + *
   14.33 + * If you wish your version of this file to be governed by only the CDDL
   14.34 + * or only the GPL Version 2, indicate your decision by adding
   14.35 + * "[Contributor] elects to include this software in this distribution
   14.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   14.37 + * single choice of license, a recipient has the option to distribute
   14.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   14.39 + * to extend the choice of license to its licensees as provided above.
   14.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   14.41 + * Version 2 license, then the option applies only if the new code is
   14.42 + * made subject to such option by the copyright holder.
   14.43 + */
   14.44 +package org.openide.util;
   14.45 +
   14.46 +import java.util.*;
   14.47 +
   14.48 +
   14.49 +/** General listener for changes in lookup.
   14.50 + *
   14.51 + * @author  Jaroslav Tulach
   14.52 + */
   14.53 +public interface LookupListener extends EventListener {
   14.54 +    /** A change in lookup occured. Please note that this method
   14.55 +     * should never block since it might be called from lookup implementation
   14.56 +     * internal threads. If you block here you are in risk that the thread
   14.57 +     * you wait for might in turn to wait for the lookup internal thread to
   14.58 +     * finish its work.
   14.59 +     * @param ev event describing the change
   14.60 +     */
   14.61 +    public void resultChanged(LookupEvent ev);
   14.62 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ALPairComparator.java	Mon Dec 14 20:58:39 2009 +0100
    15.3 @@ -0,0 +1,88 @@
    15.4 +/*
    15.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    15.6 + *
    15.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    15.8 + *
    15.9 + * The contents of this file are subject to the terms of either the GNU
   15.10 + * General Public License Version 2 only ("GPL") or the Common
   15.11 + * Development and Distribution License("CDDL") (collectively, the
   15.12 + * "License"). You may not use this file except in compliance with the
   15.13 + * License. You can obtain a copy of the License at
   15.14 + * http://www.netbeans.org/cddl-gplv2.html
   15.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   15.16 + * specific language governing permissions and limitations under the
   15.17 + * License.  When distributing the software, include this License Header
   15.18 + * Notice in each file and include the License file at
   15.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   15.20 + * particular file as subject to the "Classpath" exception as provided
   15.21 + * by Sun in the GPL Version 2 section of the License file that
   15.22 + * accompanied this code. If applicable, add the following below the
   15.23 + * License Header, with the fields enclosed by brackets [] replaced by
   15.24 + * your own identifying information:
   15.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   15.26 + *
   15.27 + * Contributor(s):
   15.28 + *
   15.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   15.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   15.31 + * Microsystems, Inc. All Rights Reserved.
   15.32 + *
   15.33 + * If you wish your version of this file to be governed by only the CDDL
   15.34 + * or only the GPL Version 2, indicate your decision by adding
   15.35 + * "[Contributor] elects to include this software in this distribution
   15.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   15.37 + * single choice of license, a recipient has the option to distribute
   15.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   15.39 + * to extend the choice of license to its licensees as provided above.
   15.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   15.41 + * Version 2 license, then the option applies only if the new code is
   15.42 + * made subject to such option by the copyright holder.
   15.43 + */
   15.44 +package org.openide.util.lookup;
   15.45 +
   15.46 +import java.util.Comparator;
   15.47 +import org.openide.util.lookup.AbstractLookup.Pair;
   15.48 +
   15.49 +
   15.50 +/** Implementation of comparator for AbstractLookup.Pair
   15.51 + *
   15.52 + * @author  Jaroslav Tulach
   15.53 + */
   15.54 +final class ALPairComparator implements Comparator<Pair<?>> {
   15.55 +    public static final Comparator<Pair<?>> DEFAULT = new ALPairComparator();
   15.56 +
   15.57 +    /** Creates a new instance of ALPairComparator */
   15.58 +    private ALPairComparator() {
   15.59 +    }
   15.60 +
   15.61 +    /** Compares two items.
   15.62 +    */
   15.63 +    public int compare(Pair<?> i1, Pair<?> i2) {
   15.64 +        int result = i1.getIndex() - i2.getIndex();
   15.65 +
   15.66 +        if (result == 0) {
   15.67 +            if (i1 != i2) {
   15.68 +                java.io.ByteArrayOutputStream bs = new java.io.ByteArrayOutputStream();
   15.69 +                java.io.PrintStream ps = new java.io.PrintStream(bs);
   15.70 +
   15.71 +                ps.println(
   15.72 +                    "Duplicate pair in tree" + // NOI18N
   15.73 +                    "Pair1: " + i1 + " pair2: " + i2 + " index1: " + i1.getIndex() + " index2: " +
   15.74 +                    i2.getIndex() // NOI18N
   15.75 +                     +" item1: " + i1.getInstance() + " item2: " + i2.getInstance() // NOI18N
   15.76 +                     +" id1: " + Integer.toHexString(System.identityHashCode(i1)) // NOI18N
   15.77 +                     +" id2: " + Integer.toHexString(System.identityHashCode(i2)) // NOI18N
   15.78 +                );
   15.79 +
   15.80 +                //                print (ps, false);
   15.81 +                ps.close();
   15.82 +
   15.83 +                throw new IllegalStateException(bs.toString());
   15.84 +            }
   15.85 +
   15.86 +            return 0;
   15.87 +        }
   15.88 +
   15.89 +        return result;
   15.90 +    }
   15.91 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/AbstractLookup.java	Mon Dec 14 20:58:39 2009 +0100
    16.3 @@ -0,0 +1,1467 @@
    16.4 +/*
    16.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    16.6 + *
    16.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    16.8 + *
    16.9 + * The contents of this file are subject to the terms of either the GNU
   16.10 + * General Public License Version 2 only ("GPL") or the Common
   16.11 + * Development and Distribution License("CDDL") (collectively, the
   16.12 + * "License"). You may not use this file except in compliance with the
   16.13 + * License. You can obtain a copy of the License at
   16.14 + * http://www.netbeans.org/cddl-gplv2.html
   16.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   16.16 + * specific language governing permissions and limitations under the
   16.17 + * License.  When distributing the software, include this License Header
   16.18 + * Notice in each file and include the License file at
   16.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   16.20 + * particular file as subject to the "Classpath" exception as provided
   16.21 + * by Sun in the GPL Version 2 section of the License file that
   16.22 + * accompanied this code. If applicable, add the following below the
   16.23 + * License Header, with the fields enclosed by brackets [] replaced by
   16.24 + * your own identifying information:
   16.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   16.26 + *
   16.27 + * Contributor(s):
   16.28 + *
   16.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   16.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   16.31 + * Microsystems, Inc. All Rights Reserved.
   16.32 + *
   16.33 + * If you wish your version of this file to be governed by only the CDDL
   16.34 + * or only the GPL Version 2, indicate your decision by adding
   16.35 + * "[Contributor] elects to include this software in this distribution
   16.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   16.37 + * single choice of license, a recipient has the option to distribute
   16.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   16.39 + * to extend the choice of license to its licensees as provided above.
   16.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   16.41 + * Version 2 license, then the option applies only if the new code is
   16.42 + * made subject to such option by the copyright holder.
   16.43 + */
   16.44 +package org.openide.util.lookup;
   16.45 +
   16.46 +import java.io.PrintStream;
   16.47 +import org.openide.util.Lookup;
   16.48 +import org.openide.util.LookupEvent;
   16.49 +import org.openide.util.LookupListener;
   16.50 +
   16.51 +import java.io.IOException;
   16.52 +import java.io.ObjectOutputStream;
   16.53 +import java.io.Serializable;
   16.54 +
   16.55 +import java.lang.ref.ReferenceQueue;
   16.56 +import java.lang.ref.WeakReference;
   16.57 +import java.util.ArrayList;
   16.58 +import java.util.Arrays;
   16.59 +import java.util.Collection;
   16.60 +import java.util.Collections;
   16.61 +import java.util.Enumeration;
   16.62 +import java.util.HashMap;
   16.63 +import java.util.HashSet;
   16.64 +import java.util.Iterator;
   16.65 +import java.util.LinkedHashSet;
   16.66 +import java.util.Map;
   16.67 +import java.util.Set;
   16.68 +import java.util.TreeSet;
   16.69 +
   16.70 +import java.util.concurrent.Executor;
   16.71 +import org.netbeans.modules.openide.util.ActiveQueue;
   16.72 +
   16.73 +
   16.74 +/** Implementation of the lookup from OpenAPIs that is based on the
   16.75 + * introduction of Item. This class should provide the default way
   16.76 + * of how to store (Class, Object) pairs in the lookups. It offers
   16.77 + * protected methods for subclasses to register the pairs.
   16.78 + * <p>Serializable since 3.27.
   16.79 + * @author  Jaroslav Tulach
   16.80 + * @since 1.9
   16.81 + */
   16.82 +public class AbstractLookup extends Lookup implements Serializable {
   16.83 +    static final long serialVersionUID = 5L;
   16.84 +
   16.85 +    /** lock for initialization of the maps of lookups */
   16.86 +    private static final Object treeLock = new Object();
   16.87 +
   16.88 +    /** the tree that registers all items (or Integer as a treshold size) */
   16.89 +    private Object tree;
   16.90 +
   16.91 +    /** count of items in to lookup */
   16.92 +    private int count;
   16.93 +
   16.94 +    /** Constructor to create this lookup and associate it with given
   16.95 +     * Content. The content than allows the creator to invoke protected
   16.96 +     * methods which are not accessible for any other user of the lookup.
   16.97 +     *
   16.98 +     * @param content the content to assciate with
   16.99 +     *
  16.100 +     * @since 1.25
  16.101 +     */
  16.102 +    public AbstractLookup(Content content) {
  16.103 +        content.attach(this);
  16.104 +    }
  16.105 +
  16.106 +    /** Constructor for testing purposes that allows specification of storage
  16.107 +     * as mechanism as well.
  16.108 +     */
  16.109 +    AbstractLookup(Content content, Storage<?> storage) {
  16.110 +        this(content);
  16.111 +        this.tree = storage;
  16.112 +        initialize();
  16.113 +    }
  16.114 +
  16.115 +    /** Constructor for testing purposes that allows specification of storage
  16.116 +     * as mechanism as well.
  16.117 +     * @param trashhold number of Pair to "remain small"
  16.118 +     */
  16.119 +    AbstractLookup(Content content, Integer trashhold) {
  16.120 +        this(content);
  16.121 +        this.tree = trashhold;
  16.122 +    }
  16.123 +
  16.124 +    /** Default constructor for subclasses that do not need to provide a content
  16.125 +     */
  16.126 +    protected AbstractLookup() {
  16.127 +    }
  16.128 +
  16.129 +    @Override
  16.130 +    public String toString() {
  16.131 +        if (tree instanceof Storage) {
  16.132 +            return "AbstractLookup" + lookup(new Lookup.Template<Object>(Object.class)).allItems(); // NOI18N
  16.133 +        } else {
  16.134 +            return super.toString();
  16.135 +        }
  16.136 +    }
  16.137 +
  16.138 +    /** Entres the storage management system.
  16.139 +     */
  16.140 +    @SuppressWarnings("unchecked")
  16.141 +    private <T> AbstractLookup.Storage<T> enterStorage() {
  16.142 +        for (;;) {
  16.143 +            synchronized (treeLock) {
  16.144 +                if (tree instanceof AbstractLookup.Storage) {
  16.145 +                    if (tree instanceof DelegatingStorage) {
  16.146 +                        // somebody is using the lookup right now
  16.147 +                        DelegatingStorage del = (DelegatingStorage) tree;
  16.148 +
  16.149 +                        // check whether there is not access from the same 
  16.150 +                        // thread (can throw exception)
  16.151 +                        del.checkForTreeModification();
  16.152 +
  16.153 +                        try {
  16.154 +                            treeLock.wait();
  16.155 +                        } catch (InterruptedException ex) {
  16.156 +                            // ignore and go on
  16.157 +                        }
  16.158 +
  16.159 +                        continue;
  16.160 +                    } else {
  16.161 +                        // ok, tree is initialized and nobody is using it yet
  16.162 +                        tree = new DelegatingStorage((Storage<T>) tree);
  16.163 +
  16.164 +                        return (Storage<T>) tree;
  16.165 +                    }
  16.166 +                }
  16.167 +
  16.168 +                // first time initialization of the tree
  16.169 +                if (tree instanceof Integer) {
  16.170 +                    tree = new ArrayStorage((Integer) tree);
  16.171 +                } else {
  16.172 +                    tree = new ArrayStorage();
  16.173 +                }
  16.174 +            }
  16.175 +
  16.176 +            // the tree has not yet been initilized, initialize and go on again
  16.177 +            initialize();
  16.178 +        }
  16.179 +    }
  16.180 +
  16.181 +    /** Exists tree ownership.
  16.182 +     */
  16.183 +    private AbstractLookup.Storage exitStorage() {
  16.184 +        synchronized (treeLock) {
  16.185 +            AbstractLookup.Storage stor = ((DelegatingStorage) tree).exitDelegate();
  16.186 +            tree = stor;
  16.187 +            treeLock.notifyAll();
  16.188 +
  16.189 +            return stor;
  16.190 +        }
  16.191 +    }
  16.192 +
  16.193 +    /** Method for subclasses to initialize them selves.
  16.194 +     */
  16.195 +    protected void initialize() {
  16.196 +    }
  16.197 +
  16.198 +    /** Notifies subclasses that a query is about to be processed.
  16.199 +     * @param template the template
  16.200 +     */
  16.201 +    protected void beforeLookup(Template<?> template) {
  16.202 +    }
  16.203 +
  16.204 +    /** The method to add instance to the lookup with.
  16.205 +     * @param pair class/instance pair
  16.206 +     */
  16.207 +    protected final void addPair(Pair<?> pair) {
  16.208 +        addPairImpl(pair, null);
  16.209 +    }
  16.210 +
  16.211 +    /** The method to add instance to the lookup with.
  16.212 +     * @param pair class/instance pair
  16.213 +     * @param notifyIn the executor that will handle the notification of events
  16.214 +     * @since 7.16
  16.215 +     */
  16.216 +    protected final void addPair(Pair<?> pair, Executor notifyIn) {
  16.217 +        addPairImpl(pair, notifyIn);
  16.218 +    }
  16.219 +
  16.220 +    private final <Transaction> void addPairImpl(Pair<?> pair, Executor notifyIn) {
  16.221 +        HashSet<R> toNotify = new HashSet<R>();
  16.222 +
  16.223 +        AbstractLookup.Storage<Transaction> t = enterStorage();
  16.224 +        Transaction transaction = null;
  16.225 +
  16.226 +        try {
  16.227 +            transaction = t.beginTransaction(-2);
  16.228 +
  16.229 +            if (t.add(pair, transaction)) {
  16.230 +                try {
  16.231 +                    pair.setIndex(t, count++);
  16.232 +                } catch (IllegalStateException ex) {
  16.233 +                    // remove the pair
  16.234 +                    t.remove(pair, transaction);
  16.235 +
  16.236 +                    // rethrow the exception
  16.237 +                    throw ex;
  16.238 +                }
  16.239 +
  16.240 +                // if the pair is newly added and was not there before
  16.241 +                t.endTransaction(transaction, toNotify);
  16.242 +            } else {
  16.243 +                // just finish the process by calling endTransaction
  16.244 +                t.endTransaction(transaction, new HashSet<R>());
  16.245 +            }
  16.246 +        } finally {
  16.247 +            exitStorage();
  16.248 +        }
  16.249 +
  16.250 +        notifyIn(notifyIn, toNotify);
  16.251 +    }
  16.252 +
  16.253 +    /** Remove instance.
  16.254 +     * @param pair class/instance pair
  16.255 +     */
  16.256 +    protected final void removePair(Pair<?> pair) {
  16.257 +        removePairImpl(pair, null);
  16.258 +    }
  16.259 +    /** Remove instance.
  16.260 +     * @param pair class/instance pair
  16.261 +     * @param notifyIn the executor that will handle the notification of events
  16.262 +     * @since 7.16
  16.263 +     */
  16.264 +    protected final void removePair(Pair<?> pair, Executor notifyIn) {
  16.265 +        removePairImpl(pair, notifyIn);
  16.266 +    }
  16.267 +
  16.268 +    private <Transaction> void removePairImpl(Pair<?> pair, Executor notifyIn) {
  16.269 +        HashSet<R> toNotify = new HashSet<R>();
  16.270 +
  16.271 +        AbstractLookup.Storage<Transaction> t = enterStorage();
  16.272 +        Transaction transaction = null;
  16.273 +
  16.274 +        try {
  16.275 +            transaction = t.beginTransaction(-1);
  16.276 +            t.remove(pair, transaction);
  16.277 +            t.endTransaction(transaction, toNotify);
  16.278 +        } finally {
  16.279 +            exitStorage();
  16.280 +        }
  16.281 +
  16.282 +        notifyIn(notifyIn, toNotify);
  16.283 +    }
  16.284 +
  16.285 +    /** Changes all pairs in the lookup to new values.
  16.286 +     * @param collection the collection of (Pair) objects
  16.287 +     */
  16.288 +    protected final void setPairs(Collection<? extends Pair> collection) {
  16.289 +        setPairs(collection, null);
  16.290 +    }
  16.291 +
  16.292 +    /** Changes all pairs in the lookup to new values, notifies listeners
  16.293 +     * using provided executor.
  16.294 +     * 
  16.295 +     * @param collection the collection of (Pair) objects
  16.296 +     * @param notifyIn the executor that will handle the notification of events
  16.297 +     * @since 7.16
  16.298 +     */
  16.299 +    protected final void setPairs(Collection<? extends Pair> collection, Executor notifyIn) {
  16.300 +        HashSet<R> listeners = setPairsAndCollectListeners(collection);
  16.301 +        notifyIn(notifyIn, listeners);
  16.302 +    }
  16.303 +    
  16.304 +    private final void notifyIn(Executor notifyIn, final HashSet<R> listeners) {
  16.305 +        NotifyListeners notify = new NotifyListeners(listeners);
  16.306 +        if (notify.shallRun()) {
  16.307 +            if (notifyIn == null) {
  16.308 +                notify.run();
  16.309 +            } else {
  16.310 +                notifyIn.execute(notify);
  16.311 +            }
  16.312 +        }
  16.313 +    }
  16.314 +    
  16.315 +    /** Getter for set of pairs. Package private contract with MetaInfServicesLookup.
  16.316 +     * @return a LinkedHashSet that can be modified
  16.317 +     */
  16.318 +    final LinkedHashSet<Pair<?>> getPairsAsLHS() {
  16.319 +        AbstractLookup.Storage<?> t = enterStorage();
  16.320 +
  16.321 +        try {
  16.322 +            Enumeration<Pair<Object>> en = t.lookup(Object.class);
  16.323 +            TreeSet<Pair<?>> arr = new TreeSet<Pair<?>>(ALPairComparator.DEFAULT);
  16.324 +            while (en.hasMoreElements()) {
  16.325 +                Pair<Object> item = en.nextElement();
  16.326 +                arr.add(item);
  16.327 +            }
  16.328 +            return new LinkedHashSet<Pair<?>>(arr);
  16.329 +        } finally {
  16.330 +            exitStorage();
  16.331 +        }
  16.332 +    }
  16.333 +
  16.334 +    /** Collects listeners without notification. Needed in MetaInfServicesLookup
  16.335 +     * right now, but maybe will become an API later.
  16.336 +     */
  16.337 +    final <Transaction> HashSet<R> setPairsAndCollectListeners(Collection<? extends Pair> collection) {
  16.338 +        HashSet<R> toNotify = new HashSet<R>(27);
  16.339 +
  16.340 +        AbstractLookup.Storage<Transaction> t = enterStorage();
  16.341 +        Transaction transaction = null;
  16.342 +
  16.343 +        try {
  16.344 +            // map between the Items and their indexes (Integer)
  16.345 +            HashMap<Item<?>,Info> shouldBeThere = new HashMap<Item<?>,Info>(collection.size() * 2);
  16.346 +
  16.347 +            count = 0;
  16.348 +
  16.349 +            Iterator it = collection.iterator();
  16.350 +            transaction = t.beginTransaction(collection.size());
  16.351 +
  16.352 +            while (it.hasNext()) {
  16.353 +                Pair item = (Pair) it.next();
  16.354 +
  16.355 +                if (t.add(item, transaction)) {
  16.356 +                    // the item has not been there yet
  16.357 +                    //t.endTransaction(transaction, toNotify);
  16.358 +                }
  16.359 +
  16.360 +                // remeber the item, because it should not be removed
  16.361 +                shouldBeThere.put(item, new Info(count++, transaction));
  16.362 +
  16.363 +                //                    arr.clear ();
  16.364 +            }
  16.365 +
  16.366 +            //            Object transaction = t.beginTransaction ();
  16.367 +            // deletes all objects that should not be there and
  16.368 +            t.retainAll(shouldBeThere, transaction);
  16.369 +
  16.370 +            // collect listeners
  16.371 +            t.endTransaction(transaction, toNotify);
  16.372 +
  16.373 +            /*
  16.374 +            // check consistency
  16.375 +            Enumeration en = t.lookup (java.lang.Object.class);
  16.376 +            boolean[] max = new boolean[count];
  16.377 +            int mistake = -1;
  16.378 +            while (en.hasMoreElements ()) {
  16.379 +                Pair item = (Pair)en.nextElement ();
  16.380 +
  16.381 +                if (max[item.index]) {
  16.382 +                    mistake = item.index;
  16.383 +                }
  16.384 +                max[item.index] = true;
  16.385 +            }
  16.386 +
  16.387 +            if (mistake != -1) {
  16.388 +                System.err.println ("Mistake at: " + mistake);
  16.389 +                tree.print (System.err, true);
  16.390 +            }
  16.391 +            */
  16.392 +        } finally {
  16.393 +            exitStorage();
  16.394 +        }
  16.395 +
  16.396 +        return toNotify;
  16.397 +    }
  16.398 +
  16.399 +    private final void writeObject(ObjectOutputStream oos)
  16.400 +    throws IOException {
  16.401 +        AbstractLookup.Storage s = enterStorage();
  16.402 +
  16.403 +        try {
  16.404 +            // #36830: Serializing only InheritanceTree no ArrayStorage
  16.405 +            s.beginTransaction(Integer.MAX_VALUE);
  16.406 +
  16.407 +            // #32040: don't write half-made changes
  16.408 +            oos.defaultWriteObject();
  16.409 +        } finally {
  16.410 +            exitStorage();
  16.411 +        }
  16.412 +    }
  16.413 +
  16.414 +    public final <T> T lookup(Class<T> clazz) {
  16.415 +        Lookup.Item<T> item = lookupItem(new Lookup.Template<T>(clazz));
  16.416 +        return (item == null) ? null : item.getInstance();
  16.417 +    }
  16.418 +
  16.419 +    @Override
  16.420 +    public final <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
  16.421 +        AbstractLookup.this.beforeLookup(template);
  16.422 +
  16.423 +        ArrayList<Pair<T>> list = null;
  16.424 +        AbstractLookup.Storage<?> t = enterStorage();
  16.425 +
  16.426 +        try {
  16.427 +            Enumeration<Pair<T>> en;
  16.428 +
  16.429 +            try {
  16.430 +                en = t.lookup(template.getType());
  16.431 +
  16.432 +                return findSmallest(en, template, false);
  16.433 +            } catch (AbstractLookup.ISE ex) {
  16.434 +                // not possible to enumerate the exception, ok, copy it 
  16.435 +                // to create new
  16.436 +                list = new ArrayList<Pair<T>>();
  16.437 +                en = t.lookup(null); // this should get all the items without any checks
  16.438 +
  16.439 +                // the checks will be done out side of the storage
  16.440 +                while (en.hasMoreElements()) {
  16.441 +                    list.add(en.nextElement());
  16.442 +                }
  16.443 +            }
  16.444 +        } finally {
  16.445 +            exitStorage();
  16.446 +        }
  16.447 +
  16.448 +        return findSmallest(Collections.enumeration(list), template, true);
  16.449 +    }
  16.450 +
  16.451 +    private static <T> Pair<T> findSmallest(Enumeration<Pair<T>> en, Lookup.Template<T> template, boolean deepCheck) {
  16.452 +        int smallest = InheritanceTree.unsorted(en) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
  16.453 +        Pair<T> res = null;
  16.454 +
  16.455 +        while (en.hasMoreElements()) {
  16.456 +            Pair<T> item = en.nextElement();
  16.457 +
  16.458 +            if (matches(template, item, deepCheck)) {
  16.459 +                if (smallest == Integer.MIN_VALUE) {
  16.460 +                    // ok, sorted enumeration the first that matches is fine
  16.461 +                    return item;
  16.462 +                } else {
  16.463 +                    // check for the smallest item
  16.464 +                    if (smallest > item.getIndex()) {
  16.465 +                        smallest = item.getIndex();
  16.466 +                        res = item;
  16.467 +                    }
  16.468 +                }
  16.469 +            }
  16.470 +        }
  16.471 +
  16.472 +        return res;
  16.473 +    }
  16.474 +
  16.475 +    public final <T> Lookup.Result<T> lookup(Lookup.Template<T> template) {
  16.476 +        for (;;) {
  16.477 +            AbstractLookup.ISE toRun = null;
  16.478 +
  16.479 +            AbstractLookup.Storage<?> t = enterStorage();
  16.480 +
  16.481 +            try {
  16.482 +                R<T> r = new R<T>();
  16.483 +                ReferenceToResult<T> newRef = new ReferenceToResult<T>(r, this, template);
  16.484 +                newRef.next = t.registerReferenceToResult(newRef);
  16.485 +
  16.486 +                return r;
  16.487 +            } catch (AbstractLookup.ISE ex) {
  16.488 +                toRun = ex;
  16.489 +            } finally {
  16.490 +                exitStorage();
  16.491 +            }
  16.492 +
  16.493 +            toRun.recover(this);
  16.494 +
  16.495 +            // and try again
  16.496 +        }
  16.497 +    }
  16.498 +
  16.499 +    /** Notifies listeners.
  16.500 +     * @param allAffectedResults set of R
  16.501 +     */
  16.502 +    static final class NotifyListeners implements Runnable {
  16.503 +        private final ArrayList<Object> evAndListeners;
  16.504 +        
  16.505 +        public NotifyListeners(Set<R> allAffectedResults) {
  16.506 +            if (allAffectedResults.isEmpty()) {
  16.507 +                evAndListeners = null;
  16.508 +                return;
  16.509 +            }
  16.510 +
  16.511 +            evAndListeners = new ArrayList<Object>();
  16.512 +            {
  16.513 +                for (R<?> result : allAffectedResults) {
  16.514 +                    result.collectFires(evAndListeners);
  16.515 +                }
  16.516 +            }
  16.517 +        }
  16.518 +
  16.519 +        public boolean shallRun() {
  16.520 +            return evAndListeners != null && !evAndListeners.isEmpty();
  16.521 +        }
  16.522 +
  16.523 +        public void run() {
  16.524 +            Iterator it = evAndListeners.iterator();
  16.525 +            while (it.hasNext()) {
  16.526 +                LookupEvent ev = (LookupEvent)it.next();
  16.527 +                LookupListener l = (LookupListener)it.next();
  16.528 +                l.resultChanged(ev);
  16.529 +            }
  16.530 +        }
  16.531 +    }
  16.532 +
  16.533 +    /**
  16.534 +     * Call resultChanged on all listeners.
  16.535 +     * @param listeners array of listeners in the format used by
  16.536 +     *        javax.swing.EventListenerList. It means that there are Class
  16.537 +     *        objects on even positions and the listeners on odd positions
  16.538 +     * @param ev the event to fire
  16.539 +     */
  16.540 +    static void notifyListeners(Object[] listeners, LookupEvent ev, Collection<Object> evAndListeners) {
  16.541 +        for (int i = listeners.length - 1; i >= 0; i--) {
  16.542 +            if (! (listeners[i] instanceof LookupListener)) {
  16.543 +                continue;
  16.544 +            }
  16.545 +            LookupListener ll = (LookupListener)listeners[i];
  16.546 +
  16.547 +            try {
  16.548 +                if (evAndListeners != null) {
  16.549 +                    if (ll instanceof WaitableResult) {
  16.550 +                        WaitableResult<?> wr = (WaitableResult<?>)ll;
  16.551 +                        wr.collectFires(evAndListeners);
  16.552 +                    } else {
  16.553 +                        evAndListeners.add(ev);
  16.554 +                        evAndListeners.add(ll);
  16.555 +                    }
  16.556 +                } else {
  16.557 +                    ll.resultChanged(ev);
  16.558 +                }
  16.559 +            } catch (StackOverflowError err) {
  16.560 +                throw new CycleError(evAndListeners); // NOI18N
  16.561 +            } catch (RuntimeException e) {
  16.562 +                // Such as e.g. occurred in #32040. Do not halt other things.
  16.563 +                e.printStackTrace();
  16.564 +            }
  16.565 +        }
  16.566 +    }
  16.567 +
  16.568 +    private static class CycleError extends StackOverflowError {
  16.569 +        private final Collection<Object> print;
  16.570 +        public CycleError(Collection<Object> evAndListeners) {
  16.571 +            this.print = evAndListeners;
  16.572 +        }
  16.573 +
  16.574 +        @Override
  16.575 +        public String getMessage() {
  16.576 +            StringBuilder sb = new StringBuilder();
  16.577 +            sb.append("StackOverflowError, here are the listeners:\n"); // NOI18N
  16.578 +            for (Object o : print) {
  16.579 +                sb.append('\n').append(o);
  16.580 +                if (sb.length() > 10000) {
  16.581 +                    break;
  16.582 +                }
  16.583 +            }
  16.584 +            return sb.toString();
  16.585 +        }
  16.586 +    } // end of CycleError
  16.587 +
  16.588 +    /** A method that defines matching between Item and Template.
  16.589 +     * @param t template providing the criteria
  16.590 +     * @param item the item to match
  16.591 +     * @param deepCheck true if type of the pair should be tested, false if it is already has been tested
  16.592 +     * @return true if item matches the template requirements, false if not
  16.593 +     */
  16.594 +    static boolean matches(Template<?> t, Pair<?> item, boolean deepCheck) {
  16.595 +        String id = t.getId();
  16.596 +
  16.597 +        if (id != null && !id.equals(item.getId())) {
  16.598 +            return false;
  16.599 +        }
  16.600 +
  16.601 +        Object instance = t.getInstance();
  16.602 +
  16.603 +        if ((instance != null) && !item.creatorOf(instance)) {
  16.604 +            return false;
  16.605 +        }
  16.606 +
  16.607 +        if (deepCheck) {
  16.608 +            return item.instanceOf(t.getType());
  16.609 +        } else {
  16.610 +            return true;
  16.611 +        }
  16.612 +    }
  16.613 +
  16.614 +    /**
  16.615 +     * Compares the array elements for equality.
  16.616 +     * @return true if all elements in the arrays are equal
  16.617 +     *  (by calling equals(Object x) method)
  16.618 +     */
  16.619 +    private static boolean compareArrays(Object[] a, Object[] b) {
  16.620 +        // handle null values
  16.621 +        if (a == null) {
  16.622 +            return (b == null);
  16.623 +        } else {
  16.624 +            if (b == null) {
  16.625 +                return false;
  16.626 +            }
  16.627 +        }
  16.628 +
  16.629 +        if (a.length != b.length) {
  16.630 +            return false;
  16.631 +        }
  16.632 +
  16.633 +        for (int i = 0; i < a.length; i++) {
  16.634 +            // handle null values for individual elements
  16.635 +            if (a[i] == null) {
  16.636 +                if (b[i] != null) {
  16.637 +                    return false;
  16.638 +                }
  16.639 +
  16.640 +                // both are null --> ok, take next
  16.641 +                continue;
  16.642 +            } else {
  16.643 +                if (b[i] == null) {
  16.644 +                    return false;
  16.645 +                }
  16.646 +            }
  16.647 +
  16.648 +            // perform the comparison
  16.649 +            if (!a[i].equals(b[i])) {
  16.650 +                return false;
  16.651 +            }
  16.652 +        }
  16.653 +
  16.654 +        return true;
  16.655 +    }
  16.656 +
  16.657 +    /** Method to be called when a result is cleared to signal that the list
  16.658 +     * of all result should be checked for clearing.
  16.659 +     * @param template the template the result was for
  16.660 +     * @return true if the hash map with all items has been cleared
  16.661 +     */
  16.662 +    <T> boolean cleanUpResult(Lookup.Template<T> template) {
  16.663 +        AbstractLookup.Storage<?> t = enterStorage();
  16.664 +
  16.665 +        try {
  16.666 +            return t.cleanUpResult(template) == null;
  16.667 +        } finally {
  16.668 +            exitStorage();
  16.669 +        }
  16.670 +    }
  16.671 +
  16.672 +    /** Storage check for tests. */
  16.673 +    static boolean isSimple(AbstractLookup l) {
  16.674 +        return DelegatingStorage.isSimple((Storage)l.tree);
  16.675 +    }
  16.676 +
  16.677 +    /** Generic support for listeners, so it can be used in other results
  16.678 +     * as well.
  16.679 +     * @param add true to add it, false to modify
  16.680 +     * @param l listener to modify
  16.681 +     * @param ref the value of the reference to listener or listener list
  16.682 +     * @return new value to the reference to listener or list
  16.683 +     */
  16.684 +    @SuppressWarnings("unchecked")
  16.685 +    static Object modifyListenerList(boolean add, LookupListener l, Object ref) {
  16.686 +        if (add) {
  16.687 +            if (ref == null) {
  16.688 +                return l;
  16.689 +            }
  16.690 +
  16.691 +            if (ref instanceof LookupListener) {
  16.692 +                ArrayList arr = new ArrayList();
  16.693 +                arr.add(ref);
  16.694 +                ref = arr;
  16.695 +            }
  16.696 +
  16.697 +            ((ArrayList) ref).add(l);
  16.698 +
  16.699 +            return ref;
  16.700 +        } else {
  16.701 +            // remove
  16.702 +            if (ref == null) {
  16.703 +                return null;
  16.704 +            }
  16.705 +
  16.706 +            if (ref == l) {
  16.707 +                return null;
  16.708 +            }
  16.709 +
  16.710 +            ArrayList arr = (ArrayList) ref;
  16.711 +            arr.remove(l);
  16.712 +
  16.713 +            if (arr.size() == 1) {
  16.714 +                return arr.iterator().next();
  16.715 +            } else {
  16.716 +                return arr;
  16.717 +            }
  16.718 +        }
  16.719 +    }
  16.720 +
  16.721 +    private static ReferenceQueue<Object> activeQueue() {
  16.722 +        return ActiveQueue.queue();
  16.723 +    }
  16.724 +
  16.725 +    /** Storage to keep the internal structure of Pairs and to answer
  16.726 +     * different queries.
  16.727 +     */
  16.728 +    interface Storage<Transaction> {
  16.729 +        /** Initializes a modification operation by creating an object
  16.730 +         * that will be passsed to all add, remove, retainAll methods
  16.731 +         * and should collect enough information about the change to
  16.732 +         * notify listeners about the transaction later
  16.733 +         *
  16.734 +         * @param ensure the amount of items that will appear in the storage
  16.735 +         *   after the modifications (-1 == remove one, -2 == add one, >= 0
  16.736 +         *   the amount of objects at the end
  16.737 +         * @return a token to identify the transaction
  16.738 +         */
  16.739 +        public Transaction beginTransaction(int ensure);
  16.740 +
  16.741 +        /** Collects all affected results R that were modified in the
  16.742 +         * given transaction.
  16.743 +         *
  16.744 +         * @param modified place to add results R to
  16.745 +         * @param transaction the transaction indentification
  16.746 +         */
  16.747 +        public void endTransaction(Transaction transaction, Set<R> modifiedResults);
  16.748 +
  16.749 +        /** Adds an item into the storage.
  16.750 +        * @param item to add
  16.751 +        * @param transaction transaction token
  16.752 +        * @return true if the Item has been added for the first time or false if some other
  16.753 +        *    item equal to this one already existed in the lookup
  16.754 +        */
  16.755 +        public boolean add(AbstractLookup.Pair<?> item, Transaction transaction);
  16.756 +
  16.757 +        /** Removes an item.
  16.758 +        */
  16.759 +        public void remove(AbstractLookup.Pair item, Transaction transaction);
  16.760 +
  16.761 +        /** Removes all items that are not present in the provided collection.
  16.762 +        * @param retain collection of Pairs to keep them in
  16.763 +        * @param transaction the transaction context
  16.764 +        */
  16.765 +        public void retainAll(Map retain, Transaction transaction);
  16.766 +
  16.767 +        /** Queries for instances of given class.
  16.768 +        * @param clazz the class to check
  16.769 +        * @return enumeration of Item
  16.770 +        * @see #unsorted
  16.771 +        */
  16.772 +        public <T> Enumeration<Pair<T>> lookup(Class<T> clazz);
  16.773 +
  16.774 +        /** Registers another reference to a result with the storage. This method
  16.775 +         * has also a special meaning.
  16.776 +         *
  16.777 +         * @param newRef the new reference to remember
  16.778 +         * @return the previous reference that was kept (null if newRef is the first one)
  16.779 +         *    the applications is expected to link from newRef to this returned
  16.780 +         *    value to form a linked list
  16.781 +         */
  16.782 +        public ReferenceToResult<?> registerReferenceToResult(ReferenceToResult<?> newRef);
  16.783 +
  16.784 +        /** Given the provided template, Do cleanup the results.
  16.785 +         * @param templ template of a result(s) that should be checked
  16.786 +         * @return null if all references for this template were cleared or one of them
  16.787 +         */
  16.788 +        public ReferenceToResult<?> cleanUpResult(Lookup.Template<?> templ);
  16.789 +    }
  16.790 +
  16.791 +    /** Extension to the default lookup item that offers additional information
  16.792 +     * for the data structures use in AbstractLookup
  16.793 +     */
  16.794 +    public static abstract class Pair<T> extends Lookup.Item<T> implements Serializable {
  16.795 +        private static final long serialVersionUID = 1L;
  16.796 +
  16.797 +        /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */
  16.798 +        private int index = -1;
  16.799 +
  16.800 +        /** For use by subclasses. */
  16.801 +        protected Pair() {
  16.802 +        }
  16.803 +
  16.804 +        final int getIndex() {
  16.805 +            return index;
  16.806 +        }
  16.807 +
  16.808 +        final void setIndex(AbstractLookup.Storage<?> tree, int x) {
  16.809 +            if (tree == null) {
  16.810 +                this.index = x;
  16.811 +
  16.812 +                return;
  16.813 +            }
  16.814 +
  16.815 +            if (this.index == -1) {
  16.816 +                this.index = x;
  16.817 +            } else {
  16.818 +                throw new IllegalStateException("You cannot use " + this + " in more than one AbstractLookup. Prev: " + this.index + " new: " + x); // NOI18N
  16.819 +            }
  16.820 +        }
  16.821 +
  16.822 +        /** Tests whether this item can produce object
  16.823 +        * of class c.
  16.824 +        */
  16.825 +        protected abstract boolean instanceOf(Class<?> c);
  16.826 +
  16.827 +        /** Method that can test whether an instance of a class has been created
  16.828 +         * by this item.
  16.829 +         *
  16.830 +         * @param obj the instance
  16.831 +         * @return if the item has already create an instance and it is the same
  16.832 +         *   as obj.
  16.833 +         */
  16.834 +        protected abstract boolean creatorOf(Object obj);
  16.835 +    }
  16.836 +
  16.837 +    /** Result based on one instance returned.
  16.838 +     */
  16.839 +    static final class R<T> extends WaitableResult<T> {
  16.840 +        /** reference our result is attached to (do not modify) */
  16.841 +        public ReferenceToResult<T> reference;
  16.842 +
  16.843 +        /** listeners on the results or pointer to one listener */
  16.844 +        private Object listeners;
  16.845 +
  16.846 +        public R() {
  16.847 +        }
  16.848 +
  16.849 +        /** Checks whether we have simple behaviour of complex.
  16.850 +         */
  16.851 +        private boolean isSimple() {
  16.852 +            Storage s = (Storage) reference.lookup.tree;
  16.853 +
  16.854 +            return DelegatingStorage.isSimple(s);
  16.855 +        }
  16.856 +
  16.857 +        //
  16.858 +        // Handling cache management for both cases, no caches
  16.859 +        // for simple (but mark that we needed them, so refresh can
  16.860 +        // be done in cloneList) and complex when all 3 types
  16.861 +        // of result are cached
  16.862 +        //
  16.863 +        private Object getFromCache(int indx) {
  16.864 +            if (isSimple()) {
  16.865 +                return null;
  16.866 +            }
  16.867 +
  16.868 +            Object maybeArray = reference.caches;
  16.869 +
  16.870 +            if (maybeArray instanceof Object[]) {
  16.871 +                return ((Object[]) maybeArray)[indx];
  16.872 +            }
  16.873 +
  16.874 +            return null;
  16.875 +        }
  16.876 +
  16.877 +        @SuppressWarnings("unchecked")
  16.878 +        private Set<Class<? extends T>> getClassesCache() {
  16.879 +            return (Set<Class<? extends T>>) getFromCache(0);
  16.880 +        }
  16.881 +
  16.882 +        private void setClassesCache(Set s) {
  16.883 +            if (isSimple()) {
  16.884 +                // mark it as being used
  16.885 +                reference.caches = reference;
  16.886 +
  16.887 +                return;
  16.888 +            }
  16.889 +
  16.890 +            if (!(reference.caches instanceof Object[])) {
  16.891 +                reference.caches = new Object[3];
  16.892 +            }
  16.893 +
  16.894 +            ((Object[]) reference.caches)[0] = s;
  16.895 +        }
  16.896 +
  16.897 +        @SuppressWarnings("unchecked")
  16.898 +        private Collection<T> getInstancesCache() {
  16.899 +            return (Collection<T>) getFromCache(1);
  16.900 +        }
  16.901 +
  16.902 +        private void setInstancesCache(Collection c) {
  16.903 +            if (isSimple()) {
  16.904 +                // mark it as being used
  16.905 +                reference.caches = reference;
  16.906 +
  16.907 +                return;
  16.908 +            }
  16.909 +
  16.910 +            if (!(reference.caches instanceof Object[])) {
  16.911 +                reference.caches = new Object[3];
  16.912 +            }
  16.913 +
  16.914 +            ((Object[]) reference.caches)[1] = c;
  16.915 +        }
  16.916 +
  16.917 +        @SuppressWarnings("unchecked")
  16.918 +        private Pair<T>[] getItemsCache() {
  16.919 +            return (Pair<T>[]) getFromCache(2);
  16.920 +        }
  16.921 +
  16.922 +        private void setItemsCache(Collection<?> c) {
  16.923 +            if (isSimple()) {
  16.924 +                // mark it as being used
  16.925 +                reference.caches = reference;
  16.926 +
  16.927 +                return;
  16.928 +            }
  16.929 +
  16.930 +            if (!(reference.caches instanceof Object[])) {
  16.931 +                reference.caches = new Object[3];
  16.932 +            }
  16.933 +
  16.934 +            ((Object[]) reference.caches)[2] = c.toArray(new Pair[0]);
  16.935 +        }
  16.936 +
  16.937 +        private void clearCaches() {
  16.938 +            if (reference.caches instanceof Object[]) {
  16.939 +                reference.caches = new Object[3];
  16.940 +            }
  16.941 +        }
  16.942 +
  16.943 +        /** Ok, register listeners to all classes and super classes.
  16.944 +         */
  16.945 +        public synchronized void addLookupListener(LookupListener l) {
  16.946 +            listeners = modifyListenerList(true, l, listeners);
  16.947 +        }
  16.948 +
  16.949 +        /** Ok, register listeners to all classes and super classes.
  16.950 +         */
  16.951 +        public synchronized void removeLookupListener(LookupListener l) {
  16.952 +            listeners = modifyListenerList(false, l, listeners);
  16.953 +        }
  16.954 +
  16.955 +        /** Delete all cached values, the template changed.
  16.956 +         */
  16.957 +        protected  void collectFires(Collection<Object> evAndListeners) {
  16.958 +            Object[] previousItems = getItemsCache();
  16.959 +            clearCaches();
  16.960 +            
  16.961 +            if (previousItems != null) {
  16.962 +                Object[] newArray = allItemsWithoutBeforeLookup().toArray();
  16.963 +
  16.964 +                if (compareArrays(previousItems, newArray)) {
  16.965 +                    // do not fire any change if nothing has been changed
  16.966 +                    return;
  16.967 +                }
  16.968 +            }
  16.969 +
  16.970 +            LookupListener[] arr;
  16.971 +
  16.972 +            synchronized (this) {
  16.973 +                if (listeners == null) {
  16.974 +                    return;
  16.975 +                }
  16.976 +
  16.977 +                if (listeners instanceof LookupListener) {
  16.978 +                    arr = new LookupListener[] { (LookupListener) listeners };
  16.979 +                } else {
  16.980 +                    ArrayList<?> l = (ArrayList<?>) listeners;
  16.981 +                    arr = l.toArray(new LookupListener[l.size()]);
  16.982 +                }
  16.983 +            }
  16.984 +
  16.985 +            final LookupListener[] ll = arr;
  16.986 +            final LookupEvent ev = new LookupEvent(this);
  16.987 +            notifyListeners(ll, ev, evAndListeners);
  16.988 +        }
  16.989 +
  16.990 +        public Collection<T> allInstances() {
  16.991 +            reference.lookup.beforeLookup(reference.template);
  16.992 +
  16.993 +            Collection<T> s = getInstancesCache();
  16.994 +
  16.995 +            if (s != null) {
  16.996 +                return s;
  16.997 +            }
  16.998 +
  16.999 +            Collection<Pair<T>> items = allItemsWithoutBeforeLookup();
 16.1000 +            ArrayList<T> list = new ArrayList<T>(items.size());
 16.1001 +
 16.1002 +            Iterator<Pair<T>> it = items.iterator();
 16.1003 +
 16.1004 +            while (it.hasNext()) {
 16.1005 +                Pair<T> item = it.next();
 16.1006 +                T obj = item.getInstance();
 16.1007 +
 16.1008 +                if (reference.template.getType().isInstance(obj)) {
 16.1009 +                    list.add(obj);
 16.1010 +                }
 16.1011 +            }
 16.1012 +            
 16.1013 +            s = Collections.unmodifiableList(list);
 16.1014 +            setInstancesCache(s);
 16.1015 +
 16.1016 +            return s;
 16.1017 +        }
 16.1018 +
 16.1019 +        /** Set of all classes.
 16.1020 +         *
 16.1021 +         */
 16.1022 +        @Override
 16.1023 +        public Set<Class<? extends T>> allClasses() {
 16.1024 +            reference.lookup.beforeLookup(reference.template);
 16.1025 +
 16.1026 +            Set<Class<? extends T>> s = getClassesCache();
 16.1027 +
 16.1028 +            if (s != null) {
 16.1029 +                return s;
 16.1030 +            }
 16.1031 +
 16.1032 +            s = new HashSet<Class<? extends T>>();
 16.1033 +
 16.1034 +            for (Pair<T> item : allItemsWithoutBeforeLookup()) {
 16.1035 +                Class<? extends T> clazz = item.getType();
 16.1036 +
 16.1037 +                if (clazz != null) {
 16.1038 +                    s.add(clazz);
 16.1039 +                }
 16.1040 +            }
 16.1041 +
 16.1042 +            s = Collections.unmodifiableSet(s);
 16.1043 +            setClassesCache(s);
 16.1044 +
 16.1045 +            return s;
 16.1046 +        }
 16.1047 +
 16.1048 +        /** Items are stored directly in the allItems.
 16.1049 +         */
 16.1050 +        @Override
 16.1051 +        public Collection<? extends Item<T>> allItems() {
 16.1052 +            reference.lookup.beforeLookup(reference.template);
 16.1053 +
 16.1054 +            return allItemsWithoutBeforeLookup();
 16.1055 +        }
 16.1056 +
 16.1057 +        /** Implements the search for allItems, but without asking for before lookup */
 16.1058 +        private Collection<Pair<T>> allItemsWithoutBeforeLookup() {
 16.1059 +            Pair<T>[] c = getItemsCache();
 16.1060 +
 16.1061 +            if (c != null) {
 16.1062 +                return Collections.unmodifiableList(Arrays.asList(c));
 16.1063 +            }
 16.1064 +
 16.1065 +            ArrayList<Pair<Object>> saferCheck = null;
 16.1066 +            AbstractLookup.Storage<?> t = reference.lookup.enterStorage();
 16.1067 +
 16.1068 +            try {
 16.1069 +                try {
 16.1070 +                    return Collections.unmodifiableCollection(initItems(t));
 16.1071 +                } catch (AbstractLookup.ISE ex) {
 16.1072 +                    // do less effective evaluation of items outside of the 
 16.1073 +                    // locked storage
 16.1074 +                    saferCheck = new ArrayList<Pair<Object>>();
 16.1075 +
 16.1076 +                    Enumeration<Pair<Object>> en = t.lookup(null); // get all Pairs
 16.1077 +
 16.1078 +                    while (en.hasMoreElements()) {
 16.1079 +                        Pair<Object> i = en.nextElement();
 16.1080 +                        saferCheck.add(i);
 16.1081 +                    }
 16.1082 +                }
 16.1083 +            } finally {
 16.1084 +                reference.lookup.exitStorage();
 16.1085 +            }
 16.1086 +            return extractPairs(saferCheck);
 16.1087 +        }
 16.1088 +
 16.1089 +        @SuppressWarnings("unchecked")
 16.1090 +        private Collection<Pair<T>> extractPairs(final ArrayList<Pair<Object>> saferCheck) {
 16.1091 +            TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
 16.1092 +            for (Pair<Object> i : saferCheck) {
 16.1093 +                if (matches(reference.template, i, false)) {
 16.1094 +                    items.add((Pair<T>)i);
 16.1095 +                }
 16.1096 +            }
 16.1097 +            return Collections.unmodifiableCollection(items);
 16.1098 +        }
 16.1099 +
 16.1100 +        /** Initializes items.
 16.1101 +         */
 16.1102 +        private Collection<Pair<T>> initItems(Storage<?> t) {
 16.1103 +            // manipulation with the tree must be synchronized
 16.1104 +            Enumeration<Pair<T>> en = t.lookup(reference.template.getType());
 16.1105 +
 16.1106 +            // InheritanceTree is comparator for AbstractLookup.Pairs
 16.1107 +            TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
 16.1108 +
 16.1109 +            while (en.hasMoreElements()) {
 16.1110 +                Pair<T> i = en.nextElement();
 16.1111 +
 16.1112 +                if (matches(reference.template, i, false)) {
 16.1113 +                    items.add(i);
 16.1114 +                }
 16.1115 +            }
 16.1116 +
 16.1117 +            // create a correctly sorted copy using the tree as the comparator
 16.1118 +            setItemsCache(items);
 16.1119 +
 16.1120 +            return items;
 16.1121 +        }
 16.1122 +
 16.1123 +        /** Used by proxy results to synchronize before lookup.
 16.1124 +         */
 16.1125 +        protected void beforeLookup(Lookup.Template t) {
 16.1126 +            if (t.getType() == reference.template.getType()) {
 16.1127 +                reference.lookup.beforeLookup(t);
 16.1128 +            }
 16.1129 +        }
 16.1130 +
 16.1131 +        /* Do not need to implement it, the default way is ok.
 16.1132 +        public boolean equals(java.lang.Object obj) {
 16.1133 +            return obj == this;
 16.1134 +        }
 16.1135 +        */
 16.1136 +        @Override
 16.1137 +        public String toString() {
 16.1138 +            return super.toString() + " for " + reference.template;
 16.1139 +        }
 16.1140 +    }
 16.1141 +     // end of R
 16.1142 +
 16.1143 +    /** A class that can be used by the creator of the AbstractLookup to
 16.1144 +     * control its content. It can be passed to AbstractLookup constructor
 16.1145 +     * and used to add and remove pairs.
 16.1146 +     *
 16.1147 +     * @since 1.25
 16.1148 +     */
 16.1149 +    public static class Content extends Object implements Serializable {
 16.1150 +        private static final long serialVersionUID = 1L;
 16.1151 +
 16.1152 +        // one of them is always null (except attach stage)
 16.1153 +
 16.1154 +        /** abstract lookup we are connected to */
 16.1155 +        private AbstractLookup al;
 16.1156 +        private transient Object notifyIn;
 16.1157 +        
 16.1158 +        /** Default constructor.
 16.1159 +         */
 16.1160 +        public Content() {
 16.1161 +            this(null);
 16.1162 +        }
 16.1163 +        
 16.1164 +        /** Creates a content associated with an executor to handle dispatch
 16.1165 +         * of changes.
 16.1166 +         * @param notifyIn the executor to notify changes in
 16.1167 +         * @since  7.16
 16.1168 +         */
 16.1169 +        public Content(Executor notifyIn) {
 16.1170 +            this.notifyIn = notifyIn;
 16.1171 +        }
 16.1172 +        
 16.1173 +        /** for testing purposes */
 16.1174 +        final void attachExecutor(Executor notifyIn) {
 16.1175 +            this.notifyIn = notifyIn;
 16.1176 +        }
 16.1177 +
 16.1178 +        /** A lookup attaches to this object.
 16.1179 +         */
 16.1180 +        final synchronized void attach(AbstractLookup al) {
 16.1181 +            if (this.al == null) {
 16.1182 +                this.al = al;
 16.1183 +
 16.1184 +                ArrayList<Pair> ep = getEarlyPairs();
 16.1185 +                if (ep != null) {
 16.1186 +                    notifyIn = null;
 16.1187 +                    setPairs(ep);
 16.1188 +                }
 16.1189 +            } else {
 16.1190 +                throw new IllegalStateException(
 16.1191 +                    "Trying to use content for " + al + " but it is already used for " + this.al
 16.1192 +                ); // NOI18N
 16.1193 +            }
 16.1194 +        }
 16.1195 +
 16.1196 +        /** The method to add instance to the lookup with.
 16.1197 +         * @param pair class/instance pair
 16.1198 +         */
 16.1199 +        public final void addPair(Pair<?> pair) {
 16.1200 +            AbstractLookup a = al;
 16.1201 +            Executor e = getExecutor();
 16.1202 +
 16.1203 +            if (a != null || e != null) {
 16.1204 +                a.addPair(pair, e);
 16.1205 +            } else {
 16.1206 +                if (notifyIn == null) {
 16.1207 +                    notifyIn = new ArrayList<Pair>(3);
 16.1208 +                }
 16.1209 +
 16.1210 +                getEarlyPairs().add(pair);
 16.1211 +            }
 16.1212 +        }
 16.1213 +
 16.1214 +        /** Remove instance.
 16.1215 +         * @param pair class/instance pair
 16.1216 +         */
 16.1217 +        public final void removePair(Pair<?> pair) {
 16.1218 +            AbstractLookup a = al;
 16.1219 +            Executor e = getExecutor();
 16.1220 +
 16.1221 +            if (a != null || e != null) {
 16.1222 +                a.removePair(pair, e);
 16.1223 +            } else {
 16.1224 +                if (notifyIn == null) {
 16.1225 +                    notifyIn = new ArrayList<Pair>(3);
 16.1226 +                }
 16.1227 +
 16.1228 +                getEarlyPairs().remove(pair);
 16.1229 +            }
 16.1230 +        }
 16.1231 +
 16.1232 +        /** Changes all pairs in the lookup to new values.
 16.1233 +         * @param c the collection of (Pair) objects
 16.1234 +         */
 16.1235 +        public final void setPairs(Collection<? extends Pair> c) {
 16.1236 +            AbstractLookup a = al;
 16.1237 +            Executor e = getExecutor();
 16.1238 +            
 16.1239 +            if (a != null || e != null) {
 16.1240 +                a.setPairs(c, e);
 16.1241 +            } else {
 16.1242 +                notifyIn = new ArrayList<Pair>(c);
 16.1243 +            }
 16.1244 +        }
 16.1245 +
 16.1246 +        @SuppressWarnings("unchecked")
 16.1247 +        private ArrayList<Pair> getEarlyPairs() {
 16.1248 +            Object o = notifyIn;
 16.1249 +            return o instanceof ArrayList ? (ArrayList<Pair>)o : null;
 16.1250 +        }
 16.1251 +        
 16.1252 +        private Executor getExecutor() {
 16.1253 +            Object o = notifyIn;
 16.1254 +            return o instanceof Executor ? (Executor)o : null;
 16.1255 +        }
 16.1256 +    }
 16.1257 +     // end of Content
 16.1258 +
 16.1259 +    /** Just a holder for index & modified values.
 16.1260 +     */
 16.1261 +    final static class Info extends Object {
 16.1262 +        public int index;
 16.1263 +        public Object transaction;
 16.1264 +
 16.1265 +        public Info(int i, Object t) {
 16.1266 +            index = i;
 16.1267 +            transaction = t;
 16.1268 +        }
 16.1269 +    }
 16.1270 +
 16.1271 +    /** Reference to a result R
 16.1272 +     */
 16.1273 +    static final class ReferenceToResult<T> extends WeakReference<R<T>> implements Runnable {
 16.1274 +        /** next refernece in chain, modified only from AbstractLookup or this */
 16.1275 +        private ReferenceToResult<?> next;
 16.1276 +
 16.1277 +        /** the template for the result */
 16.1278 +        public final Template<T> template;
 16.1279 +
 16.1280 +        /** the lookup we are attached to */
 16.1281 +        public final AbstractLookup lookup;
 16.1282 +
 16.1283 +        /** caches for results */
 16.1284 +        public Object caches;
 16.1285 +
 16.1286 +        /** Creates a weak refernece to a new result R in context of lookup
 16.1287 +         * for given template
 16.1288 +         */
 16.1289 +        private ReferenceToResult(R<T> result, AbstractLookup lookup, Template<T> template) {
 16.1290 +            super(result, activeQueue());
 16.1291 +            this.template = template;
 16.1292 +            this.lookup = lookup;
 16.1293 +            getResult().reference = this;
 16.1294 +        }
 16.1295 +
 16.1296 +        /** Returns the result or null
 16.1297 +         */
 16.1298 +        R<T> getResult() {
 16.1299 +            return get();
 16.1300 +        }
 16.1301 +
 16.1302 +        /** Cleans the reference. Implements Runnable interface, do not call
 16.1303 +         * directly.
 16.1304 +         */
 16.1305 +        public void run() {
 16.1306 +            lookup.cleanUpResult(this.template);
 16.1307 +        }
 16.1308 +
 16.1309 +        /** Clones the reference list to given Storage.
 16.1310 +         * @param storage storage to clone to
 16.1311 +         */
 16.1312 +        public void cloneList(AbstractLookup.Storage<?> storage) {
 16.1313 +            ReferenceIterator it = new ReferenceIterator(this);
 16.1314 +
 16.1315 +            while (it.next()) {
 16.1316 +                ReferenceToResult<?> current = it.current();
 16.1317 +                ReferenceToResult<?> newRef = current.cloneRef();
 16.1318 +                newRef.next = storage.registerReferenceToResult(newRef);
 16.1319 +                newRef.caches = current.caches;
 16.1320 +
 16.1321 +                if (current.caches == current) {
 16.1322 +                    current.getResult().initItems(storage);
 16.1323 +                }
 16.1324 +            }
 16.1325 +        }
 16.1326 +
 16.1327 +        private ReferenceToResult<T> cloneRef() {
 16.1328 +            return new ReferenceToResult<T>(getResult(), lookup, template);
 16.1329 +        }
 16.1330 +    }
 16.1331 +     // end of ReferenceToResult
 16.1332 +
 16.1333 +    /** Supporting class to iterate over linked list of ReferenceToResult
 16.1334 +     * Use:
 16.1335 +     * <PRE>
 16.1336 +     *  ReferenceIterator it = new ReferenceIterator (this.ref);
 16.1337 +     *  while (it.next ()) {
 16.1338 +     *    it.current (): // do some work
 16.1339 +     *  }
 16.1340 +     *  this.ref = it.first (); // remember the first one
 16.1341 +     */
 16.1342 +    static final class ReferenceIterator extends Object {
 16.1343 +        private ReferenceToResult<?> first;
 16.1344 +        private ReferenceToResult<?> current;
 16.1345 +
 16.1346 +        /** hard reference to current result, so it is not GCed meanwhile */
 16.1347 +        private R<?> currentResult;
 16.1348 +
 16.1349 +        /** Initializes the iterator with first reference.
 16.1350 +         */
 16.1351 +        public ReferenceIterator(ReferenceToResult<?> first) {
 16.1352 +            this.first = first;
 16.1353 +        }
 16.1354 +
 16.1355 +        /** Moves the current to next possition */
 16.1356 +        public boolean next() {
 16.1357 +            ReferenceToResult<?> prev;
 16.1358 +            ReferenceToResult<?> ref;
 16.1359 +
 16.1360 +            if (current == null) {
 16.1361 +                ref = first;
 16.1362 +                prev = null;
 16.1363 +            } else {
 16.1364 +                prev = current;
 16.1365 +                ref = current.next;
 16.1366 +            }
 16.1367 +
 16.1368 +            while (ref != null) {
 16.1369 +                R<?> result = ref.get();
 16.1370 +
 16.1371 +                if (result == null) {
 16.1372 +                    if (prev == null) {
 16.1373 +                        // move the head
 16.1374 +                        first = ref.next;
 16.1375 +                    } else {
 16.1376 +                        // skip over this reference
 16.1377 +                        prev.next = ref.next;
 16.1378 +                    }
 16.1379 +
 16.1380 +                    prev = ref;
 16.1381 +                    ref = ref.next;
 16.1382 +                } else {
 16.1383 +                    // we have found next item
 16.1384 +                    currentResult = result;
 16.1385 +                    current = ref;
 16.1386 +
 16.1387 +                    return true;
 16.1388 +                }
 16.1389 +            }
 16.1390 +
 16.1391 +            currentResult = null;
 16.1392 +            current = null;
 16.1393 +
 16.1394 +            return false;
 16.1395 +        }
 16.1396 +
 16.1397 +        /** Access to current reference.
 16.1398 +         */
 16.1399 +        public ReferenceToResult<?> current() {
 16.1400 +            return current;
 16.1401 +        }
 16.1402 +
 16.1403 +        /** Access to reference that is supposed to be the first one.
 16.1404 +         */
 16.1405 +        public ReferenceToResult<?> first() {
 16.1406 +            return first;
 16.1407 +        }
 16.1408 +    }
 16.1409 +
 16.1410 +    /** Signals that a lookup is being modified from a lookup query.
 16.1411 +     *
 16.1412 +     * @author  Jaroslav Tulach
 16.1413 +     */
 16.1414 +    static final class ISE extends IllegalStateException {
 16.1415 +        static final long serialVersionUID = 100L;
 16.1416 +        
 16.1417 +        /** list of jobs to execute. */
 16.1418 +        private java.util.List<Job> jobs;
 16.1419 +
 16.1420 +        /** @param msg message
 16.1421 +         */
 16.1422 +        public ISE(String msg) {
 16.1423 +            super(msg);
 16.1424 +        }
 16.1425 +
 16.1426 +        /** Registers a job to be executed partially out and partially in
 16.1427 +         * the lock over storage.
 16.1428 +         */
 16.1429 +        public void registerJob(Job job) {
 16.1430 +            if (jobs == null) {
 16.1431 +                jobs = new java.util.ArrayList<Job>();
 16.1432 +            }
 16.1433 +
 16.1434 +            jobs.add(job);
 16.1435 +        }
 16.1436 +
 16.1437 +        /** Executes the jobs outside, and then inside a locked session.
 16.1438 +         */
 16.1439 +        public void recover(AbstractLookup lookup) {
 16.1440 +            if (jobs == null) {
 16.1441 +                // no recovery plan, throw itself
 16.1442 +                throw this;
 16.1443 +            }
 16.1444 +
 16.1445 +            for (Job j : jobs) {
 16.1446 +                j.before();
 16.1447 +            }
 16.1448 +
 16.1449 +            AbstractLookup.Storage s = lookup.enterStorage();
 16.1450 +
 16.1451 +            try {
 16.1452 +                for (Job j : jobs) {
 16.1453 +                    j.inside();
 16.1454 +                }
 16.1455 +            } finally {
 16.1456 +                lookup.exitStorage();
 16.1457 +            }
 16.1458 +        }
 16.1459 +
 16.1460 +        /** A job to be executed partially outside and partially inside
 16.1461 +         * the storage lock.
 16.1462 +         */
 16.1463 +        static interface Job {
 16.1464 +            public void before();
 16.1465 +
 16.1466 +            public void inside();
 16.1467 +        }
 16.1468 +    }
 16.1469 +     // end of ISE
 16.1470 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ArrayStorage.java	Mon Dec 14 20:58:39 2009 +0100
    17.3 @@ -0,0 +1,477 @@
    17.4 +/*
    17.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    17.6 + *
    17.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    17.8 + *
    17.9 + * The contents of this file are subject to the terms of either the GNU
   17.10 + * General Public License Version 2 only ("GPL") or the Common
   17.11 + * Development and Distribution License("CDDL") (collectively, the
   17.12 + * "License"). You may not use this file except in compliance with the
   17.13 + * License. You can obtain a copy of the License at
   17.14 + * http://www.netbeans.org/cddl-gplv2.html
   17.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   17.16 + * specific language governing permissions and limitations under the
   17.17 + * License.  When distributing the software, include this License Header
   17.18 + * Notice in each file and include the License file at
   17.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   17.20 + * particular file as subject to the "Classpath" exception as provided
   17.21 + * by Sun in the GPL Version 2 section of the License file that
   17.22 + * accompanied this code. If applicable, add the following below the
   17.23 + * License Header, with the fields enclosed by brackets [] replaced by
   17.24 + * your own identifying information:
   17.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   17.26 + *
   17.27 + * Contributor(s):
   17.28 + *
   17.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   17.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   17.31 + * Microsystems, Inc. All Rights Reserved.
   17.32 + *
   17.33 + * If you wish your version of this file to be governed by only the CDDL
   17.34 + * or only the GPL Version 2, indicate your decision by adding
   17.35 + * "[Contributor] elects to include this software in this distribution
   17.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   17.37 + * single choice of license, a recipient has the option to distribute
   17.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   17.39 + * to extend the choice of license to its licensees as provided above.
   17.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   17.41 + * Version 2 license, then the option applies only if the new code is
   17.42 + * made subject to such option by the copyright holder.
   17.43 + */
   17.44 +package org.openide.util.lookup;
   17.45 +
   17.46 +import org.openide.util.Lookup;
   17.47 +
   17.48 +
   17.49 +
   17.50 +import java.util.*;
   17.51 +import org.openide.util.lookup.AbstractLookup.Pair;
   17.52 +
   17.53 +
   17.54 +/** ArrayStorage of Pairs from AbstractLookup.
   17.55 + * @author  Jaroslav Tulach
   17.56 + */
   17.57 +final class ArrayStorage extends Object
   17.58 +implements AbstractLookup.Storage<ArrayStorage.Transaction> {
   17.59 +    /** default trashold */
   17.60 +    static final Integer DEFAULT_TRASH = new Integer(11);
   17.61 +
   17.62 +    /** list of items */
   17.63 +    private Object content;
   17.64 +
   17.65 +    /** linked list of refernces to results */
   17.66 +    private transient AbstractLookup.ReferenceToResult<?> results;
   17.67 +
   17.68 +    /** Constructor
   17.69 +     */
   17.70 +    public ArrayStorage() {
   17.71 +        this(DEFAULT_TRASH);
   17.72 +    }
   17.73 +
   17.74 +    /** Constructs new ArrayStorage */
   17.75 +    public ArrayStorage(Integer treshhold) {
   17.76 +        this.content = treshhold;
   17.77 +    }
   17.78 +
   17.79 +    /** Adds an item into the tree.
   17.80 +    * @param item to add
   17.81 +    * @return true if the Item has been added for the first time or false if some other
   17.82 +    *    item equal to this one already existed in the lookup
   17.83 +    */
   17.84 +    public boolean add(AbstractLookup.Pair<?> item, Transaction changed) {
   17.85 +        Object[] arr = changed.current;
   17.86 +
   17.87 +        if (changed.arr == null) {
   17.88 +            // just simple add of one item
   17.89 +            for (int i = 0; i < arr.length; i++) {
   17.90 +                if (arr[i] == null) {
   17.91 +                    arr[i] = item;
   17.92 +                    changed.add(item);
   17.93 +
   17.94 +                    return true;
   17.95 +                }
   17.96 +
   17.97 +                if (arr[i].equals(item)) {
   17.98 +                    // reassign the item number
   17.99 +                    item.setIndex(null, ((AbstractLookup.Pair) arr[i]).getIndex());
  17.100 +
  17.101 +                    // already there, but update it
  17.102 +                    arr[i] = item;
  17.103 +
  17.104 +                    return false;
  17.105 +                }
  17.106 +            }
  17.107 +
  17.108 +            // cannot happen as the beginTransaction ensured we can finish 
  17.109 +            // correctly
  17.110 +            throw new IllegalStateException();
  17.111 +        } else {
  17.112 +            // doing remainAll after that, let Transaction hold the new array
  17.113 +            int newIndex = changed.addPair(item);
  17.114 +
  17.115 +            for (int i = 0; i < arr.length; i++) {
  17.116 +                if (arr[i] == null) {
  17.117 +                    changed.add(item);
  17.118 +
  17.119 +                    return true;
  17.120 +                }
  17.121 +
  17.122 +                if (arr[i].equals(item)) {
  17.123 +                    // already there
  17.124 +                    if (i != newIndex) {
  17.125 +                        // change in index
  17.126 +                        changed.add(item);
  17.127 +
  17.128 +                        return false;
  17.129 +                    } else {
  17.130 +                        // no change
  17.131 +                        return false;
  17.132 +                    }
  17.133 +                }
  17.134 +            }
  17.135 +
  17.136 +            // if not found in the original array
  17.137 +            changed.add(item);
  17.138 +
  17.139 +            return true;
  17.140 +        }
  17.141 +    }
  17.142 +
  17.143 +    /** Removes an item.
  17.144 +    */
  17.145 +    public void remove(AbstractLookup.Pair item, Transaction changed) {
  17.146 +        Object[] arr = changed.current;
  17.147 +        if (arr == null) {
  17.148 +            return;
  17.149 +        }
  17.150 +
  17.151 +        int found = -1;
  17.152 +
  17.153 +        for (int i = 0; i < arr.length;) {
  17.154 +            if (arr[i] == null) {
  17.155 +                // end of task
  17.156 +                return;
  17.157 +            }
  17.158 +
  17.159 +            if ((found == -1) && arr[i].equals(item)) {
  17.160 +                // already there
  17.161 +                Pair<?> p = (Pair<?>)arr[i];
  17.162 +                p.setIndex(null, -1);
  17.163 +                changed.add(p);
  17.164 +                found = i;
  17.165 +            }
  17.166 +
  17.167 +            i++;
  17.168 +
  17.169 +            if (found != -1) {
  17.170 +                if (i < arr.length && !(arr[i] instanceof Integer)) {
  17.171 +                    // moving the array
  17.172 +                    arr[i - 1] = arr[i];
  17.173 +                } else {
  17.174 +                    arr[i - 1] = null;
  17.175 +                }
  17.176 +            }
  17.177 +        }
  17.178 +    }
  17.179 +
  17.180 +    /** Removes all items that are not present in the provided collection.
  17.181 +    * @param retain Pair -> AbstractLookup.Info map
  17.182 +    * @param notify set of Classes that has possibly changed
  17.183 +    */
  17.184 +    public void retainAll(Map retain, Transaction changed) {
  17.185 +        Object[] arr = changed.current;
  17.186 +
  17.187 +        for (int from = 0; from < arr.length; from++) {
  17.188 +            if (!(arr[from] instanceof AbstractLookup.Pair)) {
  17.189 +                // end of content
  17.190 +                break;
  17.191 +            }
  17.192 +
  17.193 +            AbstractLookup.Pair p = (AbstractLookup.Pair) arr[from];
  17.194 +
  17.195 +            AbstractLookup.Info info = (AbstractLookup.Info) retain.get(p);
  17.196 +
  17.197 +            if (info == null) {
  17.198 +                // was removed
  17.199 +
  17.200 +                /*
  17.201 +                if (info != null) {
  17.202 +                if (info.index < arr.length) {
  17.203 +                    newArr[info.index] = p;
  17.204 +                }
  17.205 +
  17.206 +                if (p.getIndex() != info.index) {
  17.207 +                    p.setIndex (null, info.index);
  17.208 +                    changed.add (p);
  17.209 +                }
  17.210 +                } else {
  17.211 +                // removed
  17.212 +                 */
  17.213 +                changed.add(p);
  17.214 +            }
  17.215 +        }
  17.216 +    }
  17.217 +
  17.218 +    /** Queries for instances of given class.
  17.219 +    * @param clazz the class to check
  17.220 +    * @return enumeration of Item
  17.221 +    * @see #unsorted
  17.222 +    */
  17.223 +    public <T> Enumeration<Pair<T>> lookup(final Class<T> clazz) {
  17.224 +        if (content instanceof Object[]) {
  17.225 +            final Enumeration<Object> all = InheritanceTree.arrayEn((Object[]) content);
  17.226 +            class JustPairs implements Enumeration<Pair<T>> {
  17.227 +                private Pair<T> next;
  17.228 +
  17.229 +                @SuppressWarnings("unchecked")
  17.230 +                private Pair<T> findNext() {
  17.231 +                    for (;;) {
  17.232 +                        if (next != null) {
  17.233 +                            return next;
  17.234 +                        }
  17.235 +                        if (!all.hasMoreElements()) {
  17.236 +                            return null;
  17.237 +                        }
  17.238 +                        Object o = all.nextElement();
  17.239 +                        boolean ok;
  17.240 +                        if (o instanceof AbstractLookup.Pair) {
  17.241 +                            ok = (clazz == null) || ((AbstractLookup.Pair<?>) o).instanceOf(clazz);
  17.242 +                        } else {
  17.243 +                            ok = false;
  17.244 +                        }
  17.245 +
  17.246 +                        next = ok ? (Pair<T>) o : null;
  17.247 +                    }
  17.248 +                }
  17.249 +                
  17.250 +                public boolean hasMoreElements() {
  17.251 +                    return findNext() != null;
  17.252 +                }
  17.253 +
  17.254 +                public Pair<T> nextElement() {
  17.255 +                    Pair<T> r = findNext();
  17.256 +                    if (r == null) {
  17.257 +                        throw new NoSuchElementException();
  17.258 +                    }
  17.259 +                    next = null;
  17.260 +                    return r;
  17.261 +                }
  17.262 +            } // end of JustPairs
  17.263 +            return new JustPairs();
  17.264 +        } else {
  17.265 +            return InheritanceTree.emptyEn();
  17.266 +        }
  17.267 +    }
  17.268 +
  17.269 +    /** Associates another result with this storage.
  17.270 +     */
  17.271 +    public AbstractLookup.ReferenceToResult registerReferenceToResult(AbstractLookup.ReferenceToResult<?> newRef) {
  17.272 +        AbstractLookup.ReferenceToResult prev = this.results;
  17.273 +        this.results = newRef;
  17.274 +
  17.275 +        return prev;
  17.276 +    }
  17.277 +
  17.278 +    /** Cleanup the references
  17.279 +     */
  17.280 +    public AbstractLookup.ReferenceToResult cleanUpResult(Lookup.Template<?> templ) {
  17.281 +        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
  17.282 +
  17.283 +        while (it.next()) {
  17.284 +            // empty
  17.285 +        }
  17.286 +
  17.287 +        return this.results = it.first();
  17.288 +    }
  17.289 +
  17.290 +    /** We use a hash set of all modified Pair to handle the transaction */
  17.291 +    public Transaction beginTransaction(int ensure) {
  17.292 +        return new Transaction(ensure, content);
  17.293 +    }
  17.294 +
  17.295 +    /** Extract all results.
  17.296 +     */
  17.297 +    public void endTransaction(Transaction changed, Set<AbstractLookup.R> modified) {
  17.298 +        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
  17.299 +
  17.300 +        if (changed.arr == null) {
  17.301 +            // either add or remove, only check the content of check HashSet
  17.302 +            while (it.next()) {
  17.303 +                AbstractLookup.ReferenceToResult ref = it.current();
  17.304 +                Iterator<Pair<?>> pairs = changed.iterator();
  17.305 +
  17.306 +                while (pairs.hasNext()) {
  17.307 +                    AbstractLookup.Pair p = (AbstractLookup.Pair) pairs.next();
  17.308 +
  17.309 +                    if (AbstractLookup.matches(ref.template, p, true)) {
  17.310 +                        modified.add(ref.getResult());
  17.311 +                    }
  17.312 +                }
  17.313 +            }
  17.314 +        } else {
  17.315 +            // do full check of changes
  17.316 +            while (it.next()) {
  17.317 +                AbstractLookup.ReferenceToResult ref = it.current();
  17.318 +
  17.319 +                int oldIndex = -1;
  17.320 +                int newIndex = -1;
  17.321 +
  17.322 +                for (;;) {
  17.323 +                    oldIndex = findMatching(ref.template, changed.current, oldIndex);
  17.324 +                    newIndex = findMatching(ref.template, changed.arr, newIndex);
  17.325 +
  17.326 +                    if ((oldIndex == -1) && (newIndex == -1)) {
  17.327 +                        break;
  17.328 +                    }
  17.329 +
  17.330 +                    if (
  17.331 +                        (oldIndex == -1) || (newIndex == -1) ||
  17.332 +                            !changed.current[oldIndex].equals(changed.arr[newIndex])
  17.333 +                    ) {
  17.334 +                        modified.add(ref.getResult());
  17.335 +
  17.336 +                        break;
  17.337 +                    }
  17.338 +                }
  17.339 +            }
  17.340 +        }
  17.341 +
  17.342 +        this.results = it.first();
  17.343 +        this.content = changed.newContent(this.content);
  17.344 +    }
  17.345 +
  17.346 +    private static int findMatching(Lookup.Template t, Object[] arr, int from) {
  17.347 +        while (++from < arr.length) {
  17.348 +            if (arr[from] instanceof AbstractLookup.Pair) {
  17.349 +                if (AbstractLookup.matches(t, (AbstractLookup.Pair) arr[from], true)) {
  17.350 +                    return from;
  17.351 +                }
  17.352 +            }
  17.353 +        }
  17.354 +
  17.355 +        return -1;
  17.356 +    }
  17.357 +
  17.358 +    /** HashSet with additional field for new array which is callocated
  17.359 +     * in case we are doing replace to hold all new items.
  17.360 +     */
  17.361 +    static final class Transaction extends HashSet<Pair<?>> {
  17.362 +        /** array with current objects */
  17.363 +        public final Object[] current;
  17.364 +
  17.365 +        /** array with new objects */
  17.366 +        public final Object[] arr;
  17.367 +
  17.368 +        /** number of objects in the array */
  17.369 +        private int cnt;
  17.370 +
  17.371 +        public Transaction(int ensure, Object currentContent) {
  17.372 +            Integer trashold;
  17.373 +            Object[] _arr;
  17.374 +
  17.375 +            if (currentContent instanceof Integer) {
  17.376 +                trashold = (Integer) currentContent;
  17.377 +                _arr = null;
  17.378 +            } else {
  17.379 +                _arr = (Object[]) currentContent;
  17.380 +
  17.381 +                if (_arr[_arr.length - 1] instanceof Integer) {
  17.382 +                    trashold = (Integer) _arr[_arr.length - 1];
  17.383 +                } else {
  17.384 +                    // nowhere to grow we have reached the limit
  17.385 +                    trashold = null;
  17.386 +                }
  17.387 +            }
  17.388 +
  17.389 +            int maxSize = (trashold == null) ? _arr.length : trashold.intValue();
  17.390 +
  17.391 +            if (ensure > maxSize) {
  17.392 +                throw new UnsupportedOperationException();
  17.393 +            }
  17.394 +
  17.395 +            if (ensure == -1) {
  17.396 +                // remove => it is ok
  17.397 +                this.current = currentContent instanceof Integer ? null : (Object[]) currentContent;
  17.398 +                this.arr = null;
  17.399 +
  17.400 +                return;
  17.401 +            }
  17.402 +
  17.403 +            if (ensure == -2) {
  17.404 +                // adding one
  17.405 +                if (_arr == null) {
  17.406 +                    // first time add, let's allocate the array
  17.407 +                    _arr = new Object[2];
  17.408 +                    _arr[1] = trashold;
  17.409 +                } else {
  17.410 +                    if (_arr[_arr.length - 1] instanceof AbstractLookup.Pair) {
  17.411 +                        // we are full
  17.412 +                        throw new UnsupportedOperationException();
  17.413 +                    } else {
  17.414 +                        // ensure we have allocated enough space
  17.415 +                        if (_arr.length < 2 || _arr[_arr.length - 2] != null) {
  17.416 +                            // double the array
  17.417 +                            int newSize = (_arr.length - 1) * 2;
  17.418 +                            
  17.419 +                            if (newSize <= 1) {
  17.420 +                                newSize = 2;
  17.421 +                            }
  17.422 +
  17.423 +                            if (newSize > maxSize) {
  17.424 +                                newSize = maxSize;
  17.425 +
  17.426 +                                if (newSize <= _arr.length) {
  17.427 +                                    // no space to get in
  17.428 +                                    throw new UnsupportedOperationException();
  17.429 +                                }
  17.430 +
  17.431 +                                _arr = new Object[newSize];
  17.432 +                            } else {
  17.433 +                                // still a lot of space
  17.434 +                                _arr = new Object[newSize + 1];
  17.435 +                                _arr[newSize] = trashold;
  17.436 +                            }
  17.437 +
  17.438 +                            // copy content of original array without the last Integer into 
  17.439 +                            // the new one
  17.440 +                            System.arraycopy(currentContent, 0, _arr, 0, ((Object[]) currentContent).length - 1);
  17.441 +                        }
  17.442 +                    }
  17.443 +                }
  17.444 +
  17.445 +                this.current = _arr;
  17.446 +                this.arr = null;
  17.447 +            } else {
  17.448 +                // allocate array for complete replacement
  17.449 +                if (ensure == maxSize) {
  17.450 +                    this.arr = new Object[ensure];
  17.451 +                } else {
  17.452 +                    this.arr = new Object[ensure + 1];
  17.453 +                    this.arr[ensure] = trashold;
  17.454 +                }
  17.455 +
  17.456 +                this.current = (currentContent instanceof Object[]) ? (Object[]) currentContent : new Object[0];
  17.457 +            }
  17.458 +        }
  17.459 +
  17.460 +        public int addPair(AbstractLookup.Pair<?> p) {
  17.461 +            p.setIndex(null, cnt);
  17.462 +            arr[cnt++] = p;
  17.463 +
  17.464 +            return p.getIndex();
  17.465 +        }
  17.466 +
  17.467 +        public Object newContent(Object prev) {
  17.468 +            if (arr == null) {
  17.469 +                if (current == null) {
  17.470 +                    return prev;
  17.471 +                } else {
  17.472 +                    return current;
  17.473 +                }
  17.474 +            } else {
  17.475 +                return arr;
  17.476 +            }
  17.477 +        }
  17.478 +    }
  17.479 +     // end of Transaction
  17.480 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/Bundle.properties	Mon Dec 14 20:58:39 2009 +0100
    18.3 @@ -0,0 +1,1 @@
    18.4 +OpenIDE-Module-Name=Lookup
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/DelegatingStorage.java	Mon Dec 14 20:58:39 2009 +0100
    19.3 @@ -0,0 +1,180 @@
    19.4 +/*
    19.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    19.6 + *
    19.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    19.8 + *
    19.9 + * The contents of this file are subject to the terms of either the GNU
   19.10 + * General Public License Version 2 only ("GPL") or the Common
   19.11 + * Development and Distribution License("CDDL") (collectively, the
   19.12 + * "License"). You may not use this file except in compliance with the
   19.13 + * License. You can obtain a copy of the License at
   19.14 + * http://www.netbeans.org/cddl-gplv2.html
   19.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   19.16 + * specific language governing permissions and limitations under the
   19.17 + * License.  When distributing the software, include this License Header
   19.18 + * Notice in each file and include the License file at
   19.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   19.20 + * particular file as subject to the "Classpath" exception as provided
   19.21 + * by Sun in the GPL Version 2 section of the License file that
   19.22 + * accompanied this code. If applicable, add the following below the
   19.23 + * License Header, with the fields enclosed by brackets [] replaced by
   19.24 + * your own identifying information:
   19.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   19.26 + *
   19.27 + * Contributor(s):
   19.28 + *
   19.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   19.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   19.31 + * Microsystems, Inc. All Rights Reserved.
   19.32 + *
   19.33 + * If you wish your version of this file to be governed by only the CDDL
   19.34 + * or only the GPL Version 2, indicate your decision by adding
   19.35 + * "[Contributor] elects to include this software in this distribution
   19.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   19.37 + * single choice of license, a recipient has the option to distribute
   19.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   19.39 + * to extend the choice of license to its licensees as provided above.
   19.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   19.41 + * Version 2 license, then the option applies only if the new code is
   19.42 + * made subject to such option by the copyright holder.
   19.43 + */
   19.44 +package org.openide.util.lookup;
   19.45 +
   19.46 +import org.openide.util.Lookup;
   19.47 +
   19.48 +import java.io.*;
   19.49 +
   19.50 +import java.lang.ref.WeakReference;
   19.51 +
   19.52 +import java.util.*;
   19.53 +import org.openide.util.lookup.AbstractLookup.Pair;
   19.54 +
   19.55 +
   19.56 +/** Storages that can switch between another storages.
   19.57 + * @author  Jaroslav Tulach
   19.58 + */
   19.59 +final class DelegatingStorage<Transaction> extends Object
   19.60 +implements Serializable, AbstractLookup.Storage<Transaction> {
   19.61 +    /** object to delegate to */
   19.62 +    private AbstractLookup.Storage<Transaction> delegate;
   19.63 +
   19.64 +    /** thread just accessing the storage */
   19.65 +    private Thread owner;
   19.66 +
   19.67 +    public DelegatingStorage(AbstractLookup.Storage<Transaction> d) {
   19.68 +        this.delegate = d;
   19.69 +        this.owner = Thread.currentThread();
   19.70 +    }
   19.71 +
   19.72 +    /** Never serialize yourself, always put there the delegate */
   19.73 +    public Object writeReplace() {
   19.74 +        return this.delegate;
   19.75 +    }
   19.76 +
   19.77 +    /** Method to check whether there is not multiple access from the same thread.
   19.78 +     */
   19.79 +    public void checkForTreeModification() {
   19.80 +        if (Thread.currentThread() == owner) {
   19.81 +            throw new AbstractLookup.ISE("You are trying to modify lookup from lookup query!"); // NOI18N
   19.82 +        }
   19.83 +    }
   19.84 +
   19.85 +    /** Checks whether we have simple behaviour or complex.
   19.86 +     */
   19.87 +    public static boolean isSimple(AbstractLookup.Storage s) {
   19.88 +        if (s instanceof DelegatingStorage) {
   19.89 +            return ((DelegatingStorage) s).delegate instanceof ArrayStorage;
   19.90 +        } else {
   19.91 +            return s instanceof ArrayStorage;
   19.92 +        }
   19.93 +    }
   19.94 +
   19.95 +    /** Exits from the owners ship of the storage.
   19.96 +     */
   19.97 +    public AbstractLookup.Storage<Transaction> exitDelegate() {
   19.98 +        if (Thread.currentThread() != owner) {
   19.99 +            throw new IllegalStateException("Onwer: " + owner + " caller: " + Thread.currentThread()); // NOI18N
  19.100 +        }
  19.101 +
  19.102 +        AbstractLookup.Storage<Transaction> d = delegate;
  19.103 +        delegate = null;
  19.104 +
  19.105 +        return d;
  19.106 +    }
  19.107 +
  19.108 +    public boolean add(AbstractLookup.Pair<?> item, Transaction transaction) {
  19.109 +        return delegate.add(item, transaction);
  19.110 +    }
  19.111 +
  19.112 +    public void remove(org.openide.util.lookup.AbstractLookup.Pair item, Transaction transaction) {
  19.113 +        delegate.remove(item, transaction);
  19.114 +    }
  19.115 +
  19.116 +    public void retainAll(Map retain, Transaction transaction) {
  19.117 +        delegate.retainAll(retain, transaction);
  19.118 +    }
  19.119 +
  19.120 +    /** A special method to change the backing storage.
  19.121 +     * In fact it is not much typesafe as it changes the
  19.122 +     * type of Transaction but we know that nobody is currently
  19.123 +     * holding a transaction object, so there cannot be inconsitencies.
  19.124 +     */
  19.125 +    @SuppressWarnings("unchecked")
  19.126 +    private void changeDelegate(InheritanceTree st) {
  19.127 +        delegate = (AbstractLookup.Storage<Transaction>)st;
  19.128 +    }
  19.129 +
  19.130 +    public Transaction beginTransaction(int ensure) {
  19.131 +        try {
  19.132 +            return delegate.beginTransaction(ensure);
  19.133 +        } catch (UnsupportedOperationException ex) {
  19.134 +            // let's convert to InheritanceTree
  19.135 +            ArrayStorage arr = (ArrayStorage) delegate;
  19.136 +            InheritanceTree inh = new InheritanceTree();
  19.137 +            changeDelegate(inh);
  19.138 +
  19.139 +            //
  19.140 +            // Copy content
  19.141 +            //
  19.142 +            Enumeration<Pair<Object>> en = arr.lookup(Object.class);
  19.143 +
  19.144 +            while (en.hasMoreElements()) {
  19.145 +                if (!inh.add(en.nextElement(), new ArrayList<Class>())) {
  19.146 +                    throw new IllegalStateException("All objects have to be accepted"); // NOI18N
  19.147 +                }
  19.148 +            }
  19.149 +
  19.150 +            //
  19.151 +            // Copy listeners
  19.152 +            //
  19.153 +            AbstractLookup.ReferenceToResult<?> ref = arr.cleanUpResult(null);
  19.154 +
  19.155 +            if (ref != null) {
  19.156 +                ref.cloneList(inh);
  19.157 +            }
  19.158 +
  19.159 +            // we have added the current content and now we can start transaction
  19.160 +            return delegate.beginTransaction(ensure);
  19.161 +        }
  19.162 +    }
  19.163 +
  19.164 +    public org.openide.util.lookup.AbstractLookup.ReferenceToResult cleanUpResult(
  19.165 +        org.openide.util.Lookup.Template templ
  19.166 +    ) {
  19.167 +        return delegate.cleanUpResult(templ);
  19.168 +    }
  19.169 +
  19.170 +    public void endTransaction(Transaction transaction, Set<AbstractLookup.R> modified) {
  19.171 +        delegate.endTransaction(transaction, modified);
  19.172 +    }
  19.173 +
  19.174 +    public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
  19.175 +        return delegate.lookup(clazz);
  19.176 +    }
  19.177 +
  19.178 +    public org.openide.util.lookup.AbstractLookup.ReferenceToResult registerReferenceToResult(
  19.179 +        org.openide.util.lookup.AbstractLookup.ReferenceToResult newRef
  19.180 +    ) {
  19.181 +        return delegate.registerReferenceToResult(newRef);
  19.182 +    }
  19.183 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ExcludingLookup.java	Mon Dec 14 20:58:39 2009 +0100
    20.3 @@ -0,0 +1,428 @@
    20.4 +/*
    20.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    20.6 + *
    20.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    20.8 + *
    20.9 + * The contents of this file are subject to the terms of either the GNU
   20.10 + * General Public License Version 2 only ("GPL") or the Common
   20.11 + * Development and Distribution License("CDDL") (collectively, the
   20.12 + * "License"). You may not use this file except in compliance with the
   20.13 + * License. You can obtain a copy of the License at
   20.14 + * http://www.netbeans.org/cddl-gplv2.html
   20.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   20.16 + * specific language governing permissions and limitations under the
   20.17 + * License.  When distributing the software, include this License Header
   20.18 + * Notice in each file and include the License file at
   20.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   20.20 + * particular file as subject to the "Classpath" exception as provided
   20.21 + * by Sun in the GPL Version 2 section of the License file that
   20.22 + * accompanied this code. If applicable, add the following below the
   20.23 + * License Header, with the fields enclosed by brackets [] replaced by
   20.24 + * your own identifying information:
   20.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   20.26 + *
   20.27 + * Contributor(s):
   20.28 + *
   20.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   20.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   20.31 + * Microsystems, Inc. All Rights Reserved.
   20.32 + *
   20.33 + * If you wish your version of this file to be governed by only the CDDL
   20.34 + * or only the GPL Version 2, indicate your decision by adding
   20.35 + * "[Contributor] elects to include this software in this distribution
   20.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   20.37 + * single choice of license, a recipient has the option to distribute
   20.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   20.39 + * to extend the choice of license to its licensees as provided above.
   20.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   20.41 + * Version 2 license, then the option applies only if the new code is
   20.42 + * made subject to such option by the copyright holder.
   20.43 + */
   20.44 +package org.openide.util.lookup;
   20.45 +
   20.46 +import java.lang.ref.Reference;
   20.47 +import java.lang.ref.WeakReference;
   20.48 +import org.openide.util.Lookup;
   20.49 +import org.openide.util.LookupListener;
   20.50 +
   20.51 +import java.util.*;
   20.52 +import org.openide.util.LookupEvent;
   20.53 +
   20.54 +
   20.55 +/** Allows exclusion of certain instances from lookup.
   20.56 + *
   20.57 + * @author Jaroslav Tulach
   20.58 + */
   20.59 +final class ExcludingLookup extends org.openide.util.Lookup {
   20.60 +    /** the other lookup that we delegate to */
   20.61 +    private Lookup delegate;
   20.62 +
   20.63 +    /** classes to exclude (Class[]) or just one class (Class) */
   20.64 +    private Object classes;
   20.65 +
   20.66 +    /**
   20.67 +     * Creates new Result object with supplied instances parameter.
   20.68 +     * @param instances to be used to return from the lookup
   20.69 +     */
   20.70 +    ExcludingLookup(Lookup delegate, Class[] classes) {
   20.71 +        this.delegate = delegate;
   20.72 +
   20.73 +        for (Class c : classes) {
   20.74 +            if (c == null) {
   20.75 +                throw new NullPointerException();
   20.76 +            }
   20.77 +        }
   20.78 +        if (classes.length == 1) {
   20.79 +            this.classes = classes[0];
   20.80 +        } else {
   20.81 +            this.classes = classes;
   20.82 +        }
   20.83 +    }
   20.84 +
   20.85 +    @Override
   20.86 +    public String toString() {
   20.87 +        return "ExcludingLookup: " + delegate + " excludes: " + Arrays.asList(classes()); // NOI18N
   20.88 +    }
   20.89 +
   20.90 +    public <T> Result<T> lookup(Template<T> template) {
   20.91 +        if (template == null) {
   20.92 +            throw new NullPointerException();
   20.93 +        }
   20.94 +
   20.95 +        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
   20.96 +            // empty result
   20.97 +            return Lookup.EMPTY.lookup(template);
   20.98 +        }
   20.99 +
  20.100 +        return new R<T>(template.getType(), delegate.lookup(template));
  20.101 +    }
  20.102 +
  20.103 +    public <T> T lookup(Class<T> clazz) {
  20.104 +        if (areSubclassesOfThisClassAlwaysExcluded(clazz)) {
  20.105 +            return null;
  20.106 +        }
  20.107 +
  20.108 +        T res = delegate.lookup(clazz);
  20.109 +
  20.110 +        if (isObjectAccessible(clazz, res, 0)) {
  20.111 +            return res;
  20.112 +        } else {
  20.113 +            return null;
  20.114 +        }
  20.115 +    }
  20.116 +
  20.117 +    @Override
  20.118 +    public <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
  20.119 +        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
  20.120 +            return null;
  20.121 +        }
  20.122 +
  20.123 +        Lookup.Item<T> retValue = delegate.lookupItem(template);
  20.124 +
  20.125 +        if (isObjectAccessible(template.getType(), retValue, 2)) {
  20.126 +            return retValue;
  20.127 +        } else {
  20.128 +            return null;
  20.129 +        }
  20.130 +    }
  20.131 +
  20.132 +    /** @return true if the instance of class c shall never be returned from this lookup
  20.133 +     */
  20.134 +    private boolean areSubclassesOfThisClassAlwaysExcluded(Class<?> c) {
  20.135 +        Class<?>[] arr = classes();
  20.136 +
  20.137 +        for (int i = 0; i < arr.length; i++) {
  20.138 +            if (arr[i].isAssignableFrom(c)) {
  20.139 +                return true;
  20.140 +            }
  20.141 +        }
  20.142 +
  20.143 +        return false;
  20.144 +    }
  20.145 +
  20.146 +    /** Returns the array of classes this lookup filters.
  20.147 +     */
  20.148 +    final Class<?>[] classes() {
  20.149 +        if (classes instanceof Class[]) {
  20.150 +            return (Class[]) classes;
  20.151 +        } else {
  20.152 +            return new Class[] { (Class) classes };
  20.153 +        }
  20.154 +    }
  20.155 +
  20.156 +    /** Does a check whether two classes are accessible (in the super/sub class)
  20.157 +     * releation ship without walking thru any of the classes mentioned in the
  20.158 +     * barrier.
  20.159 +     */
  20.160 +    private static boolean isAccessible(Class<?>[] barriers, Class<?> from, Class<?> to) {
  20.161 +        if ((to == null) || !from.isAssignableFrom(to)) {
  20.162 +            // no way to reach each other by walking up
  20.163 +            return false;
  20.164 +        }
  20.165 +
  20.166 +        for (int i = 0; i < barriers.length; i++) {
  20.167 +            if (to == barriers[i]) {
  20.168 +                return false;
  20.169 +            }
  20.170 +        }
  20.171 +
  20.172 +        if (from == to) {
  20.173 +            return true;
  20.174 +        }
  20.175 +
  20.176 +        //
  20.177 +        // depth first search
  20.178 +        //
  20.179 +        if (isAccessible(barriers, from, to.getSuperclass())) {
  20.180 +            return true;
  20.181 +        }
  20.182 +
  20.183 +        Class[] interfaces = to.getInterfaces();
  20.184 +
  20.185 +        for (int i = 0; i < interfaces.length; i++) {
  20.186 +            if (isAccessible(barriers, from, interfaces[i])) {
  20.187 +                return true;
  20.188 +            }
  20.189 +        }
  20.190 +
  20.191 +        return false;
  20.192 +    }
  20.193 +
  20.194 +    /** based on type decides whether the class accepts or not anObject
  20.195 +     * @param from the base type of the query
  20.196 +     * @param to depending on value of type either Object, Class or Item
  20.197 +     * @param type 0,1,2 for Object, Class or Item
  20.198 +     * @return true if we can access the to from from by walking around the bariers
  20.199 +     */
  20.200 +    private final boolean isObjectAccessible(Class from, Object to, int type) {
  20.201 +        if (to == null) {
  20.202 +            return false;
  20.203 +        }
  20.204 +
  20.205 +        return isObjectAccessible(classes(), from, to, type);
  20.206 +    }
  20.207 +
  20.208 +    /** based on type decides whether the class accepts or not anObject
  20.209 +     * @param barriers classes to avoid when testing reachability
  20.210 +     * @param from the base type of the query
  20.211 +     * @param to depending on value of type either Object, Class or Item
  20.212 +     * @param type 0,1,2 for Object, Class or Item
  20.213 +     * @return true if we can access the to from from by walking around the bariers
  20.214 +     */
  20.215 +    static final boolean isObjectAccessible(Class[] barriers, Class from, Object to, int type) {
  20.216 +        if (to == null) {
  20.217 +            return false;
  20.218 +        }
  20.219 +
  20.220 +        switch (type) {
  20.221 +        case 0:
  20.222 +            return isAccessible(barriers, from, to.getClass());
  20.223 +
  20.224 +        case 1:
  20.225 +            return isAccessible(barriers, from, (Class) to);
  20.226 +
  20.227 +        case 2: {
  20.228 +            Item item = (Item) to;
  20.229 +
  20.230 +            return isAccessible(barriers, from, item.getType());
  20.231 +        }
  20.232 +
  20.233 +        default:
  20.234 +            throw new IllegalStateException("Type: " + type);
  20.235 +        }
  20.236 +    }
  20.237 +
  20.238 +    /** Filters collection accroding to set of given filters.
  20.239 +     */
  20.240 +    final <E, T extends Collection<E>> T filter(
  20.241 +        Class<?>[] arr, Class<?> from, T c, int type, T prototype
  20.242 +    ) {
  20.243 +        T ret = null;
  20.244 +
  20.245 +
  20.246 +// optimistic strategy expecting we will not need to filter
  20.247 +TWICE: 
  20.248 +        for (;;) {
  20.249 +            Iterator<E> it = c.iterator();
  20.250 +BIG: 
  20.251 +            while (it.hasNext()) {
  20.252 +                E res = it.next();
  20.253 +
  20.254 +                if (!isObjectAccessible(arr, from, res, type)) {
  20.255 +                    if (ret == null) {
  20.256 +                        // we need to restart the scanning again 
  20.257 +                        // as there is an active filter
  20.258 +                        ret = prototype;
  20.259 +                        continue TWICE;
  20.260 +                    }
  20.261 +
  20.262 +                    continue BIG;
  20.263 +                }
  20.264 +
  20.265 +                if (ret != null) {
  20.266 +                    // if we are running the second round from TWICE
  20.267 +                    ret.add(res);
  20.268 +                }
  20.269 +            }
  20.270 +
  20.271 +            // ok, processed
  20.272 +            break TWICE;
  20.273 +        }
  20.274 +
  20.275 +        return (ret != null) ? ret : c;
  20.276 +    }
  20.277 +
  20.278 +    /** Delegating result that filters unwanted items and instances.
  20.279 +     */
  20.280 +    private final class R<T> extends WaitableResult<T> implements LookupListener {
  20.281 +        private Result<T> result;
  20.282 +        private WeakResult<T> weak;
  20.283 +        private Object listeners;
  20.284 +        private Class<?> from;
  20.285 +
  20.286 +        R(Class<?> from, Result<T> delegate) {
  20.287 +            this.from = from;
  20.288 +            this.result = delegate;
  20.289 +            this.weak = new WeakResult<T>(this, delegate);
  20.290 +        }
  20.291 +
  20.292 +        protected void beforeLookup(Template t) {
  20.293 +            if (result instanceof WaitableResult) {
  20.294 +                ((WaitableResult) result).beforeLookup(t);
  20.295 +            }
  20.296 +        }
  20.297 +
  20.298 +        public void addLookupListener(LookupListener l) {
  20.299 +            boolean add;
  20.300 +
  20.301 +            synchronized (this) {
  20.302 +                listeners = AbstractLookup.modifyListenerList(true, l, listeners);
  20.303 +                add = listeners != null;
  20.304 +            }
  20.305 +
  20.306 +            if (add) {
  20.307 +                result.addLookupListener(weak);
  20.308 +            }
  20.309 +        }
  20.310 +
  20.311 +        public void removeLookupListener(LookupListener l) {
  20.312 +            boolean remove;
  20.313 +
  20.314 +            synchronized (this) {
  20.315 +                listeners = AbstractLookup.modifyListenerList(false, l, listeners);
  20.316 +                remove = listeners == null;
  20.317 +            }
  20.318 +
  20.319 +            if (remove) {
  20.320 +                result.removeLookupListener(weak);
  20.321 +            }
  20.322 +        }
  20.323 +
  20.324 +        public Collection<? extends T> allInstances() {
  20.325 +            return openCol(result.allInstances(), 0);
  20.326 +        }
  20.327 +
  20.328 +        private <S> Collection<S> openCol(Collection<S> c, int type) {
  20.329 +            return filter(classes(), from, c, type, new ArrayList<S>(c.size()));
  20.330 +        }
  20.331 +
  20.332 +        @Override
  20.333 +        public Set<Class<? extends T>> allClasses() {
  20.334 +            return filter(classes(), from, result.allClasses(), 1, new HashSet<Class<? extends T>>());
  20.335 +        }
  20.336 +
  20.337 +        @Override
  20.338 +        public Collection<? extends Item<T>> allItems() {
  20.339 +            return openCol(result.allItems(), 2);
  20.340 +        }
  20.341 +
  20.342 +        public void resultChanged(org.openide.util.LookupEvent ev) {
  20.343 +            if (ev.getSource() == result) {
  20.344 +                collectFires(null);
  20.345 +            }
  20.346 +        }
  20.347 +
  20.348 +        protected void collectFires(Collection<Object> evAndListeners) {
  20.349 +            LookupListener[] arr;
  20.350 +
  20.351 +            synchronized (this) {
  20.352 +                if (listeners == null) {
  20.353 +                    return;
  20.354 +                }
  20.355 +
  20.356 +                if (listeners instanceof LookupListener) {
  20.357 +                    arr = new LookupListener[] { (LookupListener) listeners };
  20.358 +                } else {
  20.359 +                    ArrayList<?> l = (ArrayList<?>) listeners;
  20.360 +                    arr = l.toArray(new LookupListener[l.size()]);
  20.361 +                }
  20.362 +            }
  20.363 +
  20.364 +            final LookupListener[] ll = arr;
  20.365 +            final org.openide.util.LookupEvent newev = new org.openide.util.LookupEvent(this);
  20.366 +            AbstractLookup.notifyListeners(ll, newev, evAndListeners);
  20.367 +        }
  20.368 +    } // end of R
  20.369 +    
  20.370 +    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
  20.371 +        private Lookup.Result source;
  20.372 +        private Reference<R<T>> result;
  20.373 +        
  20.374 +        public WeakResult(R<T> r, Lookup.Result<T> s) {
  20.375 +            this.result = new WeakReference<R<T>>(r);
  20.376 +            this.source = s;
  20.377 +        }
  20.378 +        
  20.379 +        protected void beforeLookup(Lookup.Template t) {
  20.380 +            R r = (R)result.get();
  20.381 +            if (r != null) {
  20.382 +                r.beforeLookup(t);
  20.383 +            } else {
  20.384 +                source.removeLookupListener(this);
  20.385 +            }
  20.386 +        }
  20.387 +
  20.388 +        protected void collectFires(Collection<Object> evAndListeners) {
  20.389 +            R<T> r = result.get();
  20.390 +            if (r != null) {
  20.391 +                r.collectFires(evAndListeners);
  20.392 +            } else {
  20.393 +                source.removeLookupListener(this);
  20.394 +            }
  20.395 +        }
  20.396 +
  20.397 +        public void addLookupListener(LookupListener l) {
  20.398 +            assert false;
  20.399 +        }
  20.400 +
  20.401 +        public void removeLookupListener(LookupListener l) {
  20.402 +            assert false;
  20.403 +        }
  20.404 +
  20.405 +        public Collection<T> allInstances() {
  20.406 +            assert false;
  20.407 +            return null;
  20.408 +        }
  20.409 +
  20.410 +        public void resultChanged(LookupEvent ev) {
  20.411 +            R r = (R)result.get();
  20.412 +            if (r != null) {
  20.413 +                r.resultChanged(ev);
  20.414 +            } else {
  20.415 +                source.removeLookupListener(this);
  20.416 +            }
  20.417 +        }
  20.418 +
  20.419 +        @Override
  20.420 +        public Collection<? extends Item<T>> allItems() {
  20.421 +            assert false;
  20.422 +            return null;
  20.423 +        }
  20.424 +
  20.425 +        @Override
  20.426 +        public Set<Class<? extends T>> allClasses() {
  20.427 +            assert false;
  20.428 +            return null;
  20.429 +        }
  20.430 +    } // end of WeakResult
  20.431 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/InheritanceTree.java	Mon Dec 14 20:58:39 2009 +0100
    21.3 @@ -0,0 +1,1276 @@
    21.4 +/*
    21.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    21.6 + *
    21.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    21.8 + *
    21.9 + * The contents of this file are subject to the terms of either the GNU
   21.10 + * General Public License Version 2 only ("GPL") or the Common
   21.11 + * Development and Distribution License("CDDL") (collectively, the
   21.12 + * "License"). You may not use this file except in compliance with the
   21.13 + * License. You can obtain a copy of the License at
   21.14 + * http://www.netbeans.org/cddl-gplv2.html
   21.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   21.16 + * specific language governing permissions and limitations under the
   21.17 + * License.  When distributing the software, include this License Header
   21.18 + * Notice in each file and include the License file at
   21.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   21.20 + * particular file as subject to the "Classpath" exception as provided
   21.21 + * by Sun in the GPL Version 2 section of the License file that
   21.22 + * accompanied this code. If applicable, add the following below the
   21.23 + * License Header, with the fields enclosed by brackets [] replaced by
   21.24 + * your own identifying information:
   21.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   21.26 + *
   21.27 + * Contributor(s):
   21.28 + *
   21.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   21.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   21.31 + * Microsystems, Inc. All Rights Reserved.
   21.32 + *
   21.33 + * If you wish your version of this file to be governed by only the CDDL
   21.34 + * or only the GPL Version 2, indicate your decision by adding
   21.35 + * "[Contributor] elects to include this software in this distribution
   21.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   21.37 + * single choice of license, a recipient has the option to distribute
   21.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   21.39 + * to extend the choice of license to its licensees as provided above.
   21.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   21.41 + * Version 2 license, then the option applies only if the new code is
   21.42 + * made subject to such option by the copyright holder.
   21.43 + */
   21.44 +package org.openide.util.lookup;
   21.45 +
   21.46 +import org.openide.util.Lookup;
   21.47 +import org.openide.util.lookup.AbstractLookup.Pair;
   21.48 +import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
   21.49 +import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
   21.50 +
   21.51 +import java.io.*;
   21.52 +
   21.53 +import java.lang.ref.WeakReference;
   21.54 +
   21.55 +import java.util.*;
   21.56 +
   21.57 +
   21.58 +/** A tree to represent classes with inheritance. Description of the
   21.59 + * data structure by Petr Nejedly:
   21.60 + * <P>
   21.61 + * So pretend I'm Lookup implementation. I've got a bunch of Items (e.g.
   21.62 + * setPairs() method),
   21.63 + * didn't do anything on them yet (no startup penalty) so I know nothing
   21.64 + * about them.
   21.65 + * Then I'll be asked for all instances implementing given interface or a
   21.66 + * class. I surely need
   21.67 + * to check all the Items now, as I don't know anything abou them. I surely
   21.68 + * don't want to call
   21.69 + * Item.getClass() as it will dismiss the whole effort. So all I have is
   21.70 + * Item.instanceOf()
   21.71 + * and I'll call it on every Item. I'll cache results, so the next time
   21.72 + * you'll ask me for
   21.73 + * the same interface/class, I'll answer immediatelly. But what if you ask
   21.74 + * me for another
   21.75 + * interface/class? I'll have to scan all Items for it again, unless I can
   21.76 + * be sure some
   21.77 + * of them can't implement it. The only source of this knowledge are the
   21.78 + * previous questions
   21.79 + * and my rulings on them. Here the algorithm have to be split into two
   21.80 + * paths. If you
   21.81 + * previously asked me for interfaces only, I'll have no hint for
   21.82 + * subsequent queries,
   21.83 + * but if you asked me for a class in history, and then for another class
   21.84 + * and these classes
   21.85 + * are not in inheritance relation (I can check hierarchy of lookup
   21.86 + * arguments, because
   21.87 + * they are already resolved/loaded) I can tell that those returned in
   21.88 + * previous query can't
   21.89 + * implement the newly asked class (they are in different hierarchy branch)
   21.90 + * and I need to
   21.91 + * ask less Items.
   21.92 + * <P>
   21.93 + * So if we use mostly classes for asking for services (and it is a trend
   21.94 + * to use
   21.95 + * abstract classes for this purpose in IDE anyway), this could be usable.
   21.96 + * <P>
   21.97 + * The data structure for separating the Items based on previous queries is
   21.98 + * simple
   21.99 + * tree, with every node tagged with one class. The tree's root is,
  21.100 + * naturally,
  21.101 + * java.lang.Object, is marked invited and initially contains all the
  21.102 + * Items.
  21.103 + * For every class query, the missing part of class hierarchy tree is
  21.104 + * created,
  21.105 + * the node of the class looked up is marked as invited and all Items from
  21.106 + * nearest
  21.107 + * invited parent (sperclass) are dragged to this node. The result are then
  21.108 + * all
  21.109 + * Items from this node and all the nodes deeper in hierarchy. Because it
  21.110 + * may
  21.111 + * be too complicated to walk through the children nodes, the results could
  21.112 + * be
  21.113 + * cached in the map.
  21.114 + * For interface lookup, there is a little hint in reality (interfaces
  21.115 + * and superinterfaces), but it would be harder to exploit it, so we could
  21.116 + * fall-back
  21.117 + * to walking through all the Items and cache results.
  21.118 + *
  21.119 + *
  21.120 + * @author  Jaroslav Tulach
  21.121 + */
  21.122 +final class InheritanceTree extends Object
  21.123 +implements Serializable, AbstractLookup.Storage<ArrayList<Class>> {
  21.124 +    private static final long serialVersionUID = 1L;
  21.125 +
  21.126 +    /** the root item (represents Object) */
  21.127 +    private transient Node object;
  21.128 +
  21.129 +    /** Map of queried interfaces.
  21.130 +     * <p>Type: <code>Map&lt;Class, (Collection&lt;AbstractLookup.Pair&gt; | AbstractLookup.Pair)&gt;</code>
  21.131 +     */
  21.132 +    private transient Map<Class,Object> interfaces;
  21.133 +
  21.134 +    /** Map (Class, ReferenceToResult) of all listeners that are waiting in
  21.135 +     * changes in class Class
  21.136 +     */
  21.137 +    private transient Map<Class,ReferenceToResult> reg;
  21.138 +
  21.139 +    /** Constructor
  21.140 +     */
  21.141 +    public InheritanceTree() {
  21.142 +        object = new Node(java.lang.Object.class);
  21.143 +    }
  21.144 +
  21.145 +    private void writeObject(ObjectOutputStream oos) throws IOException {
  21.146 +        oos.writeObject(object);
  21.147 +
  21.148 +        if (interfaces != null) {
  21.149 +            Iterator it = interfaces.entrySet().iterator();
  21.150 +
  21.151 +            while (it.hasNext()) {
  21.152 +                Map.Entry e = (Map.Entry) it.next();
  21.153 +                Class c = (Class) e.getKey();
  21.154 +                oos.writeObject(c.getName());
  21.155 +
  21.156 +                Object o = e.getValue();
  21.157 +
  21.158 +                if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
  21.159 +                    throw new ClassCastException(String.valueOf(o));
  21.160 +                }
  21.161 +
  21.162 +                oos.writeObject(o);
  21.163 +            }
  21.164 +        }
  21.165 +
  21.166 +        oos.writeObject(null);
  21.167 +    }
  21.168 +
  21.169 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
  21.170 +        object = (Node) ois.readObject();
  21.171 +        interfaces = new WeakHashMap<Class,Object>();
  21.172 +
  21.173 +        String clazz;
  21.174 +        ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
  21.175 +
  21.176 +        while ((clazz = (String) ois.readObject()) != null) {
  21.177 +            Object o = ois.readObject();
  21.178 +
  21.179 +            if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
  21.180 +                throw new ClassCastException(String.valueOf(o));
  21.181 +            }
  21.182 +
  21.183 +            Class c = Class.forName(clazz, false, l);
  21.184 +            interfaces.put(c, o);
  21.185 +        }
  21.186 +    }
  21.187 +
  21.188 +    /** Adds an item into the tree.
  21.189 +    * @param item to add
  21.190 +    * @return true if the Item has been added for the first time or false if some other
  21.191 +    *    item equal to this one already existed in the lookup
  21.192 +    */
  21.193 +    public boolean add(AbstractLookup.Pair<?> item, ArrayList<Class> affected) {
  21.194 +        Node node = registerClass(object, item);
  21.195 +
  21.196 +        affected.add(node.getType());
  21.197 +
  21.198 +        if (node.assignItem(this, item)) {
  21.199 +            // this is the first item added to n.items
  21.200 +            // ok, we have to test interfaces too
  21.201 +        } else {
  21.202 +            // equal item is already there => stop processing
  21.203 +            return false;
  21.204 +        }
  21.205 +
  21.206 +        boolean registeredAsInterface = registerInterface(item, affected);
  21.207 +
  21.208 +        return registeredAsInterface;
  21.209 +    }
  21.210 +
  21.211 +    /** Removes an item.
  21.212 +    */
  21.213 +    public void remove(AbstractLookup.Pair item, ArrayList<Class> affected) {
  21.214 +        Node n = removeClass(object, item);
  21.215 +
  21.216 +        if (n != null) {
  21.217 +            affected.add(n.getType());
  21.218 +        }
  21.219 +
  21.220 +        removeInterface(item, affected);
  21.221 +    }
  21.222 +
  21.223 +    /** Removes all items that are not present in the provided collection.
  21.224 +    * @param retain collection of Pairs to keep them in
  21.225 +    * @param notify set of Classes that has possibly changed
  21.226 +    */
  21.227 +    public void retainAll(Map retain, ArrayList<Class> notify) {
  21.228 +        retainAllInterface(retain, notify);
  21.229 +        retainAllClasses(object, retain, notify);
  21.230 +    }
  21.231 +
  21.232 +    /** Queries for instances of given class.
  21.233 +    * @param clazz the class to check
  21.234 +    * @return enumeration of Item
  21.235 +    * @see #unsorted
  21.236 +    */
  21.237 +    @SuppressWarnings("unchecked")
  21.238 +    public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
  21.239 +        if ((clazz != null) && clazz.isInterface()) {
  21.240 +            return (Enumeration)searchInterface(clazz);
  21.241 +        } else {
  21.242 +            return (Enumeration)searchClass(object, clazz);
  21.243 +        }
  21.244 +    }
  21.245 +
  21.246 +    /** A method to check whether the enumeration returned from
  21.247 +     * lookup method is sorted or is not
  21.248 +     * @param en enumeration to check
  21.249 +     * @return true if it is unsorted and needs to be sorted to find
  21.250 +     *   pair with smallest index
  21.251 +     */
  21.252 +    public static boolean unsorted(Enumeration en) {
  21.253 +        return en instanceof NeedsSortEnum;
  21.254 +    }
  21.255 +
  21.256 +    /** Prints debug messages.
  21.257 +     * @param out stream to output to
  21.258 +     * @param instances print also instances of the
  21.259 +     */
  21.260 +    public void print(java.io.PrintStream out, boolean instances) {
  21.261 +        printNode(object, "", out, instances); // NOI18N
  21.262 +    }
  21.263 +
  21.264 +    //
  21.265 +    // methods to work on classes which are not interfaces
  21.266 +    //
  21.267 +
  21.268 +    /** Searches the subtree and register the item where necessary.
  21.269 +    * @return the node that should contain the item
  21.270 +    */
  21.271 +    private static Node registerClass(Node n, AbstractLookup.Pair item) {
  21.272 +        if (!n.accepts(item)) {
  21.273 +            return null;
  21.274 +        }
  21.275 +
  21.276 +        if (n.children != null) {
  21.277 +            Iterator it = n.children.iterator();
  21.278 +
  21.279 +            for (;;) {
  21.280 +                Node ch = extractNode(it);
  21.281 +
  21.282 +                if (ch == null) {
  21.283 +                    break;
  21.284 +                }
  21.285 +
  21.286 +                Node result = registerClass(ch, item);
  21.287 +
  21.288 +                if (result != null) {
  21.289 +                    // it is in subclass, in case of classes, it cannot
  21.290 +                    // be any other class
  21.291 +                    return result;
  21.292 +                }
  21.293 +            }
  21.294 +        }
  21.295 +
  21.296 +        // ok, nobody of our subclasses wants the class, I'll take it
  21.297 +        return n;
  21.298 +    }
  21.299 +
  21.300 +    /** Removes the item from the tree of objects.
  21.301 +    * @return most narrow class that this item was removed from
  21.302 +    */
  21.303 +    private static Node removeClass(Node n, AbstractLookup.Pair item) {
  21.304 +        if (!n.accepts(item)) {
  21.305 +            return null;
  21.306 +        }
  21.307 +
  21.308 +        if ((n.items != null) && n.items.remove(item)) {
  21.309 +            // this node really contains the item
  21.310 +            return n;
  21.311 +        }
  21.312 +
  21.313 +        if (n.children != null) {
  21.314 +            Iterator it = n.children.iterator();
  21.315 +
  21.316 +            for (;;) {
  21.317 +                Node ch = extractNode(it);
  21.318 +
  21.319 +                if (ch == null) {
  21.320 +                    break;
  21.321 +                }
  21.322 +
  21.323 +                Node result = removeClass(ch, item);
  21.324 +
  21.325 +                // If the children node was emptied, remove it if possible.
  21.326 +                if (((ch.items == null) || ch.items.isEmpty()) && ((ch.children == null) || ch.children.isEmpty())) {
  21.327 +                    it.remove();
  21.328 +                }
  21.329 +
  21.330 +                if (result != null) {
  21.331 +                    // it is in subclass, in case of classes, it cannot
  21.332 +                    // be any other class
  21.333 +                    return result;
  21.334 +                }
  21.335 +            }
  21.336 +        }
  21.337 +
  21.338 +        // nobody found
  21.339 +        return null;
  21.340 +    }
  21.341 +
  21.342 +    /** Finds a node that represents a class.
  21.343 +    * @param n node to search from
  21.344 +    * @param clazz the clazz to find
  21.345 +    * @return node that represents clazz in the tree or null if the clazz is not
  21.346 +    *    represented under the node n
  21.347 +    */
  21.348 +    private Node classToNode(final Node n, final Class<?> clazz) {
  21.349 +        if (!n.accepts(clazz)) {
  21.350 +            // nothing from us
  21.351 +            return null;
  21.352 +        }
  21.353 +
  21.354 +        if (n.getType() == clazz) {
  21.355 +            // we have found what we need
  21.356 +            return n;
  21.357 +        }
  21.358 +
  21.359 +        if (n.children != null) {
  21.360 +            // have to proceed to children
  21.361 +            Iterator it = n.children.iterator();
  21.362 +
  21.363 +            for (;;) {
  21.364 +                final Node ch = extractNode(it);
  21.365 +
  21.366 +                if (ch == null) {
  21.367 +                    break;
  21.368 +                }
  21.369 +
  21.370 +                Node found = classToNode(ch, clazz);
  21.371 +
  21.372 +                if ((found != null) && ch.deserialized()) {
  21.373 +                    class VerifyJob implements AbstractLookup.ISE.Job {
  21.374 +                        private AbstractLookup.Pair<?>[] pairs;
  21.375 +                        private boolean[] answers;
  21.376 +
  21.377 +                        public VerifyJob(Collection<Pair> items) {
  21.378 +                            if (items != null) {
  21.379 +                                pairs = items.toArray(new AbstractLookup.Pair[0]);
  21.380 +                            }
  21.381 +                        }
  21.382 +
  21.383 +                        public void before() {
  21.384 +                            // make sure the node is converted into deserialized state
  21.385 +                            ch.deserialized();
  21.386 +
  21.387 +                            if (pairs != null) {
  21.388 +                                answers = new boolean[pairs.length];
  21.389 +
  21.390 +                                for (int i = 0; i < pairs.length; i++) {
  21.391 +                                    answers[i] = pairs[i].instanceOf(clazz);
  21.392 +                                }
  21.393 +                            }
  21.394 +                        }
  21.395 +
  21.396 +                        public void inside() {
  21.397 +                            if (pairs != null) {
  21.398 +                                for (int i = 0; i < pairs.length; i++) {
  21.399 +                                    if (answers[i]) {
  21.400 +                                        ch.assignItem(InheritanceTree.this, pairs[i]);
  21.401 +                                        n.items.remove(pairs[i]);
  21.402 +                                    }
  21.403 +                                }
  21.404 +                            }
  21.405 +
  21.406 +                            if (n.children != null) {
  21.407 +                                // consolidate all nodes that represent the same class
  21.408 +                                HashMap<Class,Node> nodes = new HashMap<Class,Node>(n.children.size() * 3);
  21.409 +
  21.410 +                                Iterator child = n.children.iterator();
  21.411 +
  21.412 +                                while (child.hasNext()) {
  21.413 +                                    Node node = extractNode(child);
  21.414 +                                    if (node == null) {
  21.415 +                                        continue;
  21.416 +                                    }
  21.417 +                                    Node prev = nodes.put(node.getType(), node);
  21.418 +
  21.419 +                                    if (prev != null) {
  21.420 +                                        child.remove();
  21.421 +                                        nodes.put(node.getType(), prev);
  21.422 +
  21.423 +                                        // mark as being deserialized
  21.424 +                                        prev.markDeserialized();
  21.425 +
  21.426 +                                        if (prev.children == null) {
  21.427 +                                            prev.children = node.children;
  21.428 +                                        } else {
  21.429 +                                            if (node.children != null) {
  21.430 +                                                prev.children.addAll(node.children);
  21.431 +                                            }
  21.432 +                                        }
  21.433 +
  21.434 +                                        if (node.items != null) {
  21.435 +                                            Iterator items = node.items.iterator();
  21.436 +
  21.437 +                                            while (items.hasNext()) {
  21.438 +                                                AbstractLookup.Pair item = (AbstractLookup.Pair) items.next();
  21.439 +                                                prev.assignItem(InheritanceTree.this, item);
  21.440 +                                            }
  21.441 +                                        }
  21.442 +                                    }
  21.443 +                                }
  21.444 +                            }
  21.445 +                        }
  21.446 +                    }
  21.447 +
  21.448 +                    VerifyJob verify = new VerifyJob(n.items);
  21.449 +
  21.450 +                    try {
  21.451 +                        verify.before();
  21.452 +                    } catch (AbstractLookup.ISE ex) {
  21.453 +                        // mark deserialized again
  21.454 +                        ch.markDeserialized();
  21.455 +                        ex.registerJob(verify);
  21.456 +                        throw ex;
  21.457 +                    }
  21.458 +
  21.459 +                    verify.inside();
  21.460 +
  21.461 +                    found = classToNode(ch, clazz);
  21.462 +                }
  21.463 +
  21.464 +                if (found != null) {
  21.465 +                    // class found in one of subnodes
  21.466 +                    return found;
  21.467 +                }
  21.468 +            }
  21.469 +        }
  21.470 +
  21.471 +        class TwoJobs implements AbstractLookup.ISE.Job {
  21.472 +            private AbstractLookup.Pair[] pairs;
  21.473 +            private boolean[] answers;
  21.474 +            private Node newNode;
  21.475 +
  21.476 +            public void before() {
  21.477 +                // have to create new subnode and possibly reparent one of my own
  21.478 +                // but all changes can be done only if we will not be interrupted from
  21.479 +                // outside - e.g. instanceOf methods will not throw exception
  21.480 +                // first of all let's compute the answers to method instanceOf
  21.481 +                AbstractLookup.Pair[] arr = null;
  21.482 +                boolean[] boolArr = null;
  21.483 +
  21.484 +                if (n.items != null) {
  21.485 +                    arr = new AbstractLookup.Pair[n.items.size()];
  21.486 +                    boolArr = new boolean[n.items.size()];
  21.487 +
  21.488 +                    int i = 0;
  21.489 +                    Iterator<Pair> it = n.items.iterator();
  21.490 +
  21.491 +                    while (it.hasNext()) {
  21.492 +                        AbstractLookup.Pair<?> item = it.next();
  21.493 +                        arr[i] = item;
  21.494 +                        boolArr[i] = item.instanceOf(clazz);
  21.495 +                        i++;
  21.496 +                    }
  21.497 +                }
  21.498 +
  21.499 +                pairs = arr;
  21.500 +                answers = boolArr;
  21.501 +            }
  21.502 +
  21.503 +            public void inside() {
  21.504 +                // test if the query has not chagned since
  21.505 +                if (pairs != null) {
  21.506 +                    if (!Arrays.equals(n.items.toArray(), pairs)) {
  21.507 +                        // ok, let try once more
  21.508 +                        return;
  21.509 +                    }
  21.510 +                }
  21.511 +
  21.512 +                internal();
  21.513 +            }
  21.514 +
  21.515 +            public void internal() {
  21.516 +                ArrayList<Node> reparent = null;
  21.517 +
  21.518 +                if (n.children == null) {
  21.519 +                    n.children = new ArrayList<Node>();
  21.520 +                } else {
  21.521 +                    // scan thru all my nodes if some of them are not a subclass
  21.522 +                    // of clazz => then they would need to become child of newNode
  21.523 +                    Iterator it = n.children.iterator();
  21.524 +
  21.525 +                    for (;;) {
  21.526 +                        Node r = extractNode(it);
  21.527 +
  21.528 +                        if (r == null) {
  21.529 +                            break;
  21.530 +                        }
  21.531 +
  21.532 +                        if (clazz.isAssignableFrom(r.getType())) {
  21.533 +                            if (reparent == null) {
  21.534 +                                reparent = new ArrayList<Node>();
  21.535 +                            }
  21.536 +
  21.537 +                            reparent.add(r);
  21.538 +                            it.remove();
  21.539 +                        }
  21.540 +                    }
  21.541 +                }
  21.542 +
  21.543 +                newNode = new Node(clazz);
  21.544 +                n.children.add(newNode);
  21.545 +
  21.546 +                if (reparent != null) {
  21.547 +                    // reassing reparent node as a child of newNode
  21.548 +                    newNode.children = reparent;
  21.549 +                }
  21.550 +
  21.551 +                // now take all my items that are instances of that class and
  21.552 +                // reasign them
  21.553 +                if (n.items != null) {
  21.554 +                    Iterator it = n.items.iterator();
  21.555 +                    int i = 0;
  21.556 +
  21.557 +                    while (it.hasNext()) {
  21.558 +                        AbstractLookup.Pair item = (AbstractLookup.Pair) it.next();
  21.559 +
  21.560 +                        if (answers[i]) { // answers[i] is precomputed value of item.instanceOf (clazz))
  21.561 +                            it.remove();
  21.562 +                            newNode.assignItem(InheritanceTree.this, pairs[i]);
  21.563 +                        }
  21.564 +
  21.565 +                        i++;
  21.566 +                    }
  21.567 +                }
  21.568 +            }
  21.569 +        }
  21.570 +
  21.571 +        TwoJobs j = new TwoJobs();
  21.572 +
  21.573 +        try {
  21.574 +            j.before();
  21.575 +        } catch (AbstractLookup.ISE ex) {
  21.576 +            // ok, it is not possible to call instanceOf now, let's 
  21.577 +            // schedule it for later
  21.578 +            // so register recovery job 
  21.579 +            ex.registerJob(j);
  21.580 +            throw ex;
  21.581 +        }
  21.582 +
  21.583 +        j.internal();
  21.584 +
  21.585 +        // newNode represents my clazz
  21.586 +        return j.newNode;
  21.587 +    }
  21.588 +
  21.589 +    /** Search for a requested class.
  21.590 +    * @return enumeration of Pair
  21.591 +    */
  21.592 +    private Enumeration<Pair> searchClass(Node n, Class<?> clazz) {
  21.593 +        if (clazz != null) {
  21.594 +            n = classToNode(n, clazz);
  21.595 +        }
  21.596 +
  21.597 +        if (n == null) {
  21.598 +            // not for us
  21.599 +            return emptyEn();
  21.600 +        } else {
  21.601 +            return nodeToEnum(n);
  21.602 +        }
  21.603 +    }
  21.604 +
  21.605 +    /** Retains all classes. Removes nodes which items and children are emptied, works
  21.606 +     * recursivelly from specified root node.
  21.607 +     * @param node root node from which to start to process the tree
  21.608 +     * @param retain a map from (Item, AbstractLookup.Info) that describes which items to retain
  21.609 +     *    and witch integer to assign them
  21.610 +     * @param notify collection of classes will be changed
  21.611 +     * @return <code>true<code> if some items were changed and node items and children are emptied,
  21.612 +     * those nodes, excluding root, will be removed from tree */
  21.613 +    private boolean retainAllClasses(Node node, Map retain, Collection<Class> notify) {
  21.614 +        boolean retained = false;
  21.615 +
  21.616 +        if ((node.items != null) && (retain != null)) {
  21.617 +            Iterator<Pair> it = node.items.iterator();
  21.618 +
  21.619 +            while (it.hasNext()) {
  21.620 +                AbstractLookup.Pair<?> item = it.next();
  21.621 +                AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(item);
  21.622 +
  21.623 +                if (n == null) {
  21.624 +                    // remove this item, it should not be there
  21.625 +                    it.remove();
  21.626 +                    retained = true;
  21.627 +                } else {
  21.628 +                    // change the index
  21.629 +                    if (item.getIndex() != n.index) {
  21.630 +                        item.setIndex(null, n.index);
  21.631 +
  21.632 +                        //                        notify.addAll ((ArrayList)n.transaction);
  21.633 +                    }
  21.634 +                }
  21.635 +            }
  21.636 +
  21.637 +            if (retained && (notify != null)) {
  21.638 +                // type of this node has been changed
  21.639 +                notify.add(node.getType());
  21.640 +            }
  21.641 +        }
  21.642 +
  21.643 +        if (node.children != null) {
  21.644 +            for (Iterator it = node.children.iterator();;) {
  21.645 +                Node ch = extractNode(it);
  21.646 +
  21.647 +                if (ch == null) {
  21.648 +                    break;
  21.649 +                }
  21.650 +
  21.651 +                boolean result = retainAllClasses(ch, retain, notify);
  21.652 +
  21.653 +                if (result) {
  21.654 +                    // The children node was emptied and has no children -> remove it.
  21.655 +                    it.remove();
  21.656 +                }
  21.657 +            }
  21.658 +        }
  21.659 +
  21.660 +        return retained && node.items.isEmpty() && ((node.children == null) || node.children.isEmpty());
  21.661 +    }
  21.662 +
  21.663 +    /** A method that creates enumeration of all items under given node.
  21.664 +     *
  21.665 +     * @param n node to create enumeration for
  21.666 +     * @return enumeration of Pairs
  21.667 +     */
  21.668 +    private static Enumeration<Pair> nodeToEnum(Node n) {
  21.669 +        if (n.children == null) {
  21.670 +            // create a simple enumeration because we do not have children
  21.671 +            Enumeration<Pair> e;
  21.672 +            if (n.items == null) {
  21.673 +                e = emptyEn();
  21.674 +            } else {
  21.675 +                e = Collections.enumeration(n.items);
  21.676 +            }
  21.677 +            return e;
  21.678 +        }
  21.679 +
  21.680 +        // create enumeration of Items
  21.681 +        return new NeedsSortEnum(n);
  21.682 +    }
  21.683 +
  21.684 +    //
  21.685 +    // Methods to work on interfaces
  21.686 +    // 
  21.687 +
  21.688 +    /** Registers an item with interfaces.
  21.689 +    * @param item item to register
  21.690 +    * @param affected list of classes that were affected
  21.691 +    * @return false if similar item has already been registered
  21.692 +    */
  21.693 +    @SuppressWarnings("unchecked")
  21.694 +    private boolean registerInterface(AbstractLookup.Pair<?> item, Collection<Class> affected) {
  21.695 +        if (interfaces == null) {
  21.696 +            return true;
  21.697 +        }
  21.698 +
  21.699 +        Iterator<Map.Entry<Class,Object>> it = interfaces.entrySet().iterator();
  21.700 +
  21.701 +        while (it.hasNext()) {
  21.702 +            Map.Entry<Class,Object> entry = it.next();
  21.703 +            Class<?> iface = entry.getKey();
  21.704 +
  21.705 +            if (item.instanceOf(iface)) {
  21.706 +                Object value = entry.getValue();
  21.707 +
  21.708 +                if (value instanceof Collection) {
  21.709 +                    Collection<Object> set = (Collection<Object>) value;
  21.710 +
  21.711 +                    if (!set.add(item)) {
  21.712 +                        // item is already there, probably (if everything is correct) is registered in 
  21.713 +                        // all other ifaces too, so stop additional testing
  21.714 +                        return false;
  21.715 +                    }
  21.716 +                } else {
  21.717 +                    // there is just one pair right now
  21.718 +                    if (value.equals(item)) {
  21.719 +                        // item is there => stop processing (same as above)
  21.720 +                        return false;
  21.721 +                    }
  21.722 +
  21.723 +                    // otherwise replace the single item with ArrayList
  21.724 +                    ArrayList<Object> ll = new ArrayList<Object>(3);
  21.725 +                    ll.add(value);
  21.726 +                    ll.add(item);
  21.727 +                    entry.setValue(ll);
  21.728 +                }
  21.729 +
  21.730 +                affected.add(iface);
  21.731 +            }
  21.732 +        }
  21.733 +
  21.734 +        return true;
  21.735 +    }
  21.736 +
  21.737 +    /** Removes interface.
  21.738 +    * @param item item to register
  21.739 +    * @param affected list of classes that were affected
  21.740 +    */
  21.741 +    @SuppressWarnings("unchecked")
  21.742 +    private void removeInterface(AbstractLookup.Pair item, Collection affected) {
  21.743 +        if (interfaces == null) {
  21.744 +            return;
  21.745 +        }
  21.746 +
  21.747 +        Iterator it = interfaces.entrySet().iterator();
  21.748 +
  21.749 +        while (it.hasNext()) {
  21.750 +            Map.Entry entry = (Map.Entry) it.next();
  21.751 +            Object value = entry.getValue();
  21.752 +
  21.753 +            if (value instanceof Collection) {
  21.754 +                Collection set = (Collection) value;
  21.755 +
  21.756 +                if (set.remove(item)) {
  21.757 +                    if (set.size() == 1) {
  21.758 +                        // if there is just one item remaining change to single item mode
  21.759 +                        entry.setValue(set.iterator().next());
  21.760 +                    }
  21.761 +
  21.762 +                    // adds the Class the item was register to into affected
  21.763 +                    affected.add(entry.getKey());
  21.764 +                }
  21.765 +            } else {
  21.766 +                // single item value
  21.767 +                if (value.equals(item)) {
  21.768 +                    // Emptied -> remove.
  21.769 +                    it.remove();
  21.770 +
  21.771 +                    affected.add(entry.getKey());
  21.772 +                }
  21.773 +            }
  21.774 +        }
  21.775 +    }
  21.776 +
  21.777 +    /** Retains some items.
  21.778 +    * @param retainItems items to retain and their mapping to index numbers
  21.779 +    *    (AbstractLookup.Pair -> AbstractLookup.Info)
  21.780 +    * @param affected list of classes that were affected
  21.781 +    */
  21.782 +    @SuppressWarnings("unchecked")
  21.783 +    private void retainAllInterface(Map retainItems, Collection affected) {
  21.784 +        if (interfaces == null) {
  21.785 +            return;
  21.786 +        }
  21.787 +
  21.788 +        Iterator it = interfaces.entrySet().iterator();
  21.789 +
  21.790 +        while (it.hasNext()) {
  21.791 +            Map.Entry entry = (Map.Entry) it.next();
  21.792 +            Object value = entry.getValue();
  21.793 +
  21.794 +            HashMap<?,?> retain = new HashMap(retainItems);
  21.795 +
  21.796 +            Iterator elems;
  21.797 +            boolean multi = value instanceof Collection;
  21.798 +
  21.799 +            if (multi) {
  21.800 +                // collection mode
  21.801 +                elems = ((Collection) value).iterator();
  21.802 +            } else {
  21.803 +                // single item mode
  21.804 +                elems = Collections.singleton(value).iterator();
  21.805 +            }
  21.806 +
  21.807 +            boolean changed = false;
  21.808 +            boolean reordered = false;
  21.809 +
  21.810 +            while (elems.hasNext()) {
  21.811 +                AbstractLookup.Pair p = (AbstractLookup.Pair) elems.next();
  21.812 +
  21.813 +                AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(p);
  21.814 +
  21.815 +                if (n == null) {
  21.816 +                    if (multi) {
  21.817 +                        // remove it
  21.818 +                        elems.remove();
  21.819 +                    }
  21.820 +
  21.821 +                    changed = true;
  21.822 +                } else {
  21.823 +                    if (p.getIndex() != n.index) {
  21.824 +                        // improve the index
  21.825 +                        p.setIndex(null, n.index);
  21.826 +
  21.827 +                        //                    affected.addAll ((ArrayList)n.transaction);
  21.828 +                        reordered = true;
  21.829 +                    }
  21.830 +                }
  21.831 +            }
  21.832 +
  21.833 +            if (reordered && value instanceof List) {
  21.834 +                // if reordered, than update the order in the collection
  21.835 +                List l = (List) value;
  21.836 +                Collections.sort(l, ALPairComparator.DEFAULT);
  21.837 +            }
  21.838 +
  21.839 +            if (changed) {
  21.840 +                if (multi) {
  21.841 +                    Collection c = (Collection) value;
  21.842 +
  21.843 +                    if (c.size() == 1) {
  21.844 +                        // back to single item mode
  21.845 +                        entry.setValue(c.iterator().next());
  21.846 +                    }
  21.847 +                } else {
  21.848 +                    // remove in single mode => remove completely
  21.849 +                    it.remove();
  21.850 +                }
  21.851 +
  21.852 +                // adds the Class the item was register to into affected
  21.853 +                affected.add(entry.getKey());
  21.854 +            }
  21.855 +        }
  21.856 +    }
  21.857 +
  21.858 +    /** Searches for a clazz between interfaces.
  21.859 +    * @param clazz class to search for
  21.860 +    * @return enumeration of Items
  21.861 +    */
  21.862 +    @SuppressWarnings("unchecked")
  21.863 +    private Enumeration<Pair> searchInterface(final Class<?> clazz) {
  21.864 +        if (interfaces == null) {
  21.865 +            // first call for interface, only initialize
  21.866 +            interfaces = new WeakHashMap();
  21.867 +        }
  21.868 +
  21.869 +        Object obj = interfaces.get(clazz);
  21.870 +
  21.871 +        if (obj == null) {
  21.872 +            // set of items
  21.873 +            AbstractLookup.Pair one = null;
  21.874 +            ArrayList items = null;
  21.875 +
  21.876 +            Enumeration en = lookup(Object.class);
  21.877 +
  21.878 +            while (en.hasMoreElements()) {
  21.879 +                AbstractLookup.Pair it = (AbstractLookup.Pair) en.nextElement();
  21.880 +
  21.881 +                if (it.instanceOf(clazz)) {
  21.882 +                    // ok, this item implements given clazz
  21.883 +                    if (one == null) {
  21.884 +                        one = it;
  21.885 +                    } else {
  21.886 +                        if (items == null) {
  21.887 +                            items = new ArrayList(3);
  21.888 +                            items.add(one);
  21.889 +                        }
  21.890 +
  21.891 +                        items.add(it);
  21.892 +                    }
  21.893 +                }
  21.894 +            }
  21.895 +
  21.896 +            if ((items == null) && (one != null)) {
  21.897 +                // single item mode
  21.898 +                interfaces.put(clazz, one);
  21.899 +
  21.900 +                return singletonEn(one);
  21.901 +            } else {
  21.902 +                if (items == null) {
  21.903 +                    items = new ArrayList(2);
  21.904 +                }
  21.905 +
  21.906 +                interfaces.put(clazz, items);
  21.907 +
  21.908 +                return Collections.enumeration(items);
  21.909 +            }
  21.910 +        } else {
  21.911 +            if (obj instanceof Collection) {
  21.912 +                return Collections.enumeration((Collection) obj);
  21.913 +            } else {
  21.914 +                // single item mode
  21.915 +                return singletonEn((Pair)obj);
  21.916 +            }
  21.917 +        }
  21.918 +    }
  21.919 +
  21.920 +    /** Extracts a node from an iterator, returning null if no next element found
  21.921 +     */
  21.922 +    private static Node extractNode(Iterator it) {
  21.923 +        while (it.hasNext()) {
  21.924 +            Node n = (Node) it.next();
  21.925 +
  21.926 +            if (n.get() == null) {
  21.927 +                it.remove();
  21.928 +            } else {
  21.929 +                return n;
  21.930 +            }
  21.931 +        }
  21.932 +
  21.933 +        return null;
  21.934 +    }
  21.935 +
  21.936 +    /** Prints debug info about the node.
  21.937 +     * @param n node to print
  21.938 +     * @param sp spaces to add
  21.939 +     * @param out where
  21.940 +     * @param instances print also instances
  21.941 +     */
  21.942 +    private static void printNode(Node n, String sp, java.io.PrintStream out, boolean instances) {
  21.943 +        int i;
  21.944 +        Iterator it;
  21.945 +
  21.946 +        Class type = n.getType();
  21.947 +
  21.948 +        out.print(sp);
  21.949 +        out.println("Node for: " + type + "\t" + ((type == null) ? null : type.getClassLoader())); // NOI18N
  21.950 +
  21.951 +        if (n.items != null) {
  21.952 +            i = 0;
  21.953 +            it = new ArrayList<Pair>(n.items).iterator();
  21.954 +
  21.955 +            while (it.hasNext()) {
  21.956 +                AbstractLookup.Pair p = (AbstractLookup.Pair) it.next();
  21.957 +                out.print(sp);
  21.958 +                out.print("  item (" + i++ + "): ");
  21.959 +                out.print(p); // NOI18N
  21.960 +                out.print(" id: " + Integer.toHexString(System.identityHashCode(p))); // NOI18N
  21.961 +                out.print(" index: "); // NOI18N
  21.962 +                out.print(p.getIndex());
  21.963 +
  21.964 +                if (instances) {
  21.965 +                    out.print(" I: " + p.getInstance());
  21.966 +                }
  21.967 +
  21.968 +                out.println();
  21.969 +            }
  21.970 +        }
  21.971 +
  21.972 +        if (n.children != null) {
  21.973 +            i = 0;
  21.974 +            it = n.children.iterator();
  21.975 +
  21.976 +            while (it.hasNext()) {
  21.977 +                Node ch = (Node) it.next();
  21.978 +                printNode(ch, sp + "  ", out, instances); // NOI18N
  21.979 +            }
  21.980 +        }
  21.981 +    }
  21.982 +
  21.983 +    public ReferenceToResult registerReferenceToResult(ReferenceToResult<?> newRef) {
  21.984 +        if (reg == null) {
  21.985 +            reg = new HashMap<Class,ReferenceToResult>();
  21.986 +        }
  21.987 +
  21.988 +        Class<? extends Object> clazz = newRef.template.getType();
  21.989 +
  21.990 +        // initialize the data structures if not yet
  21.991 +        lookup(clazz);
  21.992 +
  21.993 +        // newRef will be the new head of the list
  21.994 +        return reg.put(clazz, newRef);
  21.995 +    }
  21.996 +
  21.997 +    public ReferenceToResult cleanUpResult(Lookup.Template templ) {
  21.998 +        collectListeners(null, templ.getType());
  21.999 +
 21.1000 +        return (reg == null) ? null : reg.get(templ.getType());
 21.1001 +    }
 21.1002 +
 21.1003 +    public ArrayList<Class> beginTransaction(int ensure) {
 21.1004 +        return new ArrayList<Class>();
 21.1005 +    }
 21.1006 +
 21.1007 +    public void endTransaction(ArrayList<Class> list, Set<AbstractLookup.R> allAffectedResults) {
 21.1008 +        if (list.size() == 1) {
 21.1009 +            // probably the most common case
 21.1010 +            collectListeners(allAffectedResults, list.get(0));
 21.1011 +        } else {
 21.1012 +            Iterator it = list.iterator();
 21.1013 +
 21.1014 +            while (it.hasNext()) {
 21.1015 +                collectListeners(allAffectedResults, (Class) it.next());
 21.1016 +            }
 21.1017 +        }
 21.1018 +    }
 21.1019 +
 21.1020 +    /** Notifies all listeners that are interested in changes in this class.
 21.1021 +     * Should be called from synchronized places.
 21.1022 +     * @param allAffectedResults adds Results into this set
 21.1023 +     * @param c the class that has changed
 21.1024 +     */
 21.1025 +    private void collectListeners(Set<AbstractLookup.R> allAffectedResults, Class c) {
 21.1026 +        if (reg == null) {
 21.1027 +            return;
 21.1028 +        }
 21.1029 +
 21.1030 +        while (c != null) {
 21.1031 +            ReferenceToResult first = reg.get(c);
 21.1032 +            ReferenceIterator it = new ReferenceIterator(first);
 21.1033 +
 21.1034 +            while (it.next()) {
 21.1035 +                AbstractLookup.R result = it.current().getResult();
 21.1036 +
 21.1037 +                if (allAffectedResults != null) {
 21.1038 +                    // add result
 21.1039 +                    allAffectedResults.add(result);
 21.1040 +                }
 21.1041 +            }
 21.1042 +
 21.1043 +            if (first != it.first()) {
 21.1044 +                if (it.first() == null) {
 21.1045 +                    // we do not need have more results on this object
 21.1046 +                    reg.remove(c);
 21.1047 +                } else {
 21.1048 +                    // move the head of the list
 21.1049 +                    reg.put(c, it.first());
 21.1050 +                }
 21.1051 +            }
 21.1052 +
 21.1053 +            c = c.getSuperclass();
 21.1054 +        }
 21.1055 +
 21.1056 +        if (reg.isEmpty()) {
 21.1057 +            // clean up the list of all results if we do not need them anymore
 21.1058 +            reg = null;
 21.1059 +        }
 21.1060 +    }
 21.1061 +
 21.1062 +    /** Node in the tree.
 21.1063 +    */
 21.1064 +    static final class Node extends WeakReference<Class> implements Serializable {
 21.1065 +        static final long serialVersionUID = 3L;
 21.1066 +
 21.1067 +        /** children nodes */
 21.1068 +        public ArrayList<Node> children;
 21.1069 +
 21.1070 +        /** list of items assigned to this node (suspect to be subclasses) */
 21.1071 +        public Collection<Pair> items;
 21.1072 +
 21.1073 +        /** Constructor.
 21.1074 +        */
 21.1075 +        public Node(Class clazz) {
 21.1076 +            super(clazz);
 21.1077 +        }
 21.1078 +
 21.1079 +        /** Returns true if the object was deserialized also clears the serialized flag.
 21.1080 +         * @return true if so.
 21.1081 +         */
 21.1082 +        public boolean deserialized() {
 21.1083 +            if ((items == null) || items instanceof LinkedHashSet) {
 21.1084 +                return false;
 21.1085 +            }
 21.1086 +
 21.1087 +            if (items.isEmpty()) {
 21.1088 +                items = null;
 21.1089 +            } else {
 21.1090 +                items = new LinkedHashSet<Pair>(items);
 21.1091 +            }
 21.1092 +
 21.1093 +            return true;
 21.1094 +        }
 21.1095 +
 21.1096 +        /** Marks this item as being deserialized.
 21.1097 +         */
 21.1098 +        public void markDeserialized() {
 21.1099 +            if (items == null || items == Collections.EMPTY_LIST) {
 21.1100 +                items = Collections.emptyList();
 21.1101 +            } else {
 21.1102 +                items = Collections.synchronizedCollection(items);
 21.1103 +            }
 21.1104 +        }
 21.1105 +
 21.1106 +        /** Getter for the type associated with this node.
 21.1107 +         */
 21.1108 +        public Class<?> getType() {
 21.1109 +            Class<?> c = get();
 21.1110 +
 21.1111 +            // if  garbage collected, then return a garbage
 21.1112 +            return (c == null) ? Void.TYPE : c;
 21.1113 +        }
 21.1114 +
 21.1115 +        /** Checks whether a node can represent an class.
 21.1116 +        */
 21.1117 +        public boolean accepts(Class<?> clazz) {
 21.1118 +            if (getType() == Object.class) {
 21.1119 +                return true;
 21.1120 +            }
 21.1121 +
 21.1122 +            return getType().isAssignableFrom(clazz);
 21.1123 +        }
 21.1124 +
 21.1125 +        /** Checks whether item is instance of this node.
 21.1126 +        */
 21.1127 +        public boolean accepts(AbstractLookup.Pair<?> item) {
 21.1128 +            if (getType() == Object.class) {
 21.1129 +                // Object.class
 21.1130 +                return true;
 21.1131 +            }
 21.1132 +
 21.1133 +            return item.instanceOf(getType());
 21.1134 +        }
 21.1135 +
 21.1136 +        /** Assings an item to this node.
 21.1137 +        * @param item the item
 21.1138 +        * @return true if item has been added as new
 21.1139 +        */
 21.1140 +        public boolean assignItem(InheritanceTree tree, AbstractLookup.Pair<?> item) {
 21.1141 +            if ((items == null) || (items == Collections.EMPTY_LIST)) {
 21.1142 +                items = new LinkedHashSet<Pair>();
 21.1143 +                items.add(item);
 21.1144 +
 21.1145 +                return true;
 21.1146 +            }
 21.1147 +
 21.1148 +            if (items.contains(item)) {
 21.1149 +                Iterator<Pair> it = items.iterator();
 21.1150 +                Pair old;
 21.1151 +                for (;;) {
 21.1152 +                    old = it.next();
 21.1153 +                    if (item.equals(old)) {
 21.1154 +                        break;
 21.1155 +                    }
 21.1156 +                }
 21.1157 +
 21.1158 +                if (old != item) {
 21.1159 +                    // replace the items there
 21.1160 +                    item.setIndex(tree, old.getIndex());
 21.1161 +                }
 21.1162 +
 21.1163 +                it.remove();
 21.1164 +                items.add(item);
 21.1165 +
 21.1166 +                return false;
 21.1167 +            }
 21.1168 +
 21.1169 +            items.add(item);
 21.1170 +
 21.1171 +            return true;
 21.1172 +        }
 21.1173 +
 21.1174 +        private Object writeReplace() {
 21.1175 +            return new R(this);
 21.1176 +        }
 21.1177 +
 21.1178 +        @Override
 21.1179 +        public String toString() {
 21.1180 +            return "Node for " + get();
 21.1181 +        }
 21.1182 +    }
 21.1183 +     // End of class Node.
 21.1184 +
 21.1185 +    private static final class R implements Serializable {
 21.1186 +        static final long serialVersionUID = 1L;
 21.1187 +        private static ClassLoader l;
 21.1188 +        private String clazzName;
 21.1189 +        private transient Class<?> clazz;
 21.1190 +        private ArrayList<Node> children;
 21.1191 +        private Collection<Pair> items;
 21.1192 +
 21.1193 +        public R(Node n) {
 21.1194 +            this.clazzName = n.getType().getName();
 21.1195 +            this.children = n.children;
 21.1196 +
 21.1197 +            if (n.items instanceof LinkedHashSet || (n.items == null)) {
 21.1198 +                this.items = n.items;
 21.1199 +            } else {
 21.1200 +                this.items = new LinkedHashSet<Pair>(n.items);
 21.1201 +            }
 21.1202 +        }
 21.1203 +
 21.1204 +        private void readObject(ObjectInputStream ois)
 21.1205 +        throws IOException, ClassNotFoundException {
 21.1206 +            ois.defaultReadObject();
 21.1207 +
 21.1208 +            if (l == null) {
 21.1209 +                l = Lookup.getDefault().lookup(ClassLoader.class);
 21.1210 +            }
 21.1211 +
 21.1212 +            clazz = Class.forName(clazzName, false, l);
 21.1213 +        }
 21.1214 +
 21.1215 +        private Object readResolve() throws ObjectStreamException {
 21.1216 +            Node n = new Node(clazz);
 21.1217 +            n.children = children;
 21.1218 +            n.items = items;
 21.1219 +            n.markDeserialized();
 21.1220 +
 21.1221 +            return n;
 21.1222 +        }
 21.1223 +    }
 21.1224 +     // end of R
 21.1225 +
 21.1226 +    static Enumeration<Object> arrayEn(Object[] object) {
 21.1227 +        return Collections.enumeration(Arrays.asList(object));
 21.1228 +    }
 21.1229 +    static <T> Enumeration<T> singletonEn(T object) {
 21.1230 +        return Collections.enumeration(Collections.singleton(object));
 21.1231 +    }
 21.1232 +    static <T> Enumeration<T> emptyEn() {
 21.1233 +        return Collections.enumeration(Collections.<T>emptyList());
 21.1234 +    }
 21.1235 +
 21.1236 +    /** Just a marker class to be able to do instanceof and find out
 21.1237 +     * that this enumeration is not sorted
 21.1238 +     */
 21.1239 +    private static final class NeedsSortEnum extends LinkedList<Node>
 21.1240 +    implements Enumeration<Pair> {
 21.1241 +        private Enumeration<Pair> en;
 21.1242 +
 21.1243 +        public NeedsSortEnum(Node n) {
 21.1244 +            add(n);
 21.1245 +        }
 21.1246 +
 21.1247 +        private boolean ensureNext() {
 21.1248 +            for (;;) {
 21.1249 +                if (en != null && en.hasMoreElements()) {
 21.1250 +                    return true;
 21.1251 +                }
 21.1252 +                if (isEmpty()) {
 21.1253 +                    return false;
 21.1254 +                }
 21.1255 +
 21.1256 +                Node n2 = poll();
 21.1257 +                if (n2.children != null) {
 21.1258 +                    addAll(n2.children);
 21.1259 +                }
 21.1260 +
 21.1261 +                if (n2.items != null && !n2.items.isEmpty()) {
 21.1262 +                    en = Collections.enumeration(n2.items);
 21.1263 +                }
 21.1264 +            }
 21.1265 +        }
 21.1266 +
 21.1267 +        public boolean hasMoreElements() {
 21.1268 +            return ensureNext();
 21.1269 +        }
 21.1270 +
 21.1271 +        public Pair nextElement() {
 21.1272 +            if (!ensureNext()) {
 21.1273 +                throw new NoSuchElementException();
 21.1274 +            }
 21.1275 +            return en.nextElement();
 21.1276 +        }
 21.1277 +    }
 21.1278 +     // end of NeedsSortEnum
 21.1279 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/InstanceContent.java	Mon Dec 14 20:58:39 2009 +0100
    22.3 @@ -0,0 +1,378 @@
    22.4 +/*
    22.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    22.6 + *
    22.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    22.8 + *
    22.9 + * The contents of this file are subject to the terms of either the GNU
   22.10 + * General Public License Version 2 only ("GPL") or the Common
   22.11 + * Development and Distribution License("CDDL") (collectively, the
   22.12 + * "License"). You may not use this file except in compliance with the
   22.13 + * License. You can obtain a copy of the License at
   22.14 + * http://www.netbeans.org/cddl-gplv2.html
   22.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   22.16 + * specific language governing permissions and limitations under the
   22.17 + * License.  When distributing the software, include this License Header
   22.18 + * Notice in each file and include the License file at
   22.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   22.20 + * particular file as subject to the "Classpath" exception as provided
   22.21 + * by Sun in the GPL Version 2 section of the License file that
   22.22 + * accompanied this code. If applicable, add the following below the
   22.23 + * License Header, with the fields enclosed by brackets [] replaced by
   22.24 + * your own identifying information:
   22.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   22.26 + *
   22.27 + * Contributor(s):
   22.28 + *
   22.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   22.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   22.31 + * Microsystems, Inc. All Rights Reserved.
   22.32 + *
   22.33 + * If you wish your version of this file to be governed by only the CDDL
   22.34 + * or only the GPL Version 2, indicate your decision by adding
   22.35 + * "[Contributor] elects to include this software in this distribution
   22.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   22.37 + * single choice of license, a recipient has the option to distribute
   22.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   22.39 + * to extend the choice of license to its licensees as provided above.
   22.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   22.41 + * Version 2 license, then the option applies only if the new code is
   22.42 + * made subject to such option by the copyright holder.
   22.43 + */
   22.44 +package org.openide.util.lookup;
   22.45 +
   22.46 +import org.openide.util.lookup.AbstractLookup.Pair;
   22.47 +
   22.48 +import java.lang.ref.WeakReference;
   22.49 +
   22.50 +import java.util.*;
   22.51 +import java.util.concurrent.Executor;
   22.52 +import org.openide.util.Lookup.Item;
   22.53 +
   22.54 +
   22.55 +/** A special content implementation that can be passed to AbstractLookup
   22.56 + * and provides methods for registration of instances and lazy instances.
   22.57 + * <PRE>
   22.58 + *      InstanceContent ic = new InstanceContent ();
   22.59 + *      AbstractLookup al = new AbstractLookup (ic);
   22.60 + *
   22.61 + *      ic.add (new Object ());
   22.62 + *      ic.add (new Dimension (...));
   22.63 + *
   22.64 + *      Dimension theDim = (Dimension)al.lookup (Dimension.class);
   22.65 + * </PRE>
   22.66 + *
   22.67 + * @author  Jaroslav Tulach
   22.68 + *
   22.69 + * @since 1.25
   22.70 + */
   22.71 +public final class InstanceContent extends AbstractLookup.Content {
   22.72 +    /**
   22.73 +     * Create a new, empty content.
   22.74 +     */
   22.75 +    public InstanceContent() {
   22.76 +    }
   22.77 +
   22.78 +    /** Creates a content associated with an executor to handle dispatch
   22.79 +     * of changes.
   22.80 +     * @param notifyIn the executor to notify changes in
   22.81 +     * @since  7.16
   22.82 +     */
   22.83 +    public InstanceContent(Executor notifyIn) {
   22.84 +        super(notifyIn);
   22.85 +    }
   22.86 +    /** The method to add instance to the lookup with.
   22.87 +     * @param inst instance
   22.88 +     */
   22.89 +    public final void add(Object inst) {
   22.90 +        addPair(new SimpleItem<Object>(inst));
   22.91 +    }
   22.92 +
   22.93 +    /** Adds a convertible instance into the lookup. The <code>inst</code>
   22.94 +     * argument is just a key, not the actual value to appear in the lookup.
   22.95 +     * The value will be created on demand, later when it is really needed
   22.96 +     * by calling <code>convertor</code> methods.
   22.97 +     * <p>
   22.98 +     * This method is useful to delay creation of heavy weight objects.
   22.99 +     * Instead just register lightweight key and a convertor.
  22.100 +     * <p>
  22.101 +     * To remove registered object from lookup use {@link #remove(java.lang.Object, org.openide.util.lookup.InstanceContent.Convertor)}
  22.102 +     * with the same arguments.
  22.103 +     *
  22.104 +     * @param inst instance
  22.105 +     * @param conv convertor which postponing an instantiation,
  22.106 +     * if <code>conv==null</code> then the instance is registered directly.
  22.107 +     */
  22.108 +    public final <T,R> void add(T inst, Convertor<T,R> conv) {
  22.109 +        addPair(new ConvertingItem<T,R>(inst, conv));
  22.110 +    }
  22.111 +
  22.112 +    /** Remove instance.
  22.113 +     * @param inst instance
  22.114 +     */
  22.115 +    public final void remove(Object inst) {
  22.116 +        removePair(new SimpleItem<Object>(inst));
  22.117 +    }
  22.118 +
  22.119 +    /** Remove instance added with a convertor.
  22.120 +     * @param inst instance
  22.121 +     * @param conv convertor, if <code>conv==null</code> it is same like
  22.122 +     * remove(Object)
  22.123 +     */
  22.124 +    public final <T,R> void remove(T inst, Convertor<T,R> conv) {
  22.125 +        removePair(new ConvertingItem<T,R>(inst, conv));
  22.126 +    }
  22.127 +
  22.128 +    /** Changes all pairs in the lookup to new values. Converts collection of
  22.129 +     * instances to collection of pairs.
  22.130 +     * @param col the collection of (Item) objects
  22.131 +     * @param conv the convertor to use or null
  22.132 +     */
  22.133 +    public final <T,R> void set(Collection<T> col, Convertor<T,R> conv) {
  22.134 +        ArrayList<Pair<?>> l = new ArrayList<Pair<?>>(col.size());
  22.135 +        Iterator<T> it = col.iterator();
  22.136 +
  22.137 +        if (conv == null) {
  22.138 +            while (it.hasNext()) {
  22.139 +                l.add(new SimpleItem<T>(it.next()));
  22.140 +            }
  22.141 +        } else {
  22.142 +            while (it.hasNext()) {
  22.143 +                l.add(new ConvertingItem<T,R>(it.next(), conv));
  22.144 +            }
  22.145 +        }
  22.146 +
  22.147 +        setPairs(l);
  22.148 +    }
  22.149 +
  22.150 +    /** Convertor postpones an instantiation of an object.
  22.151 +     * @since 1.25
  22.152 +     */
  22.153 +    public static interface Convertor<T,R> {
  22.154 +        /** Convert obj to other object. There is no need to implement
  22.155 +         * cache mechanism. It is provided by
  22.156 +         * {@link Item#getInstance()} method itself. However the
  22.157 +         * method can be called more than once because instance is held
  22.158 +         * just by weak reference.
  22.159 +         *
  22.160 +         * @param obj the registered object
  22.161 +         * @return the object converted from this object
  22.162 +         */
  22.163 +        public R convert(T obj);
  22.164 +
  22.165 +        /** Return type of converted object. Accessible via
  22.166 +         * {@link Item#getType()}
  22.167 +         * @param obj the registered object
  22.168 +         * @return the class that will be produced from this object (class or
  22.169 +         *      superclass of convert (obj))
  22.170 +         */
  22.171 +        public Class<? extends R> type(T obj);
  22.172 +
  22.173 +        /** Computes the ID of the resulted object. Accessible via
  22.174 +         * {@link Item#getId()}.
  22.175 +         * @param obj the registered object
  22.176 +         * @return the ID for the object
  22.177 +         */
  22.178 +        public String id(T obj);
  22.179 +
  22.180 +        /** The human presentable name for the object. Accessible via
  22.181 +         * {@link Item#getDisplayName()}.
  22.182 +         * @param obj the registered object
  22.183 +         * @return the name representing the object for the user
  22.184 +         */
  22.185 +        public String displayName(T obj);
  22.186 +    }
  22.187 +
  22.188 +    /** Instance of one item representing an object.
  22.189 +     */
  22.190 +    final static class SimpleItem<T> extends Pair<T> {
  22.191 +        private T obj;
  22.192 +
  22.193 +        /** Create an item.
  22.194 +         * @obj object to register
  22.195 +         */
  22.196 +        public SimpleItem(T obj) {
  22.197 +            if (obj == null) {
  22.198 +                throw new NullPointerException();
  22.199 +            }
  22.200 +            this.obj = obj;
  22.201 +        }
  22.202 +
  22.203 +        /** Tests whether this item can produce object
  22.204 +         * of class c.
  22.205 +         */
  22.206 +        public boolean instanceOf(Class<?> c) {
  22.207 +            return c.isInstance(obj);
  22.208 +        }
  22.209 +
  22.210 +        /** Get instance of registered object. If convertor is specified then
  22.211 +         *  method InstanceLookup.Convertor.convertor is used and weak reference
  22.212 +         * to converted object is saved.
  22.213 +         * @return the instance of the object.
  22.214 +         */
  22.215 +        public T getInstance() {
  22.216 +            return obj;
  22.217 +        }
  22.218 +
  22.219 +        @Override
  22.220 +        public boolean equals(Object o) {
  22.221 +            if (o instanceof SimpleItem) {
  22.222 +                return obj.equals(((SimpleItem) o).obj);
  22.223 +            } else {
  22.224 +                return false;
  22.225 +            }
  22.226 +        }
  22.227 +
  22.228 +        @Override
  22.229 +        public int hashCode() {
  22.230 +            return obj.hashCode();
  22.231 +        }
  22.232 +
  22.233 +        /** An identity of the item.
  22.234 +         * @return string representing the item, that can be used for
  22.235 +         *   persistance purposes to locate the same item next time
  22.236 +         */
  22.237 +        public String getId() {
  22.238 +            return "IL[" + obj.toString(); // NOI18N
  22.239 +        }
  22.240 +
  22.241 +        /** Getter for display name of the item.
  22.242 +         */
  22.243 +        public String getDisplayName() {
  22.244 +            return obj.toString();
  22.245 +        }
  22.246 +
  22.247 +        /** Method that can test whether an instance of a class has been created
  22.248 +         * by this item.
  22.249 +         *
  22.250 +         * @param obj the instance
  22.251 +         * @return if the item has already create an instance and it is the same
  22.252 +         *  as obj.
  22.253 +         */
  22.254 +        protected boolean creatorOf(Object obj) {
  22.255 +            return obj == this.obj;
  22.256 +        }
  22.257 +
  22.258 +        /** The class of this item.
  22.259 +         * @return the correct class
  22.260 +         */
  22.261 +        @SuppressWarnings("unchecked")
  22.262 +        public Class<? extends T> getType() {
  22.263 +            return (Class<? extends T>)obj.getClass();
  22.264 +        }
  22.265 +    }
  22.266 +     // end of SimpleItem
  22.267 +
  22.268 +    /** Instance of one item registered in the map.
  22.269 +     */
  22.270 +    final static class ConvertingItem<T,R> extends Pair<R> {
  22.271 +        /** registered object */
  22.272 +        private T obj;
  22.273 +
  22.274 +        /** Reference to converted object. */
  22.275 +        private WeakReference<R> ref;
  22.276 +
  22.277 +        /** convertor to use */
  22.278 +        private Convertor<? super T,R> conv;
  22.279 +
  22.280 +        /** Create an item.
  22.281 +         * @obj object to register
  22.282 +         * @conv a convertor, can be <code>null</code>.
  22.283 +         */
  22.284 +        public ConvertingItem(T obj, Convertor<? super T,R> conv) {
  22.285 +            this.obj = obj;
  22.286 +            this.conv = conv;
  22.287 +        }
  22.288 +
  22.289 +        /** Tests whether this item can produce object
  22.290 +         * of class c.
  22.291 +         */
  22.292 +        public boolean instanceOf(Class<?> c) {
  22.293 +            return c.isAssignableFrom(getType());
  22.294 +        }
  22.295 +
  22.296 +        /** Returns converted object or null if obj has not been converted yet
  22.297 +         * or reference was cleared by garbage collector.
  22.298 +         */
  22.299 +        private R getConverted() {
  22.300 +            if (ref == null) {
  22.301 +                return null;
  22.302 +            }
  22.303 +
  22.304 +            return ref.get();
  22.305 +        }
  22.306 +
  22.307 +        /** Get instance of registered object. If convertor is specified then
  22.308 +         *  method InstanceLookup.Convertor.convertor is used and weak reference
  22.309 +         * to converted object is saved.
  22.310 +         * @return the instance of the object.
  22.311 +         */
  22.312 +        public synchronized R getInstance() {
  22.313 +            R converted = getConverted();
  22.314 +
  22.315 +            if (converted == null) {
  22.316 +                converted = conv.convert(obj);
  22.317 +                ref = new WeakReference<R>(converted);
  22.318 +            }
  22.319 +
  22.320 +            return converted;
  22.321 +        }
  22.322 +
  22.323 +        @Override
  22.324 +        public boolean equals(Object o) {
  22.325 +            if (o instanceof ConvertingItem) {
  22.326 +                return obj.equals(((ConvertingItem) o).obj);
  22.327 +            } else {
  22.328 +                return false;
  22.329 +            }
  22.330 +        }
  22.331 +
  22.332 +        @Override
  22.333 +        public int hashCode() {
  22.334 +            return obj.hashCode();
  22.335 +        }
  22.336 +
  22.337 +        /** An identity of the item.
  22.338 +         * @return string representing the item, that can be used for
  22.339 +         *   persistance purposes to locate the same item next time
  22.340 +         */
  22.341 +        public String getId() {
  22.342 +            return conv.id(obj);
  22.343 +        }
  22.344 +
  22.345 +        /** Getter for display name of the item.
  22.346 +         */
  22.347 +        public String getDisplayName() {
  22.348 +            return conv.displayName(obj);
  22.349 +        }
  22.350 +
  22.351 +        /** Method that can test whether an instance of a class has been created
  22.352 +         * by this item.
  22.353 +         *
  22.354 +         * @param obj the instance
  22.355 +         * @return if the item has already create an instance and it is the same
  22.356 +         *  as obj.
  22.357 +         */
  22.358 +        protected boolean creatorOf(Object obj) {
  22.359 +            if (conv == null) {
  22.360 +                return obj == this.obj;
  22.361 +            } else {
  22.362 +                return obj == getConverted();
  22.363 +            }
  22.364 +        }
  22.365 +
  22.366 +        /** The class of this item.
  22.367 +         * @return the correct class
  22.368 +         */
  22.369 +        @SuppressWarnings("unchecked")
  22.370 +        public Class<? extends R> getType() {
  22.371 +            R converted = getConverted();
  22.372 +
  22.373 +            if (converted == null) {
  22.374 +                return conv.type(obj);
  22.375 +            }
  22.376 +
  22.377 +            return (Class<? extends R>)converted.getClass();
  22.378 +        }
  22.379 +    }
  22.380 +     // end of ConvertingItem
  22.381 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/Lookups.java	Mon Dec 14 20:58:39 2009 +0100
    23.3 @@ -0,0 +1,317 @@
    23.4 +/*
    23.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    23.6 + *
    23.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    23.8 + *
    23.9 + * The contents of this file are subject to the terms of either the GNU
   23.10 + * General Public License Version 2 only ("GPL") or the Common
   23.11 + * Development and Distribution License("CDDL") (collectively, the
   23.12 + * "License"). You may not use this file except in compliance with the
   23.13 + * License. You can obtain a copy of the License at
   23.14 + * http://www.netbeans.org/cddl-gplv2.html
   23.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   23.16 + * specific language governing permissions and limitations under the
   23.17 + * License.  When distributing the software, include this License Header
   23.18 + * Notice in each file and include the License file at
   23.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   23.20 + * particular file as subject to the "Classpath" exception as provided
   23.21 + * by Sun in the GPL Version 2 section of the License file that
   23.22 + * accompanied this code. If applicable, add the following below the
   23.23 + * License Header, with the fields enclosed by brackets [] replaced by
   23.24 + * your own identifying information:
   23.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   23.26 + *
   23.27 + * Contributor(s):
   23.28 + *
   23.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   23.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
   23.31 + * Microsystems, Inc. All Rights Reserved.
   23.32 + *
   23.33 + * If you wish your version of this file to be governed by only the CDDL
   23.34 + * or only the GPL Version 2, indicate your decision by adding
   23.35 + * "[Contributor] elects to include this software in this distribution
   23.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   23.37 + * single choice of license, a recipient has the option to distribute
   23.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   23.39 + * to extend the choice of license to its licensees as provided above.
   23.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   23.41 + * Version 2 license, then the option applies only if the new code is
   23.42 + * made subject to such option by the copyright holder.
   23.43 + */
   23.44 +
   23.45 +package org.openide.util.lookup;
   23.46 +
   23.47 +import java.util.Arrays;
   23.48 +import org.netbeans.modules.openide.util.NamedServicesProvider;
   23.49 +import org.openide.util.Lookup;
   23.50 +
   23.51 +/**
   23.52 + * Static factory methods for creating common lookup implementations.
   23.53 + *
   23.54 + * @author David Strupl
   23.55 + * @since 2.21
   23.56 + */
   23.57 +public class Lookups {
   23.58 +
   23.59 +    /** static methods only */
   23.60 +    private Lookups() {}
   23.61 +
   23.62 +    /**
   23.63 +     * Creates a singleton lookup. It means lookup that contains only
   23.64 +     * one object specified via the supplied parameter. The lookup will
   23.65 +     * either return the object or null if the supplied template does
   23.66 +     * not match the class. If the specified argument is null the method
   23.67 +     * will end with NullPointerException.
   23.68 +     * @return Fully initialized lookup object ready to use
   23.69 +     * @throws NullPointerException if the supplied argument is null
   23.70 +     * @since 2.21
   23.71 +     */
   23.72 +    public static Lookup singleton(Object objectToLookup) {
   23.73 +        if (objectToLookup == null) {
   23.74 +            throw new NullPointerException();
   23.75 +        }
   23.76 +
   23.77 +        return new SingletonLookup(objectToLookup);
   23.78 +    }
   23.79 +
   23.80 +    /**
   23.81 +     * Creates a lookup that contains an array of objects specified via the
   23.82 +     * parameter. The resulting lookup is fixed in the following sense: it
   23.83 +     * contains only fixed set of objects passed in by the array parameter.
   23.84 +     * Its contents never changes so registering listeners on such lookup
   23.85 +     * does not have any observable effect (the listeners are never called).
   23.86 +     *
   23.87 +     * @param objectsToLookup list of objects to include
   23.88 +     * @return Fully initialized lookup object ready to use
   23.89 +     * @throws NullPointerException if the supplied argument is null
   23.90 +     * @since 2.21
   23.91 +     *
   23.92 +     */
   23.93 +    public static Lookup fixed(Object... objectsToLookup) {
   23.94 +        if (objectsToLookup == null) {
   23.95 +            throw new NullPointerException();
   23.96 +        }
   23.97 +
   23.98 +        if (objectsToLookup.length == 0) {
   23.99 +            return Lookup.EMPTY;
  23.100 +        }
  23.101 +
  23.102 +        if (objectsToLookup.length == 1) {
  23.103 +            return singleton(objectsToLookup[0]);
  23.104 +        }
  23.105 +
  23.106 +        return new SimpleLookup(Arrays.asList(objectsToLookup));
  23.107 +    }
  23.108 +
  23.109 +    /**
  23.110 +     * Creates a lookup that contains an array of objects specified via the
  23.111 +     * parameter. The resulting lookup is fixed in the following sense: it
  23.112 +     * contains only fixed set of objects passed in by the array parameter.
  23.113 +     * The objects returned from this lookup are converted to real objects
  23.114 +     * before they are returned by the lookup.
  23.115 +     * Its contents never changes so registering listeners on such lookup
  23.116 +     * does not have any observable effect (the listeners are never called).
  23.117 +     *
  23.118 +     * @return Fully initialized lookup object ready to use
  23.119 +     * @throws NullPointerException if the any of the arguments is null
  23.120 +     * @since 2.21
  23.121 +     *
  23.122 +     */
  23.123 +    public static <T,R> Lookup fixed(T[] keys, InstanceContent.Convertor<? super T,R> convertor) {
  23.124 +        if (keys == null) {
  23.125 +            throw new NullPointerException();
  23.126 +        }
  23.127 +
  23.128 +        if (convertor == null) {
  23.129 +            throw new NullPointerException();
  23.130 +        }
  23.131 +
  23.132 +        return new SimpleLookup(Arrays.asList(keys), convertor);
  23.133 +    }
  23.134 +
  23.135 +    /** Creates a lookup that delegates to another one but that one can change
  23.136 +     * from time to time. The returned lookup checks every time somebody calls
  23.137 +     * <code>lookup</code> or <code>lookupItem</code> method whether the
  23.138 +     * provider still returns the same lookup. If not, it updates state of
  23.139 +     * all {@link org.openide.util.Lookup.Result}s 
  23.140 +     * that it created (and that still exists).
  23.141 +     * <P>
  23.142 +     * The user of this method has to implement its provider's <code>getLookup</code>
  23.143 +     * method (must be thread safe and fast, will be called often and from any thread)
  23.144 +     * pass it to this method and use the returned lookup. Whenever the user
  23.145 +     * changes the return value from the <code>getLookup</code> method and wants
  23.146 +     * to notify listeners on the lookup about that it should trigger the event
  23.147 +     * firing, for example by calling <code>lookup.lookup (Object.class)</code>
  23.148 +     * directly on the lookup returned by this method
  23.149 +     * that forces a check of the return value of {@link org.openide.util.Lookup.Provider#getLookup}</code>.
  23.150 +     *
  23.151 +     * @param provider the provider that returns a lookup to delegate to
  23.152 +     * @return lookup delegating to the lookup returned by the provider
  23.153 +     * @since 3.9
  23.154 +     */
  23.155 +    public static Lookup proxy(Lookup.Provider provider) {
  23.156 +        return new SimpleProxyLookup(provider);
  23.157 +    }
  23.158 +
  23.159 +    /** Returns a lookup that implements the JDK1.3 JAR services mechanism and delegates
  23.160 +     * to META-INF/services/name.of.class files.
  23.161 +     * <p>Some extensions to the JAR services specification are implemented:
  23.162 +     * <ol>
  23.163 +     * <li>An entry may be followed by a line of the form <code>#position=<i>integer</i></code>
  23.164 +     *     to specify ordering. (Smaller numbers first, entries with unspecified position last.)
  23.165 +     * <li>A line of the form <code>#-<i>classname</i></code> suppresses an entry registered
  23.166 +     *     in another file, so can be used to supersede one implementation with another.
  23.167 +     * </ol>
  23.168 +     * <p>Note: It is not dynamic - so if you need to change the classloader or JARs,
  23.169 +     * wrap it in a {@link ProxyLookup} and change the delegate when necessary.
  23.170 +     * Existing instances will be kept if the implementation classes are unchanged,
  23.171 +     * so there is "stability" in doing this provided some parent loaders are the same
  23.172 +     * as the previous ones.
  23.173 +     * @since 3.35
  23.174 +     * @see ServiceProvider
  23.175 +     */
  23.176 +    public static Lookup metaInfServices(ClassLoader classLoader) {
  23.177 +        return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N
  23.178 +    }
  23.179 +
  23.180 +    /** Returns a lookup that behaves exactly like {@link #metaInfServices(ClassLoader)}
  23.181 +     * except that it does not read data from <code>META-INF/services/</code>, but instead
  23.182 +     * from the specified prefix.
  23.183 +     * @param classLoader class loader to use for loading
  23.184 +     * @param prefix prefix to prepend to the class name when searching
  23.185 +     * @since 7.9
  23.186 +     */
  23.187 +    public static Lookup metaInfServices(ClassLoader classLoader, String prefix) {
  23.188 +        return new MetaInfServicesLookup(classLoader, prefix);
  23.189 +    }
  23.190 +    
  23.191 +    /** Creates a <q>named</q> lookup.
  23.192 +     * It is a lookup identified by a given path.
  23.193 +     * Two lookups with the same path should have the same content.
  23.194 +     * <p>It is expected that each <q>named</q> lookup
  23.195 +     * will contain a superset of what would be created by:
  23.196 +     * <code>{@linkplain #metaInfServices(ClassLoader,String) metaInfServices}(theRightLoader, "META-INF/namedservices/" + path + "/")</code>
  23.197 +     *
  23.198 +     * <p class="nonnormative">Various environments can add their own
  23.199 +     * extensions to its content. As such
  23.200 +     * {@link Lookups#forPath(java.lang.String)} can combine lookups
  23.201 +     * from several sources. In current NetBeans Runtime Container, two lookups are used:
  23.202 +     * </p>
  23.203 +     * <ul class="nonnormative">
  23.204 +     * <li><code>Lookups.metaInfServices("META-INF/namedservices/" + path)</code></li>
  23.205 +     * <li><code>org.openide.loaders.FolderLookup(path)</code></li>
  23.206 +     * </ul>
  23.207 +     * <p class="nonnormative">
  23.208 +     * Please note that these lookups differ in the way they inspect sub-folders.
  23.209 +     * The first lookup just returns instances from the given path, ignoring
  23.210 +     * sub-folders, the second one retrieves instances from the whole sub-tree.
  23.211 +     * </p>
  23.212 +     * <p>
  23.213 +     * Read more about the <a href="@org-openide-util@/org/openide/util/doc-files/api.html#folderlookup">usage of this method</a>.
  23.214 +     * 
  23.215 +     * @param path the path identifying the lookup, e.g. <code>Projects/Actions</code>
  23.216 +     * @return lookup associated with this path
  23.217 +     * @since 7.9
  23.218 +     */
  23.219 +    public static Lookup forPath(String path) {
  23.220 +        return NamedServicesProvider.find(path);
  23.221 +    }
  23.222 +    
  23.223 +    /** Creates a lookup that wraps another one and filters out instances
  23.224 +     * of specified classes. If you have a lookup and
  23.225 +     * you want to remove all instances of ActionMap you can use:
  23.226 +     * <pre>
  23.227 +     * l = Lookups.exclude(lookup, ActionMap.class);
  23.228 +     * </pre>
  23.229 +     * Then anybody who asks for <code>l.lookup(ActionMap.class)</code> or
  23.230 +     * subclass will get <code>null</code>. Even if the original lookup contains the
  23.231 +     * value.
  23.232 +     * To create empty lookup (well, just an example, otherwise use {@link Lookup#EMPTY}) one could use:
  23.233 +     * <pre>
  23.234 +     * Lookup.exclude(anyLookup, Object.class);
  23.235 +     * </pre>
  23.236 +     * as any instance in any lookup is of type Object and thus would be excluded.
  23.237 +     * <p>
  23.238 +     * The complete behavior can be described as <code>classes</code> being
  23.239 +     * a barrier. For an object not to be excluded, there has to be an inheritance
  23.240 +     * path between the queried class and the actual class of the instance,
  23.241 +     * that is not blocked by any of the excluded classes:
  23.242 +     * <pre>
  23.243 +     * interface A {}
  23.244 +     * interface B {}
  23.245 +     * class C implements A, B {}
  23.246 +     * Object c = new C();
  23.247 +     * Lookup l1 = Lookups.singleton(c);
  23.248 +     * Lookup l2 = Lookups.exclude(l1, A.class);
  23.249 +     * assertNull("A is directly excluded", l2.lookup(A.class));
  23.250 +     * assertEquals("Returns C as A.class is not between B and C", c, l2.lookup(B.class));
  23.251 +     * </pre>
  23.252 +     * For more info check the
  23.253 +     * <a href="http://hg.netbeans.org/main-golden/annotate/4883eaeda744/openide.util/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java">
  23.254 +     * excluding lookup tests</a> and the discussion in issue
  23.255 +     * <a href="http://openide.netbeans.org/issues/show_bug.cgi?id=53058">53058</a>.
  23.256 +     *
  23.257 +     * @param lookup the original lookup that should be filtered
  23.258 +     * @param classes array of classes those instances should be excluded
  23.259 +     * @since 5.4
  23.260 +     */
  23.261 +    public static Lookup exclude(Lookup lookup, Class... classes) {
  23.262 +        return new ExcludingLookup(lookup, classes);
  23.263 +    }
  23.264 +
  23.265 +    /** Creates <code>Lookup.Item</code> representing the instance passed in.
  23.266 +     *
  23.267 +     * @param instance the object for which Lookup.Item should be creted
  23.268 +     * @param id unique identification of the object, for details see {@link org.openide.util.Lookup.Item#getId},
  23.269 +     * can be <code>null</code>
  23.270 +     * @return lookup item representing instance
  23.271 +     * @since 4.8
  23.272 +     */
  23.273 +    public static <T> Lookup.Item<T> lookupItem(T instance, String id) {
  23.274 +        return new LookupItem<T>(instance, id);
  23.275 +    }
  23.276 +
  23.277 +    private static class LookupItem<T> extends Lookup.Item<T> {
  23.278 +        private String id;
  23.279 +        private T instance;
  23.280 +
  23.281 +        public LookupItem(T instance) {
  23.282 +            this(instance, null);
  23.283 +        }
  23.284 +
  23.285 +        public LookupItem(T instance, String id) {
  23.286 +            this.id = id;
  23.287 +            this.instance = instance;
  23.288 +        }
  23.289 +
  23.290 +        public String getDisplayName() {
  23.291 +            return getId();
  23.292 +        }
  23.293 +
  23.294 +        public String getId() {
  23.295 +            return (id == null) ? instance.toString() : id;
  23.296 +        }
  23.297 +
  23.298 +        public T getInstance() {
  23.299 +            return instance;
  23.300 +        }
  23.301 +
  23.302 +        @SuppressWarnings("unchecked")
  23.303 +        public Class<? extends T> getType() {
  23.304 +            return (Class<? extends T>)instance.getClass();
  23.305 +        }
  23.306 +
  23.307 +        public @Override boolean equals(Object object) {
  23.308 +            if (object instanceof LookupItem) {
  23.309 +                return instance == ((LookupItem) object).getInstance();
  23.310 +            }
  23.311 +
  23.312 +            return false;
  23.313 +        }
  23.314 +
  23.315 +        public @Override int hashCode() {
  23.316 +            return instance.hashCode();
  23.317 +        }
  23.318 +    }
  23.319 +     // End of LookupItem class
  23.320 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/MetaInfServicesLookup.java	Mon Dec 14 20:58:39 2009 +0100
    24.3 @@ -0,0 +1,563 @@
    24.4 +/*
    24.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    24.6 + *
    24.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    24.8 + *
    24.9 + * The contents of this file are subject to the terms of either the GNU
   24.10 + * General Public License Version 2 only ("GPL") or the Common
   24.11 + * Development and Distribution License("CDDL") (collectively, the
   24.12 + * "License"). You may not use this file except in compliance with the
   24.13 + * License. You can obtain a copy of the License at
   24.14 + * http://www.netbeans.org/cddl-gplv2.html
   24.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   24.16 + * specific language governing permissions and limitations under the
   24.17 + * License.  When distributing the software, include this License Header
   24.18 + * Notice in each file and include the License file at
   24.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   24.20 + * particular file as subject to the "Classpath" exception as provided
   24.21 + * by Sun in the GPL Version 2 section of the License file that
   24.22 + * accompanied this code. If applicable, add the following below the
   24.23 + * License Header, with the fields enclosed by brackets [] replaced by
   24.24 + * your own identifying information:
   24.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   24.26 + *
   24.27 + * Contributor(s):
   24.28 + *
   24.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   24.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   24.31 + * Microsystems, Inc. All Rights Reserved.
   24.32 + *
   24.33 + * If you wish your version of this file to be governed by only the CDDL
   24.34 + * or only the GPL Version 2, indicate your decision by adding
   24.35 + * "[Contributor] elects to include this software in this distribution
   24.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   24.37 + * single choice of license, a recipient has the option to distribute
   24.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   24.39 + * to extend the choice of license to its licensees as provided above.
   24.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   24.41 + * Version 2 license, then the option applies only if the new code is
   24.42 + * made subject to such option by the copyright holder.
   24.43 + */
   24.44 +
   24.45 +package org.openide.util.lookup;
   24.46 +
   24.47 +import java.io.BufferedReader;
   24.48 +import java.io.IOException;
   24.49 +import java.io.InputStream;
   24.50 +import java.io.InputStreamReader;
   24.51 +import java.lang.ref.Reference;
   24.52 +import java.lang.ref.WeakReference;
   24.53 +import java.lang.reflect.Method;
   24.54 +import java.net.URL;
   24.55 +import java.util.ArrayList;
   24.56 +import java.util.Collection;
   24.57 +import java.util.Enumeration;
   24.58 +import java.util.HashSet;
   24.59 +import java.util.LinkedHashSet;
   24.60 +import java.util.List;
   24.61 +import java.util.Map;
   24.62 +import java.util.WeakHashMap;
   24.63 +import java.util.concurrent.Executor;
   24.64 +import java.util.concurrent.Executors;
   24.65 +import java.util.logging.Level;
   24.66 +import java.util.logging.Logger;
   24.67 +import org.openide.util.Lookup;
   24.68 +
   24.69 +/**
   24.70 + * @author Jaroslav Tulach, Jesse Glick
   24.71 + * @see Lookups#metaInfServices(ClassLoader,String)
   24.72 + * @see "#14722"
   24.73 + */
   24.74 +final class MetaInfServicesLookup extends AbstractLookup {
   24.75 +
   24.76 +    private static final Logger LOGGER = Logger.getLogger(MetaInfServicesLookup.class.getName());
   24.77 +    static final Executor RP = Executors.newSingleThreadExecutor(); 
   24.78 +    /*TBD: Inject RequestProcessor somehow
   24.79 +     new RequestProcessor(MetaInfServicesLookup.class.getName(), 1);
   24.80 +     */
   24.81 +    private static int knownInstancesCount;
   24.82 +    private static final List<Reference<Object>> knownInstances;
   24.83 +    static {
   24.84 +        knownInstances = new ArrayList<Reference<Object>>();
   24.85 +        for (int i = 0; i < 512; i++) {
   24.86 +            knownInstances.add(null);
   24.87 +        }
   24.88 +    }
   24.89 +
   24.90 +    /** A set of all requested classes.
   24.91 +     * Note that classes that we actually succeeded on can never be removed
   24.92 +     * from here because we hold a strong reference to the loader.
   24.93 +     * However we also hold classes which are definitely not loadable by
   24.94 +     * our loader.
   24.95 +     */
   24.96 +    private final Map<Class,Object> classes = new WeakHashMap<Class,Object>();
   24.97 +
   24.98 +    /** class loader to use */
   24.99 +    private final ClassLoader loader;
  24.100 +    /** prefix to prepend */
  24.101 +    private final String prefix;
  24.102 +
  24.103 +    /** Create a lookup reading from a specified classloader.
  24.104 +     */
  24.105 +    public MetaInfServicesLookup(ClassLoader loader, String prefix) {
  24.106 +        this.loader = loader;
  24.107 +        this.prefix = prefix;
  24.108 +
  24.109 +        LOGGER.log(Level.FINE, "Created: {0}", this);
  24.110 +    }
  24.111 +
  24.112 +    @Override
  24.113 +    public String toString() {
  24.114 +        return "MetaInfServicesLookup[" + loader + "]"; // NOI18N
  24.115 +    }
  24.116 +
  24.117 +    /* Tries to load appropriate resources from manifest files.
  24.118 +     */
  24.119 +    @Override
  24.120 +    protected final void beforeLookup(Lookup.Template t) {
  24.121 +        Class c = t.getType();
  24.122 +
  24.123 +        Collection<AbstractLookup.Pair<?>> toAdd = null;
  24.124 +        synchronized (this) {
  24.125 +            if (classes.get(c) == null) { // NOI18N
  24.126 +                toAdd = new ArrayList<Pair<?>>();
  24.127 +            } else {
  24.128 +                // ok, nothing needs to be done
  24.129 +                return;
  24.130 +            }
  24.131 +        }
  24.132 +        if (toAdd != null) {
  24.133 +            search(c, toAdd);
  24.134 +        }
  24.135 +        synchronized (this) {
  24.136 +            if (classes.put(c, "") == null) { // NOI18N
  24.137 +                // Added new class, search for it.
  24.138 +                LinkedHashSet<AbstractLookup.Pair<?>> arr = getPairsAsLHS();
  24.139 +                arr.addAll(toAdd);
  24.140 +                setPairs(arr, RP);
  24.141 +            }
  24.142 +        }
  24.143 +    }
  24.144 +
  24.145 +    /** Finds all pairs and adds them to the collection.
  24.146 +     *
  24.147 +     * @param clazz class to find
  24.148 +     * @param result collection to add Pair to
  24.149 +     */
  24.150 +    private void search(Class<?> clazz, Collection<AbstractLookup.Pair<?>> result) {
  24.151 +        if (LOGGER.isLoggable(Level.FINER)) {
  24.152 +            LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this);
  24.153 +        }
  24.154 +
  24.155 +        String res = prefix + clazz.getName(); // NOI18N
  24.156 +        Enumeration<URL> en;
  24.157 +
  24.158 +        try {
  24.159 +            en = loader.getResources(res);
  24.160 +        } catch (IOException ioe) {
  24.161 +            // do not use ErrorManager because we are in the startup code
  24.162 +            // and ErrorManager might not be ready
  24.163 +            ioe.printStackTrace();
  24.164 +
  24.165 +            return;
  24.166 +        }
  24.167 +
  24.168 +        // Do not create multiple instances in case more than one JAR
  24.169 +        // has the same entry in it (and they load to the same class).
  24.170 +        // Probably would not happen, assuming JARs only list classes
  24.171 +        // they own, but just in case...
  24.172 +        List<Item> foundClasses = new ArrayList<Item>();
  24.173 +        Collection<Class> removeClasses = new ArrayList<Class>();
  24.174 +
  24.175 +        boolean foundOne = false;
  24.176 +
  24.177 +        while (en.hasMoreElements()) {
  24.178 +            if (!foundOne) {
  24.179 +                foundOne = true;
  24.180 +
  24.181 +                // Double-check that in fact we can load the *interface* class.
  24.182 +                // For example, say class I is defined in two JARs, J1 and J2.
  24.183 +                // There is also an implementation M1 defined in J1, and another
  24.184 +                // implementation M2 defined in J2.
  24.185 +                // Classloaders C1 and C2 are made from J1 and J2.
  24.186 +                // A MetaInfServicesLookup is made from C1. Then the user asks to
  24.187 +                // lookup I as loaded from C2. J1 has the services line and lists
  24.188 +                // M1, and we can in fact make it. However it is not of the desired
  24.189 +                // type to be looked up. Don't do this check, which could be expensive,
  24.190 +                // unless we expect to be getting some results, however.
  24.191 +                Class realMcCoy = null;
  24.192 +
  24.193 +                try {
  24.194 +                    realMcCoy = loader.loadClass(clazz.getName());
  24.195 +                } catch (ClassNotFoundException cnfe) {
  24.196 +                    // our loader does not know about it, OK
  24.197 +                }
  24.198 +
  24.199 +                if (realMcCoy != clazz) {
  24.200 +                    // Either the interface class is not available at all in our loader,
  24.201 +                    // or it is not the same version as we expected. Don't provide results.
  24.202 +                    if (LOGGER.isLoggable(Level.WARNING)) {
  24.203 +                        if (realMcCoy != null) {
  24.204 +                            LOGGER.log(Level.WARNING,
  24.205 +                                clazz.getName() + " is not the real McCoy! Actually found it in " +
  24.206 +                                realMcCoy.getClassLoader()
  24.207 +                            ); // NOI18N
  24.208 +                        } else {
  24.209 +                            LOGGER.log(Level.WARNING, clazz.getName() + " could not be found in " + loader); // NOI18N
  24.210 +                        }
  24.211 +                    }
  24.212 +
  24.213 +                    return;
  24.214 +                }
  24.215 +            }
  24.216 +
  24.217 +            URL url = en.nextElement();
  24.218 +            Item currentItem = null;
  24.219 +
  24.220 +            try {
  24.221 +                InputStream is = url.openStream();
  24.222 +
  24.223 +                try {
  24.224 +                    BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N
  24.225 +
  24.226 +                    while (true) {
  24.227 +                        String line = reader.readLine();
  24.228 +
  24.229 +                        if (line == null) {
  24.230 +                            break;
  24.231 +                        }
  24.232 +
  24.233 +                        line = line.trim();
  24.234 +
  24.235 +                        // is it position attribute?
  24.236 +                        if (line.startsWith("#position=")) {
  24.237 +                            if (currentItem == null) {
  24.238 +                                LOGGER.log(Level.WARNING, "Found line '{0}' in {1} but there is no item to associate it with", new Object[] {line, url});
  24.239 +                                continue;
  24.240 +                            }
  24.241 +
  24.242 +                            try {
  24.243 +                                currentItem.position = Integer.parseInt(line.substring(10));
  24.244 +                            } catch (NumberFormatException e) {
  24.245 +                                // do not use ErrorManager because we are in the startup code
  24.246 +                                // and ErrorManager might not be ready
  24.247 +                                e.printStackTrace();
  24.248 +                            }
  24.249 +                        }
  24.250 +
  24.251 +                        if (currentItem != null) {
  24.252 +                            insertItem(currentItem, foundClasses);
  24.253 +                            currentItem = null;
  24.254 +                        }
  24.255 +
  24.256 +                        // Ignore blank lines and comments.
  24.257 +                        if (line.length() == 0) {
  24.258 +                            continue;
  24.259 +                        }
  24.260 +
  24.261 +                        boolean remove = false;
  24.262 +
  24.263 +                        if (line.charAt(0) == '#') {
  24.264 +                            if ((line.length() == 1) || (line.charAt(1) != '-')) {
  24.265 +                                continue;
  24.266 +                            }
  24.267 +
  24.268 +                            // line starting with #- is a sign to remove that class from lookup
  24.269 +                            remove = true;
  24.270 +                            line = line.substring(2);
  24.271 +                        }
  24.272 +
  24.273 +                        Class inst = null;
  24.274 +
  24.275 +                        try {
  24.276 +                            // Most lines are fully-qualified class names.
  24.277 +                            inst = Class.forName(line, false, loader);
  24.278 +                        } catch (ClassNotFoundException cnfe) {
  24.279 +                            if (remove) {
  24.280 +                                // if we are removing somthing and the something
  24.281 +                                // cannot be found it is ok to do nothing
  24.282 +                                continue;
  24.283 +                            } else {
  24.284 +                                // but if we are not removing just rethrow
  24.285 +                                throw cnfe;
  24.286 +                            }
  24.287 +                        }
  24.288 +
  24.289 +                        if (!clazz.isAssignableFrom(inst)) {
  24.290 +                            throw new ClassNotFoundException(clazzToString(inst) + " not a subclass of " + clazzToString(clazz)); // NOI18N
  24.291 +                        }
  24.292 +
  24.293 +                        if (remove) {
  24.294 +                            removeClasses.add(inst);
  24.295 +                        } else {
  24.296 +                            // create new item here, but do not put it into
  24.297 +                            // foundClasses array yet because following line
  24.298 +                            // might specify its position
  24.299 +                            currentItem = new Item();
  24.300 +                            currentItem.clazz = inst;
  24.301 +                        }
  24.302 +                    }
  24.303 +
  24.304 +                    if (currentItem != null) {
  24.305 +                        insertItem(currentItem, foundClasses);
  24.306 +                        currentItem = null;
  24.307 +                    }
  24.308 +                } finally {
  24.309 +                    is.close();
  24.310 +                }
  24.311 +            } catch (ClassNotFoundException ex) {
  24.312 +                LOGGER.log(Level.WARNING, null, ex);
  24.313 +            } catch (IOException ex) {
  24.314 +                LOGGER.log(Level.WARNING, null, ex);
  24.315 +            }
  24.316 +        }
  24.317 +
  24.318 +        LOGGER.log(Level.FINER, "Found impls of {0}: {1} and removed: {2} from: {3}", new Object[] {clazz.getName(), foundClasses, removeClasses, this});
  24.319 +
  24.320 +        foundClasses.removeAll(removeClasses);
  24.321 +
  24.322 +        for (Item item : foundClasses) {
  24.323 +            if (removeClasses.contains(item.clazz)) {
  24.324 +                continue;
  24.325 +            }
  24.326 +
  24.327 +            result.add(new P(item.clazz));
  24.328 +        }
  24.329 +    }
  24.330 +    private static String clazzToString(Class clazz) {
  24.331 +        return clazz.getName() + "@" + clazz.getClassLoader() + ":" + clazz.getProtectionDomain().getCodeSource().getLocation(); // NOI18N
  24.332 +    }
  24.333 +
  24.334 +    /**
  24.335 +     * Insert item to the list according to item.position value.
  24.336 +     */
  24.337 +    private void insertItem(Item item, List<Item> list) {
  24.338 +        // no position? -> add it to the end
  24.339 +        if (item.position == -1) {
  24.340 +            list.add(item);
  24.341 +
  24.342 +            return;
  24.343 +        }
  24.344 +
  24.345 +        int index = -1;
  24.346 +        for (Item i : list) {
  24.347 +            index++;
  24.348 +
  24.349 +            if (i.position == -1) {
  24.350 +                list.add(index, item);
  24.351 +
  24.352 +                return;
  24.353 +            } else {
  24.354 +                if (i.position > item.position) {
  24.355 +                    list.add(index, item);
  24.356 +
  24.357 +                    return;
  24.358 +                }
  24.359 +            }
  24.360 +        }
  24.361 +
  24.362 +        list.add(item);
  24.363 +    }
  24.364 +
  24.365 +    private static class Item {
  24.366 +        private Class clazz;
  24.367 +        private int position = -1;
  24.368 +        @Override
  24.369 +        public String toString() {
  24.370 +            return "MetaInfServicesLookup.Item[" + clazz.getName() + "]"; // NOI18N
  24.371 +        }
  24.372 +    }
  24.373 +
  24.374 +    /** Pair that holds name of a class and maybe the instance.
  24.375 +     */
  24.376 +    private static final class P extends AbstractLookup.Pair<Object> {
  24.377 +        /** May be one of three things:
  24.378 +         * 1. The implementation class which was named in the services file.
  24.379 +         * 2. An instance of it.
  24.380 +         * 3. Null, if creation of the instance resulted in an error.
  24.381 +         */
  24.382 +        private Object object;
  24.383 +
  24.384 +        public P(Class<?> clazz) {
  24.385 +            this.object = clazz;
  24.386 +        }
  24.387 +
  24.388 +        /** Finds the class.
  24.389 +         */
  24.390 +        private Class<? extends Object> clazz() {
  24.391 +            Object o = object;
  24.392 +
  24.393 +            if (o instanceof Class) {
  24.394 +                return (Class<? extends Object>) o;
  24.395 +            } else if (o != null) {
  24.396 +                return o.getClass();
  24.397 +            } else {
  24.398 +                // Broken.
  24.399 +                return Object.class;
  24.400 +            }
  24.401 +        }
  24.402 +
  24.403 +        @Override
  24.404 +        public boolean equals(Object o) {
  24.405 +            if (o instanceof P) {
  24.406 +                return ((P) o).clazz().equals(clazz());
  24.407 +            }
  24.408 +
  24.409 +            return false;
  24.410 +        }
  24.411 +
  24.412 +        @Override
  24.413 +        public int hashCode() {
  24.414 +            return clazz().hashCode();
  24.415 +        }
  24.416 +
  24.417 +        protected boolean instanceOf(Class<?> c) {
  24.418 +            return c.isAssignableFrom(clazz());
  24.419 +        }
  24.420 +
  24.421 +        public Class<?> getType() {
  24.422 +            return clazz();
  24.423 +        }
  24.424 +
  24.425 +        public Object getInstance() {
  24.426 +            Object o = object; // keeping local copy to avoid another
  24.427 +
  24.428 +            // thread to modify it under my hands
  24.429 +            if (o instanceof Class) {
  24.430 +                synchronized (o) { // o is Class and we will not create 
  24.431 +                                   // 2 instances of the same class
  24.432 +
  24.433 +                    try {
  24.434 +                        Class<?> c = ((Class) o);
  24.435 +                        o = null;
  24.436 +
  24.437 +                        synchronized (knownInstances) { // guards only the static cache
  24.438 +                            int size = knownInstances.size();
  24.439 +                            int index = c.hashCode() % size;
  24.440 +                            for (int i = 0; i < size; i++) {
  24.441 +                                Reference<Object> ref = knownInstances.get(index);
  24.442 +                                Object obj = ref == null ? null : ref.get();
  24.443 +                                if (obj == null) {
  24.444 +                                    break;
  24.445 +                                }
  24.446 +                                if (c == obj.getClass()) {
  24.447 +                                    o = obj;
  24.448 +                                    break;
  24.449 +                                }
  24.450 +                                if (++index == size) {
  24.451 +                                    index = 0;
  24.452 +                                }
  24.453 +                            }
  24.454 +                        }
  24.455 +
  24.456 +                        if (o == null) {
  24.457 +                            o = createInstance(c);
  24.458 +
  24.459 +                            synchronized (knownInstances) { // guards only the static cache
  24.460 +                                hashPut(o);
  24.461 +
  24.462 +                                int size = knownInstances.size();
  24.463 +                                if (knownInstancesCount > size * 2 / 3) {
  24.464 +                                    LOGGER.log(Level.CONFIG, "Cache of size {0} is 2/3 full. Rehashing.", size);
  24.465 +                                    HashSet<Reference<Object>> all = new HashSet<Reference<Object>>();
  24.466 +                                    all.addAll(knownInstances);
  24.467 +                                    for (int i = 0; i < size; i++) {
  24.468 +                                        knownInstances.set(i, null);
  24.469 +                                    }
  24.470 +                                    for (int i = 0; i < size; i++) {
  24.471 +                                        knownInstances.add(null);
  24.472 +                                    }
  24.473 +                                    knownInstancesCount = 0;
  24.474 +                                    for (Reference<Object> r : all) {
  24.475 +                                        if (r == null) {
  24.476 +                                            continue;
  24.477 +                                        }
  24.478 +                                        Object instance = r.get();
  24.479 +                                        if (instance == null) {
  24.480 +                                            continue;
  24.481 +                                        }
  24.482 +                                        hashPut(instance);
  24.483 +                                    }
  24.484 +                                }
  24.485 +
  24.486 +                            }
  24.487 +                        }
  24.488 +
  24.489 +                        // Do not assign to instance var unless there is a complete synch
  24.490 +                        // block between the newInstance and this line. Otherwise we could
  24.491 +                        // be assigning a half-constructed instance that another thread
  24.492 +                        // could see and return immediately.
  24.493 +                        object = o;
  24.494 +                    } catch (Exception ex) {
  24.495 +                        LOGGER.log(Level.WARNING, "Cannot create " + object, ex);
  24.496 +                        object = null;
  24.497 +                    } catch (ExceptionInInitializerError x) { // #174055
  24.498 +                        LOGGER.log(Level.WARNING, "Cannot create " + object, x);
  24.499 +                        object = null;
  24.500 +                    }
  24.501 +                }
  24.502 +            }
  24.503 +
  24.504 +            return object;
  24.505 +        }
  24.506 +
  24.507 +        public String getDisplayName() {
  24.508 +            return clazz().getName();
  24.509 +        }
  24.510 +
  24.511 +        public String getId() {
  24.512 +            return clazz().getName();
  24.513 +        }
  24.514 +
  24.515 +        protected boolean creatorOf(Object obj) {
  24.516 +            return obj == object;
  24.517 +        }
  24.518 +
  24.519 +        private static void hashPut(Object o) {
  24.520 +            Class<?> c = o.getClass();
  24.521 +            int size = knownInstances.size();
  24.522 +            int index = c.hashCode() % size;
  24.523 +            for (int i = 0; i < size; i++) {
  24.524 +                Reference<Object> ref = knownInstances.get(index);
  24.525 +                Object obj = ref == null ? null : ref.get();
  24.526 +                if (obj == null) {
  24.527 +                    knownInstances.set(index, new WeakReference<Object>(o));
  24.528 +                    knownInstancesCount++;
  24.529 +                    break;
  24.530 +                }
  24.531 +                if (++index == size) {
  24.532 +                    index = 0;
  24.533 +                }
  24.534 +            }
  24.535 +        }
  24.536 +
  24.537 +        private static boolean findSharedClassObjectSkip;
  24.538 +        private static Method findSharedClassObject;
  24.539 +        /** Basically does c.newInstance(), however the method is complicated
  24.540 +         * with a special behaviour for old and almost obsoleted NetBeans
  24.541 +         * class: SharedClassObject.
  24.542 +         */
  24.543 +        private static Object createInstance(Class<?> c) throws InstantiationException, IllegalAccessException {
  24.544 +            if (!findSharedClassObjectSkip) {
  24.545 +                try {
  24.546 +                    if (findSharedClassObject == null) {
  24.547 +                        Class<?> sco;
  24.548 +                        try {
  24.549 +                            sco = Class.forName("org.openide.util.SharedClassObject"); // NOI18N
  24.550 +                        } catch (ClassNotFoundException ex) {
  24.551 +                            findSharedClassObjectSkip = true;
  24.552 +                            return c.newInstance();
  24.553 +                        }
  24.554 +                        findSharedClassObject = sco.getMethod("findObject", Class.class, boolean.class);
  24.555 +                    }
  24.556 +                    if (findSharedClassObject.getReturnType().isAssignableFrom(c)) {
  24.557 +                        return findSharedClassObject.invoke(null, c, true);
  24.558 +                    }
  24.559 +                } catch (Exception problem) {
  24.560 +                    throw (InstantiationException)new InstantiationException(problem.getMessage()).initCause(problem);
  24.561 +                }
  24.562 +            }
  24.563 +            return c.newInstance();
  24.564 +        }
  24.565 +    }
  24.566 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ProxyLookup.java	Mon Dec 14 20:58:39 2009 +0100
    25.3 @@ -0,0 +1,980 @@
    25.4 +/*
    25.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    25.6 + *
    25.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    25.8 + *
    25.9 + * The contents of this file are subject to the terms of either the GNU
   25.10 + * General Public License Version 2 only ("GPL") or the Common
   25.11 + * Development and Distribution License("CDDL") (collectively, the
   25.12 + * "License"). You may not use this file except in compliance with the
   25.13 + * License. You can obtain a copy of the License at
   25.14 + * http://www.netbeans.org/cddl-gplv2.html
   25.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   25.16 + * specific language governing permissions and limitations under the
   25.17 + * License.  When distributing the software, include this License Header
   25.18 + * Notice in each file and include the License file at
   25.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   25.20 + * particular file as subject to the "Classpath" exception as provided
   25.21 + * by Sun in the GPL Version 2 section of the License file that
   25.22 + * accompanied this code. If applicable, add the following below the
   25.23 + * License Header, with the fields enclosed by brackets [] replaced by
   25.24 + * your own identifying information:
   25.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   25.26 + *
   25.27 + * Contributor(s):
   25.28 + *
   25.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   25.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   25.31 + * Microsystems, Inc. All Rights Reserved.
   25.32 + *
   25.33 + * If you wish your version of this file to be governed by only the CDDL
   25.34 + * or only the GPL Version 2, indicate your decision by adding
   25.35 + * "[Contributor] elects to include this software in this distribution
   25.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   25.37 + * single choice of license, a recipient has the option to distribute
   25.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   25.39 + * to extend the choice of license to its licensees as provided above.
   25.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   25.41 + * Version 2 license, then the option applies only if the new code is
   25.42 + * made subject to such option by the copyright holder.
   25.43 + */
   25.44 +
   25.45 +package org.openide.util.lookup;
   25.46 +
   25.47 +import java.lang.ref.Reference;
   25.48 +import java.lang.ref.WeakReference;
   25.49 +import java.util.ArrayList;
   25.50 +import java.util.Arrays;
   25.51 +import java.util.Collection;
   25.52 +import java.util.Collections;
   25.53 +import java.util.HashMap;
   25.54 +import java.util.HashSet;
   25.55 +import java.util.IdentityHashMap;
   25.56 +import java.util.Iterator;
   25.57 +import java.util.List;
   25.58 +import java.util.Map;
   25.59 +import java.util.Map.Entry;
   25.60 +import java.util.Set;
   25.61 +import java.util.concurrent.Executor;
   25.62 +import javax.swing.event.EventListenerList;
   25.63 +import org.openide.util.Lookup;
   25.64 +import org.openide.util.LookupEvent;
   25.65 +import org.openide.util.LookupListener;
   25.66 +
   25.67 +/** Implementation of lookup that can delegate to others.
   25.68 + *
   25.69 + * @author  Jaroslav Tulach
   25.70 + * @since 1.9
   25.71 + */
   25.72 +public class ProxyLookup extends Lookup {
   25.73 +    /** data representing the state of the lookup */
   25.74 +    private ImmutableInternalData data;
   25.75 +
   25.76 +    /** Create a proxy to some other lookups.
   25.77 +     * @param lookups the initial delegates
   25.78 +     */
   25.79 +    public ProxyLookup(Lookup... lookups) {
   25.80 +        data = ImmutableInternalData.EMPTY.setLookupsNoFire(lookups, true);
   25.81 +    }
   25.82 +
   25.83 +    /**
   25.84 +     * Create a lookup initially proxying to no others.
   25.85 +     * Permits serializable subclasses.
   25.86 +     * @since 3.27
   25.87 +     */
   25.88 +    protected ProxyLookup() {
   25.89 +        data = ImmutableInternalData.EMPTY;
   25.90 +    }
   25.91 +
   25.92 +    @Override
   25.93 +    public synchronized String toString() {
   25.94 +        return "ProxyLookup(class=" + getClass() + ")->" + Arrays.asList(getData().getLookups(false)); // NOI18N
   25.95 +    }
   25.96 +
   25.97 +    /** Getter for the delegates.
   25.98 +    * @return the array of lookups we delegate to
   25.99 +    * @since 1.19
  25.100 +    */
  25.101 +    protected final Lookup[] getLookups() {
  25.102 +        synchronized (ProxyLookup.this) {
  25.103 +            return getData().getLookups(true);
  25.104 +        }
  25.105 +    }
  25.106 +
  25.107 +    private Set<Lookup> identityHashSet(Collection<Lookup> current) {
  25.108 +        Map<Lookup,Void> map = new IdentityHashMap<Lookup, Void>();
  25.109 +        for (Lookup lookup : current) {
  25.110 +            map.put(lookup, null);
  25.111 +        }
  25.112 +        return map.keySet();
  25.113 +    }
  25.114 +    
  25.115 +    /**
  25.116 +     * Changes the delegates.
  25.117 +     *
  25.118 +     * @param lookups the new lookups to delegate to
  25.119 +     * @since 1.19 protected
  25.120 +     */
  25.121 +    protected final void setLookups(Lookup... lookups) {
  25.122 +        setLookups(null, lookups);
  25.123 +    }
  25.124 +    
  25.125 +    /**
  25.126 +     * Changes the delegates immediatelly, notifies the listeners in provided
  25.127 +     * executor, potentially later.
  25.128 +     *
  25.129 +     * @param lookups the new lookups to delegate to
  25.130 +     * @param notifyIn executor to deliver the notification to listeners or null
  25.131 +     * @since 7.16
  25.132 +     */
  25.133 +    protected final void setLookups(Executor notifyIn, Lookup... lookups) {
  25.134 +        Collection<Reference<R>> arr;
  25.135 +        Set<Lookup> newL;
  25.136 +        Set<Lookup> current;
  25.137 +        Lookup[] old;
  25.138 +        
  25.139 +        Map<Result,LookupListener> toRemove = new IdentityHashMap<Lookup.Result, LookupListener>();
  25.140 +        Map<Result,LookupListener> toAdd = new IdentityHashMap<Lookup.Result, LookupListener>();
  25.141 +        
  25.142 +        ImmutableInternalData orig;
  25.143 +        synchronized (ProxyLookup.this) {
  25.144 +            orig = getData();
  25.145 +            ImmutableInternalData newData = getData().setLookupsNoFire(lookups, false);
  25.146 +            if (newData == getData()) {
  25.147 +                return;
  25.148 +            }
  25.149 +            arr = setData(newData, lookups, toAdd, toRemove);
  25.150 +        }
  25.151 +        
  25.152 +        // better to do this later than in synchronized block
  25.153 +        for (Map.Entry<Result, LookupListener> e : toRemove.entrySet()) {
  25.154 +            e.getKey().removeLookupListener(e.getValue());
  25.155 +        }
  25.156 +        for (Map.Entry<Result, LookupListener> e : toAdd.entrySet()) {
  25.157 +            e.getKey().addLookupListener(e.getValue());
  25.158 +        }
  25.159 +
  25.160 +
  25.161 +        // this cannot be done from the synchronized block
  25.162 +        final ArrayList<Object> evAndListeners = new ArrayList<Object>();
  25.163 +        for (Reference<R> ref : arr) {
  25.164 +            R<?> r = ref.get();
  25.165 +            if (r != null) {
  25.166 +                r.collectFires(evAndListeners);
  25.167 +            }
  25.168 +        }
  25.169 +        
  25.170 +        class Notify implements Runnable {
  25.171 +            public void run() {
  25.172 +                Iterator it = evAndListeners.iterator();
  25.173 +                while (it.hasNext()) {
  25.174 +                    LookupEvent ev = (LookupEvent)it.next();
  25.175 +                    LookupListener l = (LookupListener)it.next();
  25.176 +                    l.resultChanged(ev);
  25.177 +                }
  25.178 +            }
  25.179 +        }
  25.180 +        Notify n = new Notify();
  25.181 +        if (notifyIn == null) {
  25.182 +            n.run();
  25.183 +        } else {
  25.184 +            notifyIn.execute(n);
  25.185 +        }
  25.186 +    }
  25.187 +
  25.188 +    /** Notifies subclasses that a query is about to be processed.
  25.189 +     * Subclasses can update its state before the actual processing
  25.190 +     * begins. It is allowed to call <code>setLookups</code> method
  25.191 +     * to change/update the set of objects the proxy delegates to.
  25.192 +     *
  25.193 +     * @param template the template of the query
  25.194 +     * @since 1.31
  25.195 +     */
  25.196 +    protected void beforeLookup(Template<?> template) {
  25.197 +    }
  25.198 +
  25.199 +    public final <T> T lookup(Class<T> clazz) {
  25.200 +        beforeLookup(new Template<T>(clazz));
  25.201 +
  25.202 +        Lookup[] tmpLkps;
  25.203 +        synchronized (ProxyLookup.this) {
  25.204 +            tmpLkps = getData().getLookups(false);
  25.205 +        }
  25.206 +
  25.207 +        for (int i = 0; i < tmpLkps.length; i++) {
  25.208 +            T o = tmpLkps[i].lookup(clazz);
  25.209 +
  25.210 +            if (o != null) {
  25.211 +                return o;
  25.212 +            }
  25.213 +        }
  25.214 +
  25.215 +        return null;
  25.216 +    }
  25.217 +
  25.218 +    @Override
  25.219 +    public final <T> Item<T> lookupItem(Template<T> template) {
  25.220 +        beforeLookup(template);
  25.221 +
  25.222 +        Lookup[] tmpLkps; 
  25.223 +        synchronized (ProxyLookup.this) {
  25.224 +            tmpLkps = getData().getLookups(false);
  25.225 +        }
  25.226 +
  25.227 +        for (int i = 0; i < tmpLkps.length; i++) {
  25.228 +            Item<T> o = tmpLkps[i].lookupItem(template);
  25.229 +
  25.230 +            if (o != null) {
  25.231 +                return o;
  25.232 +            }
  25.233 +        }
  25.234 +
  25.235 +        return null;
  25.236 +    }
  25.237 +
  25.238 +    @SuppressWarnings("unchecked")
  25.239 +    private static <T> R<T> convertResult(R r) {
  25.240 +        return (R<T>)r;
  25.241 +    }
  25.242 +
  25.243 +    public final <T> Result<T> lookup(Lookup.Template<T> template) {
  25.244 +        synchronized (ProxyLookup.this) {
  25.245 +            ImmutableInternalData[] res = { null };
  25.246 +            R<T> newR = getData().findResult(this, res, template);
  25.247 +            setData(res[0], getData().getLookups(false), null, null);
  25.248 +            return newR;
  25.249 +        }
  25.250 +    }
  25.251 +
  25.252 +    /** Unregisters a template from the has map.
  25.253 +     */
  25.254 +    private final void unregisterTemplate(Template<?> template) {
  25.255 +        synchronized (ProxyLookup.this) {
  25.256 +            ImmutableInternalData id = getData();
  25.257 +            if (id == null) {
  25.258 +                return;
  25.259 +            }
  25.260 +            setData(id.removeTemplate(this, template), getData().getLookups(false), null, null);
  25.261 +        }
  25.262 +    }
  25.263 +
  25.264 +    private ImmutableInternalData getData() {
  25.265 +        assert Thread.holdsLock(this);
  25.266 +        return data;
  25.267 +    }
  25.268 +
  25.269 +    private Collection<Reference<R>> setData(
  25.270 +        ImmutableInternalData newData, Lookup[] current, 
  25.271 +        Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
  25.272 +    ) {
  25.273 +        assert Thread.holdsLock(ProxyLookup.this);
  25.274 +        assert newData != null;
  25.275 +        
  25.276 +        ImmutableInternalData previous = this.getData();
  25.277 +        
  25.278 +        if (previous == newData) {
  25.279 +            return Collections.emptyList();
  25.280 +        }
  25.281 +
  25.282 +        if (newData.isEmpty()) {
  25.283 +            this.setData(newData);
  25.284 +            // no affected results => exit
  25.285 +            return Collections.emptyList();
  25.286 +        }
  25.287 +
  25.288 +        Collection<Reference<R>> arr = newData.references();
  25.289 +
  25.290 +        Set<Lookup> removed = identityHashSet(previous.getLookupsList());
  25.291 +        Set<Lookup> currentSet = identityHashSet(Arrays.asList(current));
  25.292 +        Set<Lookup> newL = identityHashSet(currentSet);
  25.293 +        removed.removeAll(currentSet); // current contains just those lookups that have disappeared
  25.294 +        newL.removeAll(previous.getLookupsList()); // really new lookups
  25.295 +
  25.296 +        for (Reference<R> ref : arr) {
  25.297 +            R<?> r = ref.get();
  25.298 +            if (r != null) {
  25.299 +                r.lookupChange(newData, current, previous, newL, removed, toAdd, toRemove);
  25.300 +                if (this.getData() != previous) {
  25.301 +                    // the data were changed by an re-entrant call
  25.302 +                    // skip any other change processing, as it is not needed
  25.303 +                    // anymore
  25.304 +                }
  25.305 +            }
  25.306 +        }
  25.307 +                for (Reference<R> ref : arr) {
  25.308 +            R<?> r = ref.get();
  25.309 +            if (r != null) {
  25.310 +                r.data = newData;
  25.311 +            }
  25.312 +        }
  25.313 +        this.setData(newData);
  25.314 +        return arr;
  25.315 +    }
  25.316 +
  25.317 +    private void setData(ImmutableInternalData data) {
  25.318 +        this.data = data;
  25.319 +    }
  25.320 +
  25.321 +    /** Result of a lookup request. Allows access to single object
  25.322 +     * that was found (not too useful) and also to all objects found
  25.323 +     * (more useful).
  25.324 +     */
  25.325 +    private static final class R<T> extends WaitableResult<T> {
  25.326 +        /** weak listener & result */
  25.327 +        private final WeakResult<T> weakL;
  25.328 +        
  25.329 +        /** list of listeners added */
  25.330 +        private javax.swing.event.EventListenerList listeners;
  25.331 +
  25.332 +        /** collection of Objects */
  25.333 +        private Collection[] cache;
  25.334 +
  25.335 +        
  25.336 +        /** associated lookup */
  25.337 +        private ImmutableInternalData data;
  25.338 +
  25.339 +        /** Constructor.
  25.340 +         */
  25.341 +        public R(ProxyLookup proxy, Lookup.Template<T> t) {
  25.342 +            this.weakL = new WeakResult<T>(proxy, this, t);
  25.343 +        }
  25.344 +        
  25.345 +        private ProxyLookup proxy() {
  25.346 +            return weakL.result.proxy;
  25.347 +        }
  25.348 +
  25.349 +        @SuppressWarnings("unchecked")
  25.350 +        private Result<T>[] newResults(int len) {
  25.351 +            return new Result[len];
  25.352 +        }
  25.353 +        
  25.354 +        @Override
  25.355 +        protected void finalize() {
  25.356 +            weakL.result.run();
  25.357 +        }
  25.358 +
  25.359 +        /** initializes the results
  25.360 +         */
  25.361 +        private Result<T>[] initResults() {
  25.362 +            BIG_LOOP: for (;;) {
  25.363 +                Lookup[] myLkps;
  25.364 +                ImmutableInternalData current;
  25.365 +                synchronized (proxy()) {
  25.366 +                    if (weakL.getResults() != null) {
  25.367 +                        return weakL.getResults();
  25.368 +                    }
  25.369 +                    myLkps = data.getLookups(false);
  25.370 +                    current = data;
  25.371 +                }
  25.372 +
  25.373 +                Result<T>[] arr = newResults(myLkps.length);
  25.374 +
  25.375 +                for (int i = 0; i < arr.length; i++) {
  25.376 +                    arr[i] = myLkps[i].lookup(weakL.result.template);
  25.377 +                }
  25.378 +
  25.379 +                synchronized (proxy()) {
  25.380 +                    if (current != data) {
  25.381 +                        continue;
  25.382 +                    }
  25.383 +                    
  25.384 +                    Lookup[] currentLkps = data.getLookups(false);
  25.385 +                    if (currentLkps.length != myLkps.length) {
  25.386 +                        continue BIG_LOOP;
  25.387 +                    }
  25.388 +                    for (int i = 0; i < currentLkps.length; i++) {
  25.389 +                        if (currentLkps[i] != myLkps[i]) {
  25.390 +                            continue BIG_LOOP;
  25.391 +                        }
  25.392 +                    }
  25.393 +                    
  25.394 +                    // some other thread might compute the result mean while. 
  25.395 +                    // if not finish the computation yourself
  25.396 +                    if (weakL.getResults() != null) {
  25.397 +                        return weakL.getResults();
  25.398 +                    }
  25.399 +
  25.400 +                    weakL.setResults(arr);
  25.401 +                }
  25.402 +                for (int i = 0; i < arr.length; i++) {
  25.403 +                    arr[i].addLookupListener(weakL);
  25.404 +                }
  25.405 +                return arr;
  25.406 +            }
  25.407 +        }
  25.408 +
  25.409 +        /** Called when there is a change in the list of proxied lookups.
  25.410 +         * @param added set of added lookups
  25.411 +         * @param remove set of removed lookups
  25.412 +         * @param current array of current lookups
  25.413 +         */
  25.414 +        final void lookupChange(
  25.415 +            ImmutableInternalData newData, Lookup[] current, ImmutableInternalData oldData,
  25.416 +            Set<Lookup> added, Set<Lookup> removed,
  25.417 +            Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
  25.418 +        ) {
  25.419 +            if (weakL.getResults() == null) {
  25.420 +                // not computed yet, do not need to do anything
  25.421 +                return;
  25.422 +            }
  25.423 +
  25.424 +            Lookup[] old = oldData.getLookups(false);
  25.425 +
  25.426 +            // map (Lookup, Lookup.Result)
  25.427 +            Map<Lookup,Result<T>> map = new IdentityHashMap<Lookup,Result<T>>(old.length * 2);
  25.428 +
  25.429 +            for (int i = 0; i < old.length; i++) {
  25.430 +                if (removed.contains(old[i])) {
  25.431 +                    // removed lookup
  25.432 +                    if (toRemove != null) {
  25.433 +                        toRemove.put(weakL.getResults()[i], weakL);
  25.434 +                    }
  25.435 +                } else {
  25.436 +                    // remember the association
  25.437 +                    map.put(old[i], weakL.getResults()[i]);
  25.438 +                }
  25.439 +            }
  25.440 +
  25.441 +            Lookup.Result<T>[] arr = newResults(current.length);
  25.442 +
  25.443 +            for (int i = 0; i < current.length; i++) {
  25.444 +                if (added.contains(current[i])) {
  25.445 +                    // new lookup
  25.446 +                    arr[i] = current[i].lookup(weakL.result.template);
  25.447 +                    if (toAdd != null) {
  25.448 +                        toAdd.put(arr[i], weakL);
  25.449 +                    }
  25.450 +                } else {
  25.451 +                    // old lookup
  25.452 +                    arr[i] = map.get(current[i]);
  25.453 +
  25.454 +                    if (arr[i] == null) {
  25.455 +                        // assert
  25.456 +                        throw new IllegalStateException();
  25.457 +                    }
  25.458 +                }
  25.459 +            }
  25.460 +
  25.461 +            // remember the new results
  25.462 +            weakL.setResults(arr);
  25.463 +        }
  25.464 +
  25.465 +        /** Just delegates.
  25.466 +         */
  25.467 +        public void addLookupListener(LookupListener l) {
  25.468 +            synchronized (proxy()) {
  25.469 +                if (listeners == null) {
  25.470 +                    listeners = new EventListenerList();
  25.471 +                }
  25.472 +            }
  25.473 +
  25.474 +            listeners.add(LookupListener.class, l);
  25.475 +            initResults();
  25.476 +        }
  25.477 +
  25.478 +        /** Just delegates.
  25.479 +         */
  25.480 +        public void removeLookupListener(LookupListener l) {
  25.481 +            if (listeners != null) {
  25.482 +                listeners.remove(LookupListener.class, l);
  25.483 +            }
  25.484 +        }
  25.485 +
  25.486 +        /** Access to all instances in the result.
  25.487 +         * @return collection of all instances
  25.488 +         */
  25.489 +        @SuppressWarnings("unchecked")
  25.490 +        public java.util.Collection<T> allInstances() {
  25.491 +            return computeResult(0);
  25.492 +        }
  25.493 +
  25.494 +        /** Classes of all results. Set of the most concreate classes
  25.495 +         * that are registered in the system.
  25.496 +         * @return set of Class objects
  25.497 +         */
  25.498 +        @SuppressWarnings("unchecked")
  25.499 +        @Override
  25.500 +        public java.util.Set<Class<? extends T>> allClasses() {
  25.501 +            return (java.util.Set<Class<? extends T>>) computeResult(1);
  25.502 +        }
  25.503 +
  25.504 +        /** All registered items. The collection of all pairs of
  25.505 +         * ii and their classes.
  25.506 +         * @return collection of Lookup.Item
  25.507 +         */
  25.508 +        @SuppressWarnings("unchecked")
  25.509 +        @Override
  25.510 +        public java.util.Collection<? extends Item<T>> allItems() {
  25.511 +            return computeResult(2);
  25.512 +        }
  25.513 +
  25.514 +        /** Computes results from proxied lookups.
  25.515 +         * @param indexToCache 0 = allInstances, 1 = allClasses, 2 = allItems
  25.516 +         * @return the collection or set of the objects
  25.517 +         */
  25.518 +        private java.util.Collection computeResult(int indexToCache) {
  25.519 +            // results to use
  25.520 +            Lookup.Result<T>[] arr = myBeforeLookup();
  25.521 +
  25.522 +            // if the call to beforeLookup resulted in deletion of caches
  25.523 +            synchronized (proxy()) {
  25.524 +                Collection[] cc = getCache();
  25.525 +                if (cc != null && cc != NO_CACHE) {
  25.526 +                    Collection result = cc[indexToCache];
  25.527 +                    if (result != null) {
  25.528 +                        return result;
  25.529 +                    }
  25.530 +                }
  25.531 +            }
  25.532 +
  25.533 +            // initialize the collection to hold result
  25.534 +            Collection<Object> compute;
  25.535 +            Collection<Object> ret;
  25.536 +
  25.537 +            if (indexToCache == 1) {
  25.538 +                HashSet<Object> s = new HashSet<Object>();
  25.539 +                compute = s;
  25.540 +                ret = Collections.unmodifiableSet(s);
  25.541 +            } else {
  25.542 +                List<Object> l = new ArrayList<Object>(arr.length * 2);
  25.543 +                compute = l;
  25.544 +                ret = Collections.unmodifiableList(l);
  25.545 +            }
  25.546 +
  25.547 +            // fill the collection
  25.548 +            for (int i = 0; i < arr.length; i++) {
  25.549 +                switch (indexToCache) {
  25.550 +                case 0:
  25.551 +                    compute.addAll(arr[i].allInstances());
  25.552 +                    break;
  25.553 +                case 1:
  25.554 +                    compute.addAll(arr[i].allClasses());
  25.555 +                    break;
  25.556 +                case 2:
  25.557 +                    compute.addAll(arr[i].allItems());
  25.558 +                    break;
  25.559 +                default:
  25.560 +                    assert false : "Wrong index: " + indexToCache;
  25.561 +                }
  25.562 +            }
  25.563 +            
  25.564 +            
  25.565 +
  25.566 +            synchronized (proxy()) {
  25.567 +                Collection[] cc = getCache();
  25.568 +                if (cc == null || cc == NO_CACHE) {
  25.569 +                    // initialize the cache to indicate this result is in use
  25.570 +                    setCache(cc = new Collection[3]);
  25.571 +                }
  25.572 +                
  25.573 +                if (arr == weakL.getResults()) {
  25.574 +                    // updates the results, if the results have not been
  25.575 +                    // changed during the computation of allInstances
  25.576 +                    cc[indexToCache] = ret;
  25.577 +                }
  25.578 +            }
  25.579 +
  25.580 +            return ret;
  25.581 +        }
  25.582 +
  25.583 +        /** When the result changes, fire the event.
  25.584 +         */
  25.585 +        public void resultChanged(LookupEvent ev) {
  25.586 +            collectFires(null);
  25.587 +        }
  25.588 +        
  25.589 +        protected void collectFires(Collection<Object> evAndListeners) {
  25.590 +            boolean modified = true;
  25.591 +
  25.592 +            try {
  25.593 +                // clear cached instances
  25.594 +                Collection oldItems;
  25.595 +                Collection oldInstances;
  25.596 +                synchronized (proxy()) {
  25.597 +                    final Collection[] cc = getCache();
  25.598 +                    if (cc == NO_CACHE) {
  25.599 +                        return;
  25.600 +                    }
  25.601 +
  25.602 +                    oldInstances = cc == null ? null : cc[0];
  25.603 +                    oldItems = cc == null ? null : cc[2];
  25.604 +
  25.605 +
  25.606 +                    if (listeners == null || listeners.getListenerCount() == 0) {
  25.607 +                        // clear the cache
  25.608 +                        setCache(new Collection[3]);
  25.609 +                        return;
  25.610 +                    }
  25.611 +
  25.612 +                    // ignore events if they arrive as a result of call to allItems
  25.613 +                    // or allInstances, bellow...
  25.614 +                    setCache(NO_CACHE);
  25.615 +                }
  25.616 +
  25.617 +                if (oldItems != null) {
  25.618 +                    Collection newItems = allItems();
  25.619 +                    if (oldItems.equals(newItems)) {
  25.620 +                        modified = false;
  25.621 +                    }
  25.622 +                } else {
  25.623 +                    if (oldInstances != null) {
  25.624 +                        Collection newInstances = allInstances();
  25.625 +                        if (oldInstances.equals(newInstances)) {
  25.626 +                            modified = false;
  25.627 +                        }
  25.628 +                    } else {
  25.629 +                        synchronized (proxy()) {
  25.630 +                            if (getCache() == NO_CACHE) {
  25.631 +                                // we have to initialize the cache
  25.632 +                                // to show that the result has been initialized
  25.633 +                                setCache(new Collection[3]);
  25.634 +                            }
  25.635 +                        }
  25.636 +                    }
  25.637 +                }
  25.638 +            } finally {
  25.639 +                synchronized (proxy()) {
  25.640 +                    if (getCache() == NO_CACHE) {
  25.641 +                        setCache(null);
  25.642 +                    }
  25.643 +                }
  25.644 +            }
  25.645 +            
  25.646 +            if (modified) {
  25.647 +                LookupEvent ev = new LookupEvent(this);
  25.648 +                AbstractLookup.notifyListeners(listeners.getListenerList(), ev, evAndListeners);
  25.649 +            }
  25.650 +        }
  25.651 +
  25.652 +        /** Implementation of my before lookup.
  25.653 +         * @return results to work on.
  25.654 +         */
  25.655 +        private Lookup.Result<T>[] myBeforeLookup() {
  25.656 +            Template<T> template = weakL.result.template;
  25.657 +            
  25.658 +            proxy().beforeLookup(template);
  25.659 +
  25.660 +            Lookup.Result<T>[] arr = initResults();
  25.661 +
  25.662 +            // invoke update on the results
  25.663 +            for (int i = 0; i < arr.length; i++) {
  25.664 +                if (arr[i] instanceof WaitableResult) {
  25.665 +                    WaitableResult w = (WaitableResult) arr[i];
  25.666 +                    w.beforeLookup(template);
  25.667 +                }
  25.668 +            }
  25.669 +
  25.670 +            return arr;
  25.671 +        }
  25.672 +
  25.673 +        /** Used by proxy results to synchronize before lookup.
  25.674 +         */
  25.675 +        protected void beforeLookup(Lookup.Template t) {
  25.676 +            if (t.getType() == weakL.result.template.getType()) {
  25.677 +                myBeforeLookup();
  25.678 +            }
  25.679 +        }
  25.680 +
  25.681 +        private Collection[] getCache() {
  25.682 +            return cache;
  25.683 +        }
  25.684 +
  25.685 +        private void setCache(Collection[] cache) {
  25.686 +            assert Thread.holdsLock(proxy());
  25.687 +            this.cache = cache;
  25.688 +        }
  25.689 +        private static final Collection[] NO_CACHE = new Collection[0];
  25.690 +    }
  25.691 +    private static final class WeakRef<T> extends WeakReference<R> implements Runnable {
  25.692 +        final WeakResult<T> result;
  25.693 +        final ProxyLookup proxy;
  25.694 +        final Template<T> template;
  25.695 +        
  25.696 +        public WeakRef(R r, WeakResult<T> result, ProxyLookup proxy, Template<T> template) {
  25.697 +            super(r);
  25.698 +            this.result = result;
  25.699 +            this.template = template;
  25.700 +            this.proxy = proxy;
  25.701 +        }
  25.702 +
  25.703 +        public void run() {
  25.704 +            result.removeListeners();
  25.705 +            proxy.unregisterTemplate(template);
  25.706 +        }
  25.707 +    }
  25.708 +    
  25.709 +    
  25.710 +    private static final class WeakResult<T> extends WaitableResult<T> implements LookupListener, Runnable {
  25.711 +        /** all results */
  25.712 +        private Lookup.Result<T>[] results;
  25.713 +        private final WeakRef<T> result;
  25.714 +        
  25.715 +        public WeakResult(ProxyLookup proxy, R r, Template<T> t) {
  25.716 +            this.result = new WeakRef<T>(r, this, proxy, t);
  25.717 +        }
  25.718 +        
  25.719 +        final void removeListeners() {
  25.720 +            Lookup.Result<T>[] arr = this.getResults();
  25.721 +            if (arr == null) {
  25.722 +                return;
  25.723 +            }
  25.724 +
  25.725 +            for(int i = 0; i < arr.length; i++) {
  25.726 +                arr[i].removeLookupListener(this);
  25.727 +            }
  25.728 +        }
  25.729 +
  25.730 +        protected void beforeLookup(Lookup.Template t) {
  25.731 +            R r = result.get();
  25.732 +            if (r != null) {
  25.733 +                r.beforeLookup(t);
  25.734 +            } else {
  25.735 +                removeListeners();
  25.736 +            }
  25.737 +        }
  25.738 +
  25.739 +        protected void collectFires(Collection<Object> evAndListeners) {
  25.740 +            R<?> r = result.get();
  25.741 +            if (r != null) {
  25.742 +                r.collectFires(evAndListeners);
  25.743 +            } else {
  25.744 +                removeListeners();
  25.745 +            }
  25.746 +        }
  25.747 +
  25.748 +        public void addLookupListener(LookupListener l) {
  25.749 +            assert false;
  25.750 +        }
  25.751 +
  25.752 +        public void removeLookupListener(LookupListener l) {
  25.753 +            assert false;
  25.754 +        }
  25.755 +
  25.756 +        public Collection<T> allInstances() {
  25.757 +            assert false;
  25.758 +            return null;
  25.759 +        }
  25.760 +
  25.761 +        public void resultChanged(LookupEvent ev) {
  25.762 +            R r = result.get();
  25.763 +            if (r != null) {
  25.764 +                r.resultChanged(ev);
  25.765 +            } else {
  25.766 +                removeListeners();
  25.767 +            }
  25.768 +        }
  25.769 +
  25.770 +        @Override
  25.771 +        public Collection<? extends Item<T>> allItems() {
  25.772 +            assert false;
  25.773 +            return null;
  25.774 +        }
  25.775 +
  25.776 +        @Override
  25.777 +        public Set<Class<? extends T>> allClasses() {
  25.778 +            assert false;
  25.779 +            return null;
  25.780 +        }
  25.781 +
  25.782 +        public void run() {
  25.783 +            removeListeners();
  25.784 +        }
  25.785 +
  25.786 +        private Lookup.Result<T>[] getResults() {
  25.787 +            return results;
  25.788 +        }
  25.789 +
  25.790 +        private void setResults(Lookup.Result<T>[] results) {
  25.791 +            this.results = results;
  25.792 +        }
  25.793 +    } // end of WeakResult
  25.794 +    
  25.795 +    static abstract class ImmutableInternalData extends Object {
  25.796 +        static final ImmutableInternalData EMPTY = new EmptyInternalData();
  25.797 +        static final Lookup[] EMPTY_ARR = new Lookup[0];
  25.798 +
  25.799 +        
  25.800 +        protected ImmutableInternalData() {
  25.801 +        }
  25.802 +        
  25.803 +        public static ImmutableInternalData create(Object lkp, Map<Template, Reference<R>> results) {
  25.804 +            if (results.size() == 0 && lkp == EMPTY_ARR) {
  25.805 +                return EMPTY;
  25.806 +            }
  25.807 +            if (results.size() == 1) {
  25.808 +                Entry<Template,Reference<R>> e = results.entrySet().iterator().next();
  25.809 +                return new SingleInternalData(lkp, e.getKey(), e.getValue());
  25.810 +            }
  25.811 +            
  25.812 +            return new RealInternalData(lkp, results);
  25.813 +        }
  25.814 +
  25.815 +        protected abstract boolean isEmpty();
  25.816 +        protected abstract Map<Template, Reference<R>> getResults();
  25.817 +        protected abstract Object getRawLookups();
  25.818 +
  25.819 +        final Collection<Reference<R>> references() {
  25.820 +            return getResults().values();
  25.821 +        }
  25.822 +        
  25.823 +        final <T> ImmutableInternalData removeTemplate(ProxyLookup proxy, Template<T> template) {
  25.824 +            if (getResults().containsKey(template)) {
  25.825 +                HashMap<Template,Reference<R>> c = new HashMap<Template, Reference<ProxyLookup.R>>(getResults());
  25.826 +                Reference<R> ref = c.remove(template);
  25.827 +                if (ref != null && ref.get() != null) {
  25.828 +                    // seems like there is a reference to a result for this template
  25.829 +                    // thta is still alive
  25.830 +                    return this;
  25.831 +                }
  25.832 +                return create(getRawLookups(), c);
  25.833 +            } else {
  25.834 +                return this;
  25.835 +            }
  25.836 +        }
  25.837 +        
  25.838 +        <T> R<T> findResult(ProxyLookup proxy, ImmutableInternalData[] newData, Template<T> template) {
  25.839 +            assert Thread.holdsLock(proxy);
  25.840 +            
  25.841 +            Map<Template,Reference<R>> map = getResults();
  25.842 +            
  25.843 +            Reference<R> ref = map.get(template);
  25.844 +            R r = (ref == null) ? null : ref.get();
  25.845 +
  25.846 +            if (r != null) {
  25.847 +                newData[0] = this;
  25.848 +                return convertResult(r);
  25.849 +            }
  25.850 +            
  25.851 +            HashMap<Template, Reference<R>> res = new HashMap<Template, Reference<R>>(map);
  25.852 +            R<T> newR = new R<T>(proxy, template);
  25.853 +            res.put(template, new java.lang.ref.SoftReference<R>(newR));
  25.854 +            newR.data = newData[0] = create(getRawLookups(), res);
  25.855 +            return newR;
  25.856 +        }
  25.857 +        final ImmutableInternalData setLookupsNoFire(Lookup[] lookups, boolean skipCheck) {
  25.858 +            Object l;
  25.859 +            
  25.860 +            if (!skipCheck) {
  25.861 +                Lookup[] previous = getLookups(false);
  25.862 +                if (previous == lookups) {
  25.863 +                    return this;
  25.864 +                }
  25.865 +            
  25.866 +                if (previous.length == lookups.length) {
  25.867 +                    int same = 0;
  25.868 +                    for (int i = 0; i < previous.length; i++) {
  25.869 +                        if (lookups[i] != previous[i]) {
  25.870 +                            break;
  25.871 +                        }
  25.872 +                        same++;
  25.873 +                    }
  25.874 +                    if (same == previous.length) {
  25.875 +                        return this;
  25.876 +                    }
  25.877 +                }
  25.878 +            }
  25.879 +            
  25.880 +            if (lookups.length == 1) {
  25.881 +                l = lookups[0];
  25.882 +                assert l != null : "Cannot assign null delegate";
  25.883 +            } else {
  25.884 +                if (lookups.length == 0) {
  25.885 +                    l = EMPTY_ARR;
  25.886 +                } else {
  25.887 +                    l = lookups.clone();
  25.888 +                }
  25.889 +            }
  25.890 +            
  25.891 +            if (isEmpty() && l == EMPTY_ARR) {
  25.892 +                return this;
  25.893 +            }
  25.894 +            
  25.895 +            return create(l, getResults());
  25.896 +        }
  25.897 +        final Lookup[] getLookups(boolean clone) {
  25.898 +            Object l = this.getRawLookups();
  25.899 +            if (l instanceof Lookup) {
  25.900 +                return new Lookup[] { (Lookup)l };
  25.901 +            } else {
  25.902 +                Lookup[] arr = (Lookup[])l;
  25.903 +                if (clone) {
  25.904 +                    arr = arr.clone();
  25.905 +                }
  25.906 +                return arr;
  25.907 +            }
  25.908 +        }
  25.909 +        final List<Lookup> getLookupsList() {
  25.910 +            return Arrays.asList(getLookups(false));            
  25.911 +        }
  25.912 +
  25.913 +    } // end of ImmutableInternalData
  25.914 +    
  25.915 +    private static final class SingleInternalData extends ImmutableInternalData {
  25.916 +        /** lookups to delegate to (either Lookup or array of Lookups) */
  25.917 +        private final Object lookups;
  25.918 +        private final Template template;
  25.919 +        private final Reference<ProxyLookup.R> result;
  25.920 +                
  25.921 +        public SingleInternalData(Object lookups, Template<?> template, Reference<ProxyLookup.R> result) {
  25.922 +            this.lookups = lookups;
  25.923 +            this.template = template;
  25.924 +            this.result = result;
  25.925 +        }
  25.926 +
  25.927 +        protected final boolean isEmpty() {
  25.928 +            return false;
  25.929 +        }
  25.930 +
  25.931 +        protected Map<Template, Reference<R>> getResults() {
  25.932 +            return Collections.singletonMap(template, result);
  25.933 +        }
  25.934 +        
  25.935 +        protected Object getRawLookups() {
  25.936 +            return lookups;
  25.937 +        }
  25.938 +    }
  25.939 +    private static final class RealInternalData extends ImmutableInternalData {
  25.940 +        /** lookups to delegate to (either Lookup or array of Lookups) */
  25.941 +        private final Object lookups;
  25.942 +
  25.943 +        /** map of templates to currently active results */
  25.944 +        private final Map<Template,Reference<R>> results;
  25.945 +
  25.946 +        public RealInternalData(Object lookups, Map<Template, Reference<ProxyLookup.R>> results) {
  25.947 +            this.results = results;
  25.948 +            this.lookups = lookups;
  25.949 +        }
  25.950 +
  25.951 +        protected final boolean isEmpty() {
  25.952 +            return false;
  25.953 +        }
  25.954 +
  25.955 +        protected Map<Template, Reference<R>> getResults() {
  25.956 +            boolean strict = false;
  25.957 +            assert strict = true;
  25.958 +            return strict ? Collections.unmodifiableMap(results) : results;
  25.959 +        }
  25.960 +        
  25.961 +        protected Object getRawLookups() {
  25.962 +            return lookups;
  25.963 +        }
  25.964 +    }
  25.965 +    
  25.966 +    private static final class EmptyInternalData extends ImmutableInternalData {
  25.967 +        EmptyInternalData() {
  25.968 +        }
  25.969 +
  25.970 +        protected final boolean isEmpty() {
  25.971 +            return true;
  25.972 +        }
  25.973 +
  25.974 +        protected Map<Template, Reference<R>> getResults() {
  25.975 +            return Collections.emptyMap();
  25.976 +        }
  25.977 +
  25.978 +        @Override
  25.979 +        protected Object getRawLookups() {
  25.980 +            return EMPTY_ARR;
  25.981 +        }
  25.982 +    } // end of EmptyInternalData
  25.983 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ServiceProvider.java	Mon Dec 14 20:58:39 2009 +0100
    26.3 @@ -0,0 +1,102 @@
    26.4 +/*
    26.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    26.6 + *
    26.7 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    26.8 + *
    26.9 + * The contents of this file are subject to the terms of either the GNU
   26.10 + * General Public License Version 2 only ("GPL") or the Common
   26.11 + * Development and Distribution License("CDDL") (collectively, the
   26.12 + * "License"). You may not use this file except in compliance with the
   26.13 + * License. You can obtain a copy of the License at
   26.14 + * http://www.netbeans.org/cddl-gplv2.html
   26.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   26.16 + * specific language governing permissions and limitations under the
   26.17 + * License.  When distributing the software, include this License Header
   26.18 + * Notice in each file and include the License file at
   26.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   26.20 + * particular file as subject to the "Classpath" exception as provided
   26.21 + * by Sun in the GPL Version 2 section of the License file that
   26.22 + * accompanied this code. If applicable, add the following below the
   26.23 + * License Header, with the fields enclosed by brackets [] replaced by
   26.24 + * your own identifying information:
   26.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   26.26 + *
   26.27 + * If you wish your version of this file to be governed by only the CDDL
   26.28 + * or only the GPL Version 2, indicate your decision by adding
   26.29 + * "[Contributor] elects to include this software in this distribution
   26.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   26.31 + * single choice of license, a recipient has the option to distribute
   26.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   26.33 + * to extend the choice of license to its licensees as provided above.
   26.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   26.35 + * Version 2 license, then the option applies only if the new code is
   26.36 + * made subject to such option by the copyright holder.
   26.37 + *
   26.38 + * Contributor(s):
   26.39 + *
   26.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   26.41 + */
   26.42 +
   26.43 +package org.openide.util.lookup;
   26.44 +
   26.45 +import java.lang.annotation.ElementType;
   26.46 +import java.lang.annotation.Retention;
   26.47 +import java.lang.annotation.RetentionPolicy;
   26.48 +import java.lang.annotation.Target;
   26.49 +import org.openide.util.Lookup;
   26.50 +
   26.51 +/**
   26.52 + * Declarative registration of a singleton service provider.
   26.53 + * By marking an implementation class with this annotation,
   26.54 + * you automatically register that implementation, normally in {@link Lookup#getDefault}.
   26.55 + * The class must be public and have a public no-argument constructor.
   26.56 + * <p>Example of usage:
   26.57 + * <pre>
   26.58 + * package my.module;
   26.59 + * import org.netbeans.spi.whatever.Thing;
   26.60 + * import org.openide.util.lookup.ServiceProvider;
   26.61 + * &#64;ServiceProvider(service=Thing.class)
   26.62 + * public class MyThing implements Thing {...}
   26.63 + * </pre>
   26.64 + * <p>would result in a resource file <code>META-INF/services/org.netbeans.spi.whatever.Thing</code>
   26.65 + * containing the single line of text: <code>my.module.MyThing</code>
   26.66 + * @see Lookups#metaInfServices(ClassLoader)
   26.67 + * @since org.openide.util 7.20
   26.68 + */
   26.69 +@Retention(RetentionPolicy.SOURCE)
   26.70 +@Target(ElementType.TYPE)
   26.71 +public @interface ServiceProvider {
   26.72 +
   26.73 +    /**
   26.74 +     * The interface (or abstract class) to register this implementation under.
   26.75 +     * It is an error if the implementation class is not in fact assignable to the interface.
   26.76 +     * <p>If you need to register one class under multiple interfaces, use {@link ServiceProviders}.
   26.77 +     * <p>Requests to look up the specified interface should result in this implementation.
   26.78 +     * Requests for any other types may or may not result in this implementation even if the
   26.79 +     * implementation is assignable to those types.
   26.80 +     */
   26.81 +    Class<?> service();
   26.82 +
   26.83 +    /**
   26.84 +     * An optional position in which to register this service relative to others.
   26.85 +     * Lower-numbered services are returned in the lookup result first.
   26.86 +     * Services with no specified position are returned last.
   26.87 +     */
   26.88 +    int position() default Integer.MAX_VALUE;
   26.89 +
   26.90 +    /**
   26.91 +     * An optional list of implementations (given as fully-qualified class names) which this implementation supersedes.
   26.92 +     * If specified, those implementations will not be loaded even if they were registered.
   26.93 +     * Useful on occasion to cancel a generic implementation and replace it with a more advanced one.
   26.94 +     */
   26.95 +    String[] supersedes() default {};
   26.96 +
   26.97 +    /**
   26.98 +     * An optional path to register this implementation in.
   26.99 +     * For example, <code>Projects/sometype/Nodes</code> could be used.
  26.100 +     * This style of registration would be recognized by {@link Lookups#forPath}
  26.101 +     * rather than {@link Lookup#getDefault}.
  26.102 +     */
  26.103 +    String path() default "";
  26.104 +
  26.105 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ServiceProviders.java	Mon Dec 14 20:58:39 2009 +0100
    27.3 @@ -0,0 +1,60 @@
    27.4 +/*
    27.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    27.6 + *
    27.7 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    27.8 + *
    27.9 + * The contents of this file are subject to the terms of either the GNU
   27.10 + * General Public License Version 2 only ("GPL") or the Common
   27.11 + * Development and Distribution License("CDDL") (collectively, the
   27.12 + * "License"). You may not use this file except in compliance with the
   27.13 + * License. You can obtain a copy of the License at
   27.14 + * http://www.netbeans.org/cddl-gplv2.html
   27.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   27.16 + * specific language governing permissions and limitations under the
   27.17 + * License.  When distributing the software, include this License Header
   27.18 + * Notice in each file and include the License file at
   27.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   27.20 + * particular file as subject to the "Classpath" exception as provided
   27.21 + * by Sun in the GPL Version 2 section of the License file that
   27.22 + * accompanied this code. If applicable, add the following below the
   27.23 + * License Header, with the fields enclosed by brackets [] replaced by
   27.24 + * your own identifying information:
   27.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   27.26 + *
   27.27 + * If you wish your version of this file to be governed by only the CDDL
   27.28 + * or only the GPL Version 2, indicate your decision by adding
   27.29 + * "[Contributor] elects to include this software in this distribution
   27.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   27.31 + * single choice of license, a recipient has the option to distribute
   27.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   27.33 + * to extend the choice of license to its licensees as provided above.
   27.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   27.35 + * Version 2 license, then the option applies only if the new code is
   27.36 + * made subject to such option by the copyright holder.
   27.37 + *
   27.38 + * Contributor(s):
   27.39 + *
   27.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   27.41 + */
   27.42 +
   27.43 +package org.openide.util.lookup;
   27.44 +
   27.45 +import java.lang.annotation.ElementType;
   27.46 +import java.lang.annotation.Retention;
   27.47 +import java.lang.annotation.RetentionPolicy;
   27.48 +import java.lang.annotation.Target;
   27.49 +
   27.50 +/**
   27.51 + * Similar to {@link ServiceProvider} but permits multiple registrations of one class.
   27.52 + * @since org.openide.util 7.20
   27.53 + */
   27.54 +@Retention(RetentionPolicy.SOURCE)
   27.55 +@Target(ElementType.TYPE)
   27.56 +public @interface ServiceProviders {
   27.57 +
   27.58 +    /**
   27.59 +     * List of service provider registrations.
   27.60 +     */
   27.61 +    ServiceProvider[] value();
   27.62 +
   27.63 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/SimpleLookup.java	Mon Dec 14 20:58:39 2009 +0100
    28.3 @@ -0,0 +1,250 @@
    28.4 +/*
    28.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    28.6 + *
    28.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    28.8 + *
    28.9 + * The contents of this file are subject to the terms of either the GNU
   28.10 + * General Public License Version 2 only ("GPL") or the Common
   28.11 + * Development and Distribution License("CDDL") (collectively, the
   28.12 + * "License"). You may not use this file except in compliance with the
   28.13 + * License. You can obtain a copy of the License at
   28.14 + * http://www.netbeans.org/cddl-gplv2.html
   28.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   28.16 + * specific language governing permissions and limitations under the
   28.17 + * License.  When distributing the software, include this License Header
   28.18 + * Notice in each file and include the License file at
   28.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   28.20 + * particular file as subject to the "Classpath" exception as provided
   28.21 + * by Sun in the GPL Version 2 section of the License file that
   28.22 + * accompanied this code. If applicable, add the following below the
   28.23 + * License Header, with the fields enclosed by brackets [] replaced by
   28.24 + * your own identifying information:
   28.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   28.26 + *
   28.27 + * Contributor(s):
   28.28 + *
   28.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   28.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   28.31 + * Microsystems, Inc. All Rights Reserved.
   28.32 + *
   28.33 + * If you wish your version of this file to be governed by only the CDDL
   28.34 + * or only the GPL Version 2, indicate your decision by adding
   28.35 + * "[Contributor] elects to include this software in this distribution
   28.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   28.37 + * single choice of license, a recipient has the option to distribute
   28.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   28.39 + * to extend the choice of license to its licensees as provided above.
   28.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   28.41 + * Version 2 license, then the option applies only if the new code is
   28.42 + * made subject to such option by the copyright holder.
   28.43 + */
   28.44 +package org.openide.util.lookup;
   28.45 +
   28.46 +import org.openide.util.Lookup;
   28.47 +import org.openide.util.LookupListener;
   28.48 +
   28.49 +import java.util.*;
   28.50 +
   28.51 +
   28.52 +/**
   28.53 + * Simple lookup implementation. It can be used to create temporary lookups
   28.54 + * that do not change over time. The result stores references to all objects
   28.55 + * passed in the constructor. Those objecst are the only ones returned as
   28.56 + * result.
   28.57 + * @author David Strupl
   28.58 + */
   28.59 +class SimpleLookup extends org.openide.util.Lookup {
   28.60 +    /** This variable is initialized in constructor and thus null
   28.61 +     * value is not allowed as its value. */
   28.62 +    private Collection<Item<?>> allItems;
   28.63 +
   28.64 +    /**
   28.65 +     * Creates new Result object with supplied instances parameter.
   28.66 +     * @param instances to be used to return from the lookup
   28.67 +     */
   28.68 +    SimpleLookup(Collection<Object> instances) {
   28.69 +        allItems = new ArrayList<Item<?>>(instances.size());
   28.70 +
   28.71 +        for (Iterator i = instances.iterator(); i.hasNext();) {
   28.72 +            allItems.add(new InstanceContent.SimpleItem<Object>(i.next()));
   28.73 +        }
   28.74 +    }
   28.75 +
   28.76 +    <T,R> SimpleLookup(Collection<T> keys, InstanceContent.Convertor<? super T,R> conv) {
   28.77 +        allItems = new ArrayList<Item<?>>(keys.size());
   28.78 +
   28.79 +        for (T item : keys) {
   28.80 +            allItems.add(new InstanceContent.ConvertingItem<T,R>(item, conv));
   28.81 +        }
   28.82 +    }
   28.83 +
   28.84 +    public String toString() {
   28.85 +        return "SimpleLookup" + lookup(new Template<Object>(Object.class)).allInstances();
   28.86 +    }
   28.87 +
   28.88 +    public <T> Result<T> lookup(Template<T> template) {
   28.89 +        if (template == null) {
   28.90 +            throw new NullPointerException();
   28.91 +        }
   28.92 +
   28.93 +        return new SimpleResult<T>(template);
   28.94 +    }
   28.95 +
   28.96 +    public <T> T lookup(Class<T> clazz) {
   28.97 +        for (Iterator i = allItems.iterator(); i.hasNext();) {
   28.98 +            Object o = i.next();
   28.99 +
  28.100 +            if (o instanceof AbstractLookup.Pair) {
  28.101 +                AbstractLookup.Pair<?> p = (AbstractLookup.Pair<?>)o;
  28.102 +                if (p.instanceOf(clazz)) {
  28.103 +                    Object ret = p.getInstance();
  28.104 +                    if (clazz.isInstance(ret)) {
  28.105 +                        return clazz.cast(ret);
  28.106 +                    }
  28.107 +                }
  28.108 +            }
  28.109 +        }
  28.110 +        return null;
  28.111 +    }
  28.112 +
  28.113 +    /** A method that defines matching between Item and Template.
  28.114 +     * @param item the item to match
  28.115 +     * @return true if item matches the template requirements, false if not
  28.116 +     */
  28.117 +    private static boolean matches(Template<?> t, AbstractLookup.Pair<?> item) {
  28.118 +        if (!AbstractLookup.matches(t, item, true)) {
  28.119 +            return false;
  28.120 +        }
  28.121 +
  28.122 +        Class<?> type = t.getType();
  28.123 +
  28.124 +        if ((type != null) && !type.isAssignableFrom(item.getType())) {
  28.125 +            return false;
  28.126 +        }
  28.127 +
  28.128 +        return true;
  28.129 +    }
  28.130 +
  28.131 +    /**
  28.132 +     * Result used in SimpleLookup. It holds a reference to the collection
  28.133 +     * passed in constructor. As the contents of this lookup result never
  28.134 +     * changes the addLookupListener and removeLookupListener are empty.
  28.135 +     */
  28.136 +    private class SimpleResult<T> extends Lookup.Result<T> {
  28.137 +        /** can be null and is initialized lazily */
  28.138 +        private Set<Class<? extends T>> classes;
  28.139 +
  28.140 +        /** can be null and is initialized lazily */
  28.141 +        private Collection<? extends Item<T>> items;
  28.142 +
  28.143 +        /** Template used for this result. It is never null.*/
  28.144 +        private Template<T> template;
  28.145 +
  28.146 +        /** can be null and is initialized lazily */
  28.147 +        private Collection<T> results;
  28.148 +
  28.149 +        /** Just remembers the supplied argument in variable template.*/
  28.150 +        SimpleResult(Template<T> template) {
  28.151 +            this.template = template;
  28.152 +        }
  28.153 +
  28.154 +        /**
  28.155 +         * Intentionally does nothing because the lookup does not change
  28.156 +         * and no notification is needed.
  28.157 +         */
  28.158 +        public void addLookupListener(LookupListener l) {
  28.159 +        }
  28.160 +
  28.161 +        /**
  28.162 +         * Intentionally does nothing because the lookup does not change
  28.163 +         * and no notification is needed.
  28.164 +         */
  28.165 +        public void removeLookupListener(LookupListener l) {
  28.166 +        }
  28.167 +
  28.168 +        /**
  28.169 +         * Lazy initializes the results collection. Uses a call to allItems
  28.170 +         * to obtain the instances.
  28.171 +         */
  28.172 +        public java.util.Collection<? extends T> allInstances() {
  28.173 +            synchronized (this) {
  28.174 +                if (results != null) {
  28.175 +                    return results;
  28.176 +                }
  28.177 +            }
  28.178 +
  28.179 +
  28.180 +            Collection<T> res = new ArrayList<T>(allItems.size());
  28.181 +
  28.182 +            for (Item<T> item : allItems()) {
  28.183 +                res.add(item.getInstance());
  28.184 +            }
  28.185 +
  28.186 +            synchronized (this) {
  28.187 +                results = Collections.unmodifiableCollection(res);
  28.188 +            }
  28.189 +
  28.190 +            return results;
  28.191 +        }
  28.192 +
  28.193 +        /**
  28.194 +         * Lazy initializes variable classes. Uses a call to allItems to
  28.195 +         * compute the result.
  28.196 +         */
  28.197 +        public Set<Class<? extends T>> allClasses() {
  28.198 +            synchronized (this) {
  28.199 +                if (classes != null) {
  28.200 +                    return classes;
  28.201 +                }
  28.202 +            }
  28.203 +
  28.204 +            Set<Class<? extends T>> res = new HashSet<Class<? extends T>>();
  28.205 +
  28.206 +            for (Item<T> item : allItems()) {
  28.207 +                res.add(item.getType());
  28.208 +            }
  28.209 +
  28.210 +            synchronized (this) {
  28.211 +                classes = Collections.unmodifiableSet(res);
  28.212 +            }
  28.213 +
  28.214 +            return classes;
  28.215 +        }
  28.216 +
  28.217 +        /**
  28.218 +         * Lazy initializes variable items. Creates an item for each
  28.219 +         * element in the instances collection. It puts either SimpleItem
  28.220 +         * or ConvertingItem to the collection.
  28.221 +         */
  28.222 +        public Collection<? extends Item<T>> allItems() {
  28.223 +            synchronized (this) {
  28.224 +                if (items != null) {
  28.225 +                    return items;
  28.226 +                }
  28.227 +            }
  28.228 +
  28.229 +            Collection<Item<T>> res = new ArrayList<Item<T>>(allItems.size());
  28.230 +
  28.231 +            for (Iterator<Item<?>> i = allItems.iterator(); i.hasNext();) {
  28.232 +                Item<?> o = i.next();
  28.233 +
  28.234 +                if (o instanceof AbstractLookup.Pair) {
  28.235 +                    if (matches(template, (AbstractLookup.Pair) o)) {
  28.236 +                        res.add(cast(o));
  28.237 +                    }
  28.238 +                }
  28.239 +            }
  28.240 +
  28.241 +            synchronized (this) {
  28.242 +                items = Collections.unmodifiableCollection(res);
  28.243 +            }
  28.244 +
  28.245 +            return items;
  28.246 +        }
  28.247 +
  28.248 +        @SuppressWarnings("unchecked")
  28.249 +        private Item<T> cast(Item<?> i) {
  28.250 +            return (Item<T>)i;
  28.251 +        }
  28.252 +    }
  28.253 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/SimpleProxyLookup.java	Mon Dec 14 20:58:39 2009 +0100
    29.3 @@ -0,0 +1,359 @@
    29.4 +/*
    29.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    29.6 + *
    29.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    29.8 + *
    29.9 + * The contents of this file are subject to the terms of either the GNU
   29.10 + * General Public License Version 2 only ("GPL") or the Common
   29.11 + * Development and Distribution License("CDDL") (collectively, the
   29.12 + * "License"). You may not use this file except in compliance with the
   29.13 + * License. You can obtain a copy of the License at
   29.14 + * http://www.netbeans.org/cddl-gplv2.html
   29.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   29.16 + * specific language governing permissions and limitations under the
   29.17 + * License.  When distributing the software, include this License Header
   29.18 + * Notice in each file and include the License file at
   29.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   29.20 + * particular file as subject to the "Classpath" exception as provided
   29.21 + * by Sun in the GPL Version 2 section of the License file that
   29.22 + * accompanied this code. If applicable, add the following below the
   29.23 + * License Header, with the fields enclosed by brackets [] replaced by
   29.24 + * your own identifying information:
   29.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   29.26 + *
   29.27 + * Contributor(s):
   29.28 + *
   29.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   29.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   29.31 + * Microsystems, Inc. All Rights Reserved.
   29.32 + *
   29.33 + * If you wish your version of this file to be governed by only the CDDL
   29.34 + * or only the GPL Version 2, indicate your decision by adding
   29.35 + * "[Contributor] elects to include this software in this distribution
   29.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   29.37 + * single choice of license, a recipient has the option to distribute
   29.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   29.39 + * to extend the choice of license to its licensees as provided above.
   29.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   29.41 + * Version 2 license, then the option applies only if the new code is
   29.42 + * made subject to such option by the copyright holder.
   29.43 + */
   29.44 +package org.openide.util.lookup;
   29.45 +
   29.46 +import java.lang.ref.Reference;
   29.47 +import java.lang.ref.WeakReference;
   29.48 +import org.openide.util.Lookup;
   29.49 +import org.openide.util.LookupEvent;
   29.50 +import org.openide.util.LookupListener;
   29.51 +
   29.52 +import java.util.*;
   29.53 +
   29.54 +
   29.55 +/**
   29.56 + * Simple proxy lookup. Keeps reference to a lookup it delegates to and
   29.57 + * forwards all requests.
   29.58 + *
   29.59 + * @author Jaroslav Tulach
   29.60 + */
   29.61 +final class SimpleProxyLookup extends org.openide.util.Lookup {
   29.62 +    /** the provider to check for the status */
   29.63 +    private Provider provider;
   29.64 +
   29.65 +    /** the lookup we currently delegate to */
   29.66 +    private Lookup delegate;
   29.67 +
   29.68 +    /** map of all templates to Reference (results) associated to this lookup */
   29.69 +    private WeakHashMap<Template<?>,Reference<ProxyResult<?>>> results;
   29.70 +
   29.71 +    /**
   29.72 +     * @param provider provider to delegate to
   29.73 +     */
   29.74 +    SimpleProxyLookup(Provider provider) {
   29.75 +        this.provider = provider;
   29.76 +    }
   29.77 +
   29.78 +    /** Checks whether we still delegate to the same lookup */
   29.79 +    private Lookup checkLookup() {
   29.80 +        Lookup l = provider.getLookup();
   29.81 +
   29.82 +        // iterator over Reference (ProxyResult)
   29.83 +        Iterator<Reference<ProxyResult<?>>> toCheck = null;
   29.84 +
   29.85 +        synchronized (this) {
   29.86 +            if (l != delegate) {
   29.87 +                this.delegate = l;
   29.88 +
   29.89 +                if (results != null) {
   29.90 +                    toCheck = new ArrayList<Reference<ProxyResult<?>>>(results.values()).iterator();
   29.91 +                }
   29.92 +            }
   29.93 +        }
   29.94 +
   29.95 +        if (toCheck != null) {
   29.96 +            // update
   29.97 +            ArrayList<Object> evAndListeners = new ArrayList<Object>();
   29.98 +            for (Iterator<Reference<ProxyResult<?>>> it = toCheck; it.hasNext(); ) {
   29.99 +                java.lang.ref.Reference<ProxyResult<?>> ref = it.next();
  29.100 +                if (ref == null) {
  29.101 +                    continue;
  29.102 +                }
  29.103 +
  29.104 +                ProxyResult<?> p = ref.get();
  29.105 +
  29.106 +                if (p != null && p.updateLookup(l)) {
  29.107 +                    p.collectFires(evAndListeners);
  29.108 +                }
  29.109 +            }
  29.110 +            
  29.111 +            for (Iterator it = evAndListeners.iterator(); it.hasNext(); ) {
  29.112 +                LookupEvent ev = (LookupEvent)it.next();
  29.113 +                LookupListener ll = (LookupListener)it.next();
  29.114 +                ll.resultChanged(ev);
  29.115 +            }
  29.116 +        }
  29.117 +
  29.118 +        return delegate;
  29.119 +    }
  29.120 +
  29.121 +    @SuppressWarnings("unchecked")
  29.122 +    private static <T> ProxyResult<T> cast(ProxyResult<?> p) {
  29.123 +        return (ProxyResult<T>)p;
  29.124 +    }
  29.125 +
  29.126 +    public <T> Result<T> lookup(Template<T> template) {
  29.127 +        synchronized (this) {
  29.128 +            if (results == null) {
  29.129 +                results = new WeakHashMap<Template<?>,Reference<ProxyResult<?>>>();
  29.130 +            } else {
  29.131 +                Reference<ProxyResult<?>> ref = results.get(template);
  29.132 +
  29.133 +                if (ref != null) {
  29.134 +                    ProxyResult<?> p = ref.get();
  29.135 +
  29.136 +                    if (p != null) {
  29.137 +                        return cast(p);
  29.138 +                    }
  29.139 +                }
  29.140 +            }
  29.141 +
  29.142 +            ProxyResult<T> p = new ProxyResult<T>(template);
  29.143 +            Reference<ProxyResult<?>> ref = new WeakReference<ProxyResult<?>>(p);
  29.144 +            results.put(template, ref);
  29.145 +
  29.146 +            return p;
  29.147 +        }
  29.148 +    }
  29.149 +
  29.150 +    public <T> T lookup(Class<T> clazz) {
  29.151 +        if (clazz == null) {
  29.152 +            checkLookup();
  29.153 +            return null;
  29.154 +        }
  29.155 +        return checkLookup().lookup(clazz);
  29.156 +    }
  29.157 +
  29.158 +    public <T> Item<T> lookupItem(Template<T> template) {
  29.159 +        return checkLookup().lookupItem(template);
  29.160 +    }
  29.161 +
  29.162 +    /**
  29.163 +     * Result used in SimpleLookup. It holds a reference to the collection
  29.164 +     * passed in constructor. As the contents of this lookup result never
  29.165 +     * changes the addLookupListener and removeLookupListener are empty.
  29.166 +     */
  29.167 +    private final class ProxyResult<T> extends WaitableResult<T> implements LookupListener {
  29.168 +        /** Template used for this result. It is never null.*/
  29.169 +        private Template<T> template;
  29.170 +
  29.171 +        /** result to delegate to */
  29.172 +        private Lookup.Result<T> delegate;
  29.173 +
  29.174 +        /** listeners set */
  29.175 +        private javax.swing.event.EventListenerList listeners;
  29.176 +        private LookupListener lastListener;
  29.177 +
  29.178 +        /** Just remembers the supplied argument in variable template.*/
  29.179 +        ProxyResult(Template<T> template) {
  29.180 +            this.template = template;
  29.181 +        }
  29.182 +
  29.183 +        /** Checks state of the result
  29.184 +         */
  29.185 +        private Result<T> checkResult() {
  29.186 +            updateLookup(checkLookup());
  29.187 +
  29.188 +            return this.delegate;
  29.189 +        }
  29.190 +
  29.191 +        /** Updates the state of the lookup.
  29.192 +         * @return true if the lookup really changed
  29.193 +         */
  29.194 +        public boolean updateLookup(Lookup l) {
  29.195 +            Collection<? extends Item<T>> oldPairs = (delegate != null) ? delegate.allItems() : null;
  29.196 +
  29.197 +            LookupListener removedListener;
  29.198 +
  29.199 +            synchronized (this) {
  29.200 +                if ((delegate != null) && (lastListener != null)) {
  29.201 +                    removedListener = lastListener;
  29.202 +                    delegate.removeLookupListener(lastListener);
  29.203 +                } else {
  29.204 +                    removedListener = null;
  29.205 +                }
  29.206 +            }
  29.207 +
  29.208 +            // cannot call to foreign code 
  29.209 +            Lookup.Result<T> res = l.lookup(template);
  29.210 +
  29.211 +            synchronized (this) {
  29.212 +                if (removedListener == lastListener) {
  29.213 +                    delegate = res;
  29.214 +                    lastListener = new WeakResult<T>(this, delegate);
  29.215 +                    delegate.addLookupListener(lastListener);
  29.216 +                }
  29.217 +            }
  29.218 +
  29.219 +            if (oldPairs == null) {
  29.220 +                // nobody knows about a change
  29.221 +                return false;
  29.222 +            }
  29.223 +
  29.224 +            Collection<? extends Item<T>> newPairs = delegate.allItems();
  29.225 +
  29.226 +            // See #34961 for explanation.
  29.227 +            if (!(oldPairs instanceof List)) {
  29.228 +                if (oldPairs == Collections.EMPTY_SET) {
  29.229 +                    // avoid allocation
  29.230 +                    oldPairs = Collections.emptyList();
  29.231 +                } else {
  29.232 +                    oldPairs = new ArrayList<Item<T>>(oldPairs);
  29.233 +                }
  29.234 +            }
  29.235 +
  29.236 +            if (!(newPairs instanceof List)) {
  29.237 +                newPairs = new ArrayList<Item<T>>(newPairs);
  29.238 +            }
  29.239 +
  29.240 +            return !oldPairs.equals(newPairs);
  29.241 +        }
  29.242 +
  29.243 +        public synchronized void addLookupListener(LookupListener l) {
  29.244 +            if (listeners == null) {
  29.245 +                listeners = new javax.swing.event.EventListenerList();
  29.246 +            }
  29.247 +
  29.248 +            listeners.add(LookupListener.class, l);
  29.249 +        }
  29.250 +
  29.251 +        public synchronized void removeLookupListener(LookupListener l) {
  29.252 +            if (listeners != null) {
  29.253 +                listeners.remove(LookupListener.class, l);
  29.254 +            }
  29.255 +        }
  29.256 +
  29.257 +        public java.util.Collection<? extends T> allInstances() {
  29.258 +            return checkResult().allInstances();
  29.259 +        }
  29.260 +
  29.261 +        public Set<Class<? extends T>> allClasses() {
  29.262 +            return checkResult().allClasses();
  29.263 +        }
  29.264 +
  29.265 +        public Collection<? extends Item<T>> allItems() {
  29.266 +            return checkResult().allItems();
  29.267 +        }
  29.268 +
  29.269 +        protected void beforeLookup(Lookup.Template t) {
  29.270 +            Lookup.Result r = checkResult();
  29.271 +
  29.272 +            if (r instanceof WaitableResult) {
  29.273 +                ((WaitableResult) r).beforeLookup(t);
  29.274 +            }
  29.275 +        }
  29.276 +
  29.277 +        /** A change in lookup occured.
  29.278 +         * @param ev event describing the change
  29.279 +         *
  29.280 +         */
  29.281 +        public void resultChanged(LookupEvent anEvent) {
  29.282 +            collectFires(null);
  29.283 +        } 
  29.284 +        
  29.285 +        protected void collectFires(Collection<Object> evAndListeners) {
  29.286 +            javax.swing.event.EventListenerList l = this.listeners;
  29.287 +
  29.288 +            if (l == null) {
  29.289 +                return;
  29.290 +            }
  29.291 +
  29.292 +            Object[] listeners = l.getListenerList();
  29.293 +
  29.294 +            if (listeners.length == 0) {
  29.295 +                return;
  29.296 +            }
  29.297 +
  29.298 +            LookupEvent ev = new LookupEvent(this);
  29.299 +            AbstractLookup.notifyListeners(listeners, ev, evAndListeners);
  29.300 +        }
  29.301 +    }
  29.302 +     // end of ProxyResult
  29.303 +    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
  29.304 +        private Lookup.Result source;
  29.305 +        private Reference<ProxyResult<T>> result;
  29.306 +        
  29.307 +        public WeakResult(ProxyResult<T> r, Lookup.Result<T> s) {
  29.308 +            this.result = new WeakReference<ProxyResult<T>>(r);
  29.309 +            this.source = s;
  29.310 +        }
  29.311 +        
  29.312 +        protected void beforeLookup(Lookup.Template t) {
  29.313 +            ProxyResult r = (ProxyResult)result.get();
  29.314 +            if (r != null) {
  29.315 +                r.beforeLookup(t);
  29.316 +            } else {
  29.317 +                source.removeLookupListener(this);
  29.318 +            }
  29.319 +        }
  29.320 +
  29.321 +        protected void collectFires(Collection<Object> evAndListeners) {
  29.322 +            ProxyResult<T> r = result.get();
  29.323 +            if (r != null) {
  29.324 +                r.collectFires(evAndListeners);
  29.325 +            } else {
  29.326 +                source.removeLookupListener(this);
  29.327 +            }
  29.328 +        }
  29.329 +
  29.330 +        public void addLookupListener(LookupListener l) {
  29.331 +            assert false;
  29.332 +        }
  29.333 +
  29.334 +        public void removeLookupListener(LookupListener l) {
  29.335 +            assert false;
  29.336 +        }
  29.337 +
  29.338 +        public Collection<T> allInstances() {
  29.339 +            assert false;
  29.340 +            return null;
  29.341 +        }
  29.342 +
  29.343 +        public void resultChanged(LookupEvent ev) {
  29.344 +            ProxyResult r = (ProxyResult)result.get();
  29.345 +            if (r != null) {
  29.346 +                r.resultChanged(ev);
  29.347 +            } else {
  29.348 +                source.removeLookupListener(this);
  29.349 +            }
  29.350 +        }
  29.351 +
  29.352 +        public Collection<? extends Item<T>> allItems() {
  29.353 +            assert false;
  29.354 +            return null;
  29.355 +        }
  29.356 +
  29.357 +        public Set<Class<? extends T>> allClasses() {
  29.358 +            assert false;
  29.359 +            return null;
  29.360 +        }
  29.361 +    } // end of WeakResult
  29.362 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/SingletonLookup.java	Mon Dec 14 20:58:39 2009 +0100
    30.3 @@ -0,0 +1,173 @@
    30.4 +/*
    30.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    30.6 + * 
    30.7 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    30.8 + * 
    30.9 + * The contents of this file are subject to the terms of either the GNU
   30.10 + * General Public License Version 2 only ("GPL") or the Common
   30.11 + * Development and Distribution License("CDDL") (collectively, the
   30.12 + * "License"). You may not use this file except in compliance with the
   30.13 + * License. You can obtain a copy of the License at
   30.14 + * http://www.netbeans.org/cddl-gplv2.html
   30.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   30.16 + * specific language governing permissions and limitations under the
   30.17 + * License.  When distributing the software, include this License Header
   30.18 + * Notice in each file and include the License file at
   30.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   30.20 + * particular file as subject to the "Classpath" exception as provided
   30.21 + * by Sun in the GPL Version 2 section of the License file that
   30.22 + * accompanied this code. If applicable, add the following below the
   30.23 + * License Header, with the fields enclosed by brackets [] replaced by
   30.24 + * your own identifying information:
   30.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   30.26 + * 
   30.27 + * If you wish your version of this file to be governed by only the CDDL
   30.28 + * or only the GPL Version 2, indicate your decision by adding
   30.29 + * "[Contributor] elects to include this software in this distribution
   30.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   30.31 + * single choice of license, a recipient has the option to distribute
   30.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   30.33 + * to extend the choice of license to its licensees as provided above.
   30.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   30.35 + * Version 2 license, then the option applies only if the new code is
   30.36 + * made subject to such option by the copyright holder.
   30.37 + * 
   30.38 + * Contributor(s):
   30.39 + * 
   30.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   30.41 + */
   30.42 +
   30.43 +package org.openide.util.lookup;
   30.44 +
   30.45 +import java.util.Collection;
   30.46 +import java.util.Collections;
   30.47 +import java.util.Set;
   30.48 +import org.openide.util.Lookup;
   30.49 +import org.openide.util.LookupListener;
   30.50 +
   30.51 +/**
   30.52 + * Unmodifiable lookup that contains just one fixed object.
   30.53 + *
   30.54 + * @author Marian Petras
   30.55 + */
   30.56 +class SingletonLookup extends Lookup {
   30.57 +
   30.58 +    private final Object objectToLookup;
   30.59 +    private final String id;
   30.60 +
   30.61 +    SingletonLookup(Object objectToLookup) {
   30.62 +        this(objectToLookup, null);
   30.63 +    }
   30.64 +
   30.65 +    SingletonLookup(Object objectToLookup, String id) {
   30.66 +        if (objectToLookup == null) {
   30.67 +            throw new IllegalArgumentException("null");                 //NOI18N
   30.68 +        }
   30.69 +
   30.70 +        this.objectToLookup = objectToLookup;
   30.71 +        this.id = id;
   30.72 +    }
   30.73 +
   30.74 +    @Override
   30.75 +    public <T> T lookup(Class<T> clazz) {
   30.76 +        if (clazz == null) {
   30.77 +            throw new IllegalArgumentException("null");                 //NOI18N
   30.78 +        }
   30.79 +
   30.80 +        return (clazz.isInstance(objectToLookup))
   30.81 +               ? clazz.cast(objectToLookup)
   30.82 +               : null;
   30.83 +    }
   30.84 +
   30.85 +    @Override
   30.86 +    public <T> Result<T> lookup(Template<T> template) {
   30.87 +        if (template == null) {
   30.88 +            throw new IllegalArgumentException("null");                 //NOI18N
   30.89 +        }
   30.90 +
   30.91 +        Lookup.Item<T> item = lookupItem(template);
   30.92 +        if (item != null) {
   30.93 +            return new SingletonResult<T>(item);
   30.94 +        } else {
   30.95 +            return Lookup.EMPTY.lookup(template);
   30.96 +        }
   30.97 +    }
   30.98 +
   30.99 +    @Override
  30.100 +    public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
  30.101 +        if (clazz == null) {
  30.102 +            throw new IllegalArgumentException("null");                 //NOI18N
  30.103 +        }
  30.104 +
  30.105 +        return (clazz.isInstance(objectToLookup))
  30.106 +               ? Collections.singletonList(clazz.cast(objectToLookup))
  30.107 +               : Collections.<T>emptyList();
  30.108 +    }
  30.109 +
  30.110 +    @Override
  30.111 +    @SuppressWarnings("unchecked")
  30.112 +    public <T> Item<T> lookupItem(Template<T> template) {
  30.113 +        if (template == null) {
  30.114 +            throw new IllegalArgumentException("null");                 //NOI18N
  30.115 +        }
  30.116 +
  30.117 +        String templateId = template.getId();
  30.118 +        if ((templateId != null) && !templateId.equals(id)) {
  30.119 +            return null;
  30.120 +        }
  30.121 +
  30.122 +        Object templateInst = template.getInstance();
  30.123 +        if ((templateInst != null) && (objectToLookup != templateInst)) {
  30.124 +            return null;
  30.125 +        }
  30.126 +
  30.127 +        Class<T> clazz = template.getType();
  30.128 +        if ((clazz != null) && !clazz.isInstance(objectToLookup)) {
  30.129 +            return null;
  30.130 +        }
  30.131 +
  30.132 +        Lookup.Item<T> item;
  30.133 +        if (clazz != null) {
  30.134 +            item = Lookups.lookupItem(clazz.cast(objectToLookup), id);
  30.135 +        } else {
  30.136 +            item = Lookups.lookupItem((T) objectToLookup, id);
  30.137 +        }
  30.138 +        return item;
  30.139 +    }
  30.140 +
  30.141 +    static class SingletonResult<T> extends Lookup.Result<T> {
  30.142 +
  30.143 +        private final Lookup.Item<T> item;
  30.144 +
  30.145 +        SingletonResult(Lookup.Item<T> item) {
  30.146 +            this.item = item;
  30.147 +        }
  30.148 +
  30.149 +        @Override
  30.150 +        public void addLookupListener(LookupListener l) {
  30.151 +            // this result never changes - no need to register a listener
  30.152 +        }
  30.153 +
  30.154 +        @Override
  30.155 +        public void removeLookupListener(LookupListener l) {
  30.156 +            // this result never changes - no need to register a listener
  30.157 +        }
  30.158 +
  30.159 +        @Override
  30.160 +        public Set<Class<? extends T>> allClasses() {
  30.161 +            return Collections.<Class<? extends T>>singleton(item.getType());
  30.162 +        }
  30.163 +
  30.164 +        @Override
  30.165 +        public Collection<? extends Item<T>> allItems() {
  30.166 +            return Collections.singletonList(item);
  30.167 +        }
  30.168 +
  30.169 +        @Override
  30.170 +        public Collection<? extends T> allInstances() {
  30.171 +            return Collections.singletonList(item.getInstance());
  30.172 +        }
  30.173 +
  30.174 +    }
  30.175 +
  30.176 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/WaitableResult.java	Mon Dec 14 20:58:39 2009 +0100
    31.3 @@ -0,0 +1,62 @@
    31.4 +/*
    31.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    31.6 + *
    31.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    31.8 + *
    31.9 + * The contents of this file are subject to the terms of either the GNU
   31.10 + * General Public License Version 2 only ("GPL") or the Common
   31.11 + * Development and Distribution License("CDDL") (collectively, the
   31.12 + * "License"). You may not use this file except in compliance with the
   31.13 + * License. You can obtain a copy of the License at
   31.14 + * http://www.netbeans.org/cddl-gplv2.html
   31.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   31.16 + * specific language governing permissions and limitations under the
   31.17 + * License.  When distributing the software, include this License Header
   31.18 + * Notice in each file and include the License file at
   31.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   31.20 + * particular file as subject to the "Classpath" exception as provided
   31.21 + * by Sun in the GPL Version 2 section of the License file that
   31.22 + * accompanied this code. If applicable, add the following below the
   31.23 + * License Header, with the fields enclosed by brackets [] replaced by
   31.24 + * your own identifying information:
   31.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   31.26 + *
   31.27 + * Contributor(s):
   31.28 + *
   31.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   31.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   31.31 + * Microsystems, Inc. All Rights Reserved.
   31.32 + *
   31.33 + * If you wish your version of this file to be governed by only the CDDL
   31.34 + * or only the GPL Version 2, indicate your decision by adding
   31.35 + * "[Contributor] elects to include this software in this distribution
   31.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   31.37 + * single choice of license, a recipient has the option to distribute
   31.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   31.39 + * to extend the choice of license to its licensees as provided above.
   31.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   31.41 + * Version 2 license, then the option applies only if the new code is
   31.42 + * made subject to such option by the copyright holder.
   31.43 + */
   31.44 +package org.openide.util.lookup;
   31.45 +
   31.46 +import java.util.Collection;
   31.47 +import org.openide.util.Lookup;
   31.48 +
   31.49 +
   31.50 +/** A special subclass of lookup that is able to wait before queries.
   31.51 + *
   31.52 + * @author  Jaroslav Tulach
   31.53 + */
   31.54 +abstract class WaitableResult<T> extends Lookup.Result<T> {
   31.55 +    /** Used by proxy results to synchronize before lookup.
   31.56 +     */
   31.57 +    protected abstract void beforeLookup(Lookup.Template t);
   31.58 +
   31.59 +    /** Needed to group notification of outside the package listeners
   31.60 +     * after all AbstractLookup and ProxyLookups have been updated.
   31.61 +     * @param evAndListeners LookupEvent, LookupListener, LookupEvent, LookupListener, etc.
   31.62 +     */
   31.63 +    protected abstract void collectFires(Collection<Object> evAndListeners);
   31.64 +     
   31.65 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/doc-files/index.html	Mon Dec 14 20:58:39 2009 +0100
    32.3 @@ -0,0 +1,208 @@
    32.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    32.5 +<!--
    32.6 +   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    32.7 +   -
    32.8 +   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    32.9 +   -
   32.10 +   - The contents of this file are subject to the terms of either the GNU
   32.11 +   - General Public License Version 2 only ("GPL") or the Common
   32.12 +   - Development and Distribution License("CDDL") (collectively, the
   32.13 +   - "License"). You may not use this file except in compliance with the
   32.14 +   - License. You can obtain a copy of the License at
   32.15 +   - http://www.netbeans.org/cddl-gplv2.html
   32.16 +   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   32.17 +   - specific language governing permissions and limitations under the
   32.18 +   - License.  When distributing the software, include this License Header
   32.19 +   - Notice in each file and include the License file at
   32.20 +   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   32.21 +   - particular file as subject to the "Classpath" exception as provided
   32.22 +   - by Sun in the GPL Version 2 section of the License file that
   32.23 +   - accompanied this code. If applicable, add the following below the
   32.24 +   - License Header, with the fields enclosed by brackets [] replaced by
   32.25 +   - your own identifying information:
   32.26 +   - "Portions Copyrighted [year] [name of copyright owner]"
   32.27 +   -
   32.28 +   - Contributor(s):
   32.29 +   -
   32.30 +   - The Original Software is NetBeans. The Initial Developer of the Original
   32.31 +   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   32.32 +   - Microsystems, Inc. All Rights Reserved.
   32.33 +   -
   32.34 +   - If you wish your version of this file to be governed by only the CDDL
   32.35 +   - or only the GPL Version 2, indicate your decision by adding
   32.36 +   - "[Contributor] elects to include this software in this distribution
   32.37 +   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   32.38 +   - single choice of license, a recipient has the option to distribute
   32.39 +   - your version of this file under either the CDDL, the GPL Version 2 or
   32.40 +   - to extend the choice of license to its licensees as provided above.
   32.41 +   - However, if you add GPL Version 2 code and therefore, elected the GPL
   32.42 +   - Version 2 license, then the option applies only if the new code is
   32.43 +   - made subject to such option by the copyright holder.
   32.44 +  -->
   32.45 +<HTML>
   32.46 +<HEAD>
   32.47 +<TITLE>Lookup Library</TITLE>
   32.48 +<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
   32.49 +</HEAD>
   32.50 +<BODY>
   32.51 +
   32.52 +<P>
   32.53 +
   32.54 +This is the home page of the <em>lookup library</em> implementation, which 
   32.55 +is intended to solve a general problem that every <cite>component-based system</CITE>
   32.56 +has had to face: how different components <b>register</b> to the system 
   32.57 +and how other parts of the system can <b>look</b> them <b>up</B>. 
   32.58 +<P>
   32.59 +There already are libraries trying to solve this problem, usually by querying for 
   32.60 +an interface and finding its appropriate implementaion. The most famous is 
   32.61 +<A href="http://www.jini.org/">Jini</A>, the platform for development of
   32.62 +distributed network services. Our library does something similar, but tries 
   32.63 +to stay small and easy
   32.64 +to use. The NetBeans <em>Lookup
   32.65 +Library</EM>'s main focus is a modular application consisting of independent modules
   32.66 +that want to communicate with each other. It does not try to solve networking or
   32.67 +legacy application integration. It is simple but powerful.
   32.68 +
   32.69 +<H2>Why would you want to use it?</H2>
   32.70 +
   32.71 +A well-written modular program separates <em>development</EM>
   32.72 +and <em>deployment</EM>.
   32.73 +There are many situations where a component needs some functionality but
   32.74 +does not actually care about the implementation. It is up to the <em>system
   32.75 +adminstrator</em> that deploys (installs) the application to decide which 
   32.76 +implementation to use.
   32.77 +<P>
   32.78 +The most simple and most often used method for allowing other implementations
   32.79 +to be plugged in is the <em>system property</em> pattern:
   32.80 +
   32.81 +<pre>
   32.82 +    <font class="keyword">public</font> <font class="type">Toolkit</font> <font class="function-name">getDefaultToolkit</font> () {
   32.83 +        java.awt.<font class="type">Toolkit</font> <font class="variable-name">t</font> = <font class="constant">null</font>;
   32.84 +        <font class="type">String</font> <font class="variable-name">classname</font> = System.getProperty (<font class="string">"java.awt.Toolkit"</font>);
   32.85 +        <font class="keyword">if</font> (classname != <font class="constant">null</font>) {
   32.86 +            <font class="keyword">try</font> {
   32.87 +                <font class="type">Class</font> <font class="variable-name">c</font> = Class.forName (classname);
   32.88 +                t = (java.awt.<font class="type">Toolkit</font>)c.newInstance ();
   32.89 +            } <font class="keyword">catch</font> (<font class="type">Exception</font> <font class="variable-name">ex</font>) {
   32.90 +                System.out.println (<font class="string">"Cannot initialize toolkit: "</font> + classname);
   32.91 +                ex.printStackTrace ();
   32.92 +            }
   32.93 +        }
   32.94 +        <font class="comment">// fallback </font>
   32.95 +        <font class="keyword">if</font> (t == <font class="constant">null</font>) {
   32.96 +            t = <font class="keyword">new</font> <font class="type">GenericAWTToolkit</font> ();
   32.97 +        }
   32.98 +    }
   32.99 +</pre>
  32.100 +
  32.101 +    
  32.102 +The idea is simple. The <em>deployer</em> can start the Java VM with the flag
  32.103 +<code>-Djava.awt.Toolkit=org.myorg.MyToolkit</code> where the <code>MyToolkit</code>
  32.104 +is his class with default constructor and the code in the <code>getDefaultToolkit</CODE>
  32.105 +method will instantiate the class and use it.
  32.106 +<P>
  32.107 +In principle this is general enough of a solution and works well, except that writing the 
  32.108 +code above is error prone and it also requires passing the arguments to the virtual machine. 
  32.109 +It would be much nicer if the registation could be done just by putting a JAR file with the <code>MyToolkit</code> class
  32.110 +into the application classpath.
  32.111 +<P>
  32.112 +Actually this has been realized also by the JDK development team and addressed in
  32.113 +JDK 1.3 as part of the <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Provider%20Configuration%20File">provider extension mechanism</A>. 
  32.114 +The <code>MyToolkit</code> could be registered by adding a file 
  32.115 +<code>/META-INF/services/java.awt.Toolkit</code> with one line
  32.116 +<code>org.myorg.MyToolkit</code> into the JAR file that contains the
  32.117 +<code>MyToolkit</CODE> implementation. The code in <code>getDefaultToolkit</CODE>
  32.118 +will scan all JAR files in classpath and search for that file,
  32.119 +create an instance of <code>MyToolkit</code> and use it. 
  32.120 +The deployer can influence which toolkit will be created by 
  32.121 +adding the right JAR files into the classpath.
  32.122 +<P>
  32.123 +Of course the code to access the <code>META-INF/services/</code> files is even
  32.124 +more error prone than the <em>property pattern</EM>.  And this is exactly the
  32.125 +place where the <em>lookup library</em> can help. It provides an implementation of
  32.126 +the search algorithm with an easy interface. Just write:
  32.127 +<pre>
  32.128 +    <font class="keyword">import</font> <font class="type">java.awt.Toolkit</font>;
  32.129 +    <font class="keyword">import</font> <font class="type">org.openide.util.Lookup;</font>;
  32.130 +    <font class="type">Toolkit</font> <font class="variable-name">t</font> = (<font class="type">Toolkit</font>)Lookup.getDefault().<a href="@TOP@org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(Toolkit.<font class="keyword">class</font>);
  32.131 +</PRE>
  32.132 +and if the JAR with <code>MyToolkit</CODE> is in the class path, the simple call 
  32.133 +above will do the rest.
  32.134 +<P>
  32.135 +So whenever one writes an application divided into several independent modules (jar files)
  32.136 +that are being developed and deployed independently, there is a need for registering
  32.137 +and discovering components. First of all, a set of interfaces can be defined to enable 
  32.138 +inter-module communication (like the abstract class <code>java.awt.Toolkit</CODE>).
  32.139 +After that a set of modules providing implementation can written (<code>MyToolkit</code> and other concurent implementations)
  32.140 +and after that, whenever a module trying to utilitize the functionality wants to access
  32.141 +the <code>Toolkit</code> via lookup, the real implementation is returned.
  32.142 +<P>
  32.143 +It is the responsibility of lookup to find a suitable implementation of the
  32.144 +requested service and return an object implementing the service. This is the
  32.145 +the basic functionality and while the library provides you with a little bit
  32.146 +more, even this simple usage might be extremaly useful: the client code knows
  32.147 +nothing about the implementation and the implementation can be switched in
  32.148 +deployment time by simply replacing one implementation jar with other. There
  32.149 +is no code change required.
  32.150 +
  32.151 +<H2> Local lookup usage </H2>
  32.152 +The example in previous paragraph demostrated the usage of lookup as a global
  32.153 +registry (by using the <CODE>Lookup.getDefault()</CODE> call). One can also
  32.154 +consider another scenario where the lookup can help.
  32.155 +<P>
  32.156 +Let's switch hats to be an API designer for a while. The goal is to introduce a
  32.157 +new object into the system. But you either are not sure yet what all the roles
  32.158 +of the new object will be or you (more importantly) want to be able to add (or
  32.159 +change) roles of the object dynamically. So why not to introduce following
  32.160 +method to the object's interface:
  32.161 +<pre>
  32.162 +<font class="keyword">public class </FONT> <font class="type">MorphingObject</FONT> {
  32.163 +    <font class="keyword">public</FONT> <font class="type"><a href="@TOP@org/openide/util/Lookup.html">Lookup</A></FONT> getLookup() {
  32.164 +        <font class="keyword">return</FONT> <font class="variable-name">myLookup;</FONT>
  32.165 +    }
  32.166 +    ...
  32.167 +}
  32.168 +</pre>
  32.169 +By exposing the method getLookup you can attach different functionality to the
  32.170 +MorphingObject at runtime and whoever gets a reference to your object can ask it
  32.171 +whether the object supports a given interface like this:
  32.172 +<pre>
  32.173 +<font class="type">MorphingObject</FONT> <font class="variable-name">morph</FONT> = ...
  32.174 +<font class="type">AnInterface</font> <font class="variable-name">impl</font> = (<font
  32.175 +class="type">AnInterface</font>)morph.getLookup().<a
  32.176 +href="@TOP@org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(AnInterface.<font class="keyword">class</font>);
  32.177 +<font class="keyword">if</font> (impl == <font class="constant">null</font>) {
  32.178 +    <font class="keyword">return;</font><font class="comment">/* AnInterface not supported now! */</font>
  32.179 +}
  32.180 +impl.useIt();
  32.181 +</PRE>
  32.182 +
  32.183 +<H2>Additional functionality</H2>
  32.184 +The NetBeans lookup library also provides:
  32.185 +<UL>
  32.186 +<LI>Support for dynamically changing the lookup content.</LI>
  32.187 +<LI>The ability to return multiple results.</LI>
  32.188 +<LI>Notification of changes. After retrieving the result, the client can attach a
  32.189 +listener and be notified when the result of the lookup is changed.</LI>
  32.190 +<LI>Lazy initialization of the implementation. The implementation objects are
  32.191 +initialized only after someone asks for them. Even the implementation classes
  32.192 +are not loaded if they are not going to be used! </LI>
  32.193 +</UL>
  32.194 +
  32.195 +<H2>Further information</H2>
  32.196 +<UL>
  32.197 +  <LI><A HREF="lookup-api.html">Lookup Library APIs</A> for those writing the client code.
  32.198 +Specifying the query, getting the result and listenning on changes.</LI>
  32.199 +  <LI><A HREF="lookup-spi.html">Lookup Library SPIs</A> for those writing the
  32.200 +implementaion code and registering it with lookup. Includes also writing own
  32.201 +lookup implementation.</LI>
  32.202 +  <LI>Download <A HREF="http://www.netbeans.org/">NetBeans platform</A> which
  32.203 +contains <code>org-openide-util.jar</code></LI>
  32.204 +    <A HREF="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/lookup/">
  32.205 +    implementation package (org.openide.util.lookup) </A>
  32.206 +    + classes Lookup, LookupEvent, LookupListener in
  32.207 +    <A href="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/">util package</A></LI>
  32.208 +  <li><a href="http://www.martinfowler.com/articles/injection.html">Inversion of Control Containers and the Dependency Injection pattern</a> (Martin Fowler)</li>
  32.209 +</UL>
  32.210 +</BODY>
  32.211 +</HTML>
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/doc-files/lookup-api.html	Mon Dec 14 20:58:39 2009 +0100
    33.3 @@ -0,0 +1,188 @@
    33.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    33.5 +<!--
    33.6 +   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    33.7 +   -
    33.8 +   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    33.9 +   -
   33.10 +   - The contents of this file are subject to the terms of either the GNU
   33.11 +   - General Public License Version 2 only ("GPL") or the Common
   33.12 +   - Development and Distribution License("CDDL") (collectively, the
   33.13 +   - "License"). You may not use this file except in compliance with the
   33.14 +   - License. You can obtain a copy of the License at
   33.15 +   - http://www.netbeans.org/cddl-gplv2.html
   33.16 +   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   33.17 +   - specific language governing permissions and limitations under the
   33.18 +   - License.  When distributing the software, include this License Header
   33.19 +   - Notice in each file and include the License file at
   33.20 +   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   33.21 +   - particular file as subject to the "Classpath" exception as provided
   33.22 +   - by Sun in the GPL Version 2 section of the License file that
   33.23 +   - accompanied this code. If applicable, add the following below the
   33.24 +   - License Header, with the fields enclosed by brackets [] replaced by
   33.25 +   - your own identifying information:
   33.26 +   - "Portions Copyrighted [year] [name of copyright owner]"
   33.27 +   -
   33.28 +   - Contributor(s):
   33.29 +   -
   33.30 +   - The Original Software is NetBeans. The Initial Developer of the Original
   33.31 +   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   33.32 +   - Microsystems, Inc. All Rights Reserved.
   33.33 +   -
   33.34 +   - If you wish your version of this file to be governed by only the CDDL
   33.35 +   - or only the GPL Version 2, indicate your decision by adding
   33.36 +   - "[Contributor] elects to include this software in this distribution
   33.37 +   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   33.38 +   - single choice of license, a recipient has the option to distribute
   33.39 +   - your version of this file under either the CDDL, the GPL Version 2 or
   33.40 +   - to extend the choice of license to its licensees as provided above.
   33.41 +   - However, if you add GPL Version 2 code and therefore, elected the GPL
   33.42 +   - Version 2 license, then the option applies only if the new code is
   33.43 +   - made subject to such option by the copyright holder.
   33.44 +  -->
   33.45 +<HTML>
   33.46 +<HEAD>
   33.47 +<TITLE>Lookup Library API</TITLE>
   33.48 +<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
   33.49 +</HEAD>
   33.50 +<BODY>
   33.51 +<H1>Lookup library API</H1>
   33.52 +<p>
   33.53 +This document describes usage of the API provided by the Lookup Library. In this
   33.54 +document we assume that someone has already provided us with a lookup
   33.55 +implementation (for those seeking how to write a lookup implementation please
   33.56 +check <A href="lookup-spi.html">the SPI document</A>).
   33.57 +
   33.58 +<H2> Getting the lookup </H2>
   33.59 +
   33.60 +The first question you might ask is this: how can I get hold of a
   33.61 +lookup instance? There are basically two ways how you can get it.
   33.62 +
   33.63 +<H3> Global lookup </H3>
   33.64 +As you can see in the
   33.65 +
   33.66 +<a href="@TOP@org/openide/util/Lookup.html">Lookup</a>
   33.67 +
   33.68 +Javadoc there is a static method
   33.69 +
   33.70 +<pre><a href="@TOP@org/openide/util/Lookup.html#getDefault()">public static Lookup getDefault()</a></pre>
   33.71 +
   33.72 +The object returned from this method is
   33.73 +a global lookup that can serve as a central place for registering services.
   33.74 +The default implementation is a lookup that implements
   33.75 +<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">
   33.76 +the JDK JAR services</A>
   33.77 +mechanism and delegates to <samp>META-INF/services/name.of.Class</samp> files.
   33.78 +<P>
   33.79 +If you want to add your class to this lookup just create a file in your
   33.80 +jar file under the <code>META-INF</code> directory (e.g. <samp>META-INF/services/com.my.APIClass</samp>)
   33.81 +and let the file contain only one line of text
   33.82 +
   33.83 +<pre>com.foo.impl.ImplOfTheAPI</pre>
   33.84 +
   33.85 +<p>(This is more easily done using the <code>@ServiceProvider</code> annotation.)</p>
   33.86 +
   33.87 +The following code will return you a newly created instance of
   33.88 +<code>com.foo.impl.ImplOfTheAPI</code>:
   33.89 +
   33.90 +<PRE>
   33.91 +   <font class="keyword">import</FONT> org.openide.util.Lookup;
   33.92 +   return Lookup.getDefault().lookup(com.my.APIClass.class);
   33.93 +</PRE>
   33.94 +
   33.95 +<H3> Local lookup </H3>
   33.96 +
   33.97 +This is just a reminder that whenever you find a method called getLookup
   33.98 +or similar returning a lookup instance, the provided lookup is <EM>not</EM> the
   33.99 +general lookup described in the previous paragraph. Rather, it is a private lookup
  33.100 +implementation that is usually bound to the object you invoked the method on.
  33.101 +
  33.102 +<H2> Use of Lookup.Template and Lookup.Result </H2>
  33.103 +
  33.104 +There are more ways how you can ask lookup besides the variant with one class
  33.105 +parameter. If you want more functionality, you have to implement the interface
  33.106 +Lookup.Template and pass an instance of such object to the lookup call.
  33.107 +<p>
  33.108 +<EM>Note:</EM> If you use Lookup.Template, the object returned from the lookup is
  33.109 +<EM>not</EM> the object you are looking for but rather a result object
  33.110 +(Lookup.Result). You can call methods on such a result object to get the actual
  33.111 +results.
  33.112 +<p>
  33.113 +Let's examine following example:
  33.114 +
  33.115 +<pre>
  33.116 +        <font class="keyword">import</FONT> org.openide.util.Lookup;
  33.117 +
  33.118 +        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
  33.119 +        Lookup.<font class="type">Template</font> <font class="variable-name">template</font> = <font class="keyword">new</font> Lookup.<font class="type">Template</font>(MyService.<font class="keyword">class</font>);
  33.120 +        Lookup.<font class="type">Result</font> <font class="variable-name">result</font> = lookup.lookup(template);
  33.121 +        <font class="type">Collection</font> <font class="variable-name">c</font> = result.allInstances();
  33.122 +        <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = c.iterator(); i.hasNext(); ) {
  33.123 +            <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
  33.124 +            s.callMyService();
  33.125 +        }
  33.126 +</pre>
  33.127 +
  33.128 +In this example the call to method lookup(...) returns immediately because the
  33.129 +result object can be constructed even without real results. The first time you
  33.130 +ask for the result object by calling r.allInstances(), the lookup has to supply you
  33.131 +the real results and this method can block until the required data are really
  33.132 +available.
  33.133 +<p>
  33.134 +If you are not interested in all objects as in the previous example, you can use the
  33.135 +template to ask for one resulting object (wrapped in special Item instance):
  33.136 +<pre>
  33.137 +        <font class="keyword">import</FONT> org.openide.util.Lookup;
  33.138 +
  33.139 +        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
  33.140 +        Lookup.<font class="type">Template</font> <font class="variable-name">template</font> = <font class="keyword">new</font> Lookup.<font class="type">Template</font>(MyService.<font class="keyword">class</font>);
  33.141 +        Lookup.<font class="type">Item</font> <font class="variable-name">item</font> = lookup.lookupItem(template);
  33.142 +        <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)item.getInstance();
  33.143 +        s.callMyService();
  33.144 +</pre>
  33.145 +
  33.146 +Again, the Item object can construct the real instance only if you call
  33.147 +getInstance. The item can be useful even without calling getInstance - you can get
  33.148 +its display name or an unique id. You can use this information, for example, for
  33.149 +constructing menu items without the need to instantiate (or even load!)
  33.150 +the class implementing the functionality. Only when the real functionality is
  33.151 +needed (e.g. the user has selected the menu item) you can call getInstance
  33.152 +and call the real meat of the implementation.
  33.153 +
  33.154 +<H2> Listenning on lookup changes </H2>
  33.155 +There is one additional piece of functionality bound to the Lookup.Result object worth
  33.156 +mentioning: you can attach a listener to it and be informed about any changes in
  33.157 +the lookup. This might be extremly usefull when the lookup dynamically changes
  33.158 +(from other threads). The listener can keep state of your object up-to-date even
  33.159 +in cases where the lookup changes asynchronously.
  33.160 +<p>
  33.161 +So here is some sample code using the listenner:
  33.162 +
  33.163 +<pre>
  33.164 +        <font class="keyword">import</FONT> org.openide.util.Lookup;
  33.165 +        <font class="keyword">import</FONT> org.openide.util.LookupListener;
  33.166 +        <font class="keyword">import</FONT> org.openide.util.LookupEvent;
  33.167 +
  33.168 +        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
  33.169 +        Lookup.<font class="type">Template</font> <font class="variable-name">template</font> = <font class="keyword">new</font> Lookup.<font class="type">Template</font>(MyService.<font class="keyword">class</font>);
  33.170 +        <font class="keyword">final</font> <font class="variable-name">Lookup</font>.<font class="type">Result</font> <font class="variable-name">result</font> = lookup.lookup(template);
  33.171 +        result.addLookupListener(<font class="keyword">new</font> <font class="type">LookupListener</font>() {
  33.172 +            <font class="keyword">public</font> <font class="type">void</font> <font class="function-name">resultChanged</font>(<font class="type">LookupEvent</font> <font class="variable-name">e</font>) {
  33.173 +                reaction(result);
  33.174 +            }
  33.175 +        });
  33.176 +        reaction(result);
  33.177 +    }
  33.178 +    <font class="keyword">private</font> <font class="keyword">static</font> <font class="type">void</font> <font class="function-name">reaction</font>(Lookup.<font class="type">Result</font> <font class="variable-name">r</font>) {
  33.179 +        <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = r.allInstances().iterator(); i.hasNext(); ) {
  33.180 +            <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
  33.181 +            s.callMyService();
  33.182 +        }
  33.183 +    }
  33.184 +</pre>
  33.185 +
  33.186 +Please note that we first attach a listener and then call the reaction method.
  33.187 +This ensures that we always get the newest possible state. Also you must be
  33.188 +careful in the reaction method since it can be called from two different
  33.189 +threads simultaneously (your code has to be prepared for this).
  33.190 +</BODY>
  33.191 +</HTML>
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/doc-files/lookup-spi.html	Mon Dec 14 20:58:39 2009 +0100
    34.3 @@ -0,0 +1,147 @@
    34.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    34.5 +<!--
    34.6 +   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    34.7 +   -
    34.8 +   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    34.9 +   -
   34.10 +   - The contents of this file are subject to the terms of either the GNU
   34.11 +   - General Public License Version 2 only ("GPL") or the Common
   34.12 +   - Development and Distribution License("CDDL") (collectively, the
   34.13 +   - "License"). You may not use this file except in compliance with the
   34.14 +   - License. You can obtain a copy of the License at
   34.15 +   - http://www.netbeans.org/cddl-gplv2.html
   34.16 +   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   34.17 +   - specific language governing permissions and limitations under the
   34.18 +   - License.  When distributing the software, include this License Header
   34.19 +   - Notice in each file and include the License file at
   34.20 +   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   34.21 +   - particular file as subject to the "Classpath" exception as provided
   34.22 +   - by Sun in the GPL Version 2 section of the License file that
   34.23 +   - accompanied this code. If applicable, add the following below the
   34.24 +   - License Header, with the fields enclosed by brackets [] replaced by
   34.25 +   - your own identifying information:
   34.26 +   - "Portions Copyrighted [year] [name of copyright owner]"
   34.27 +   -
   34.28 +   - Contributor(s):
   34.29 +   -
   34.30 +   - The Original Software is NetBeans. The Initial Developer of the Original
   34.31 +   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   34.32 +   - Microsystems, Inc. All Rights Reserved.
   34.33 +   -
   34.34 +   - If you wish your version of this file to be governed by only the CDDL
   34.35 +   - or only the GPL Version 2, indicate your decision by adding
   34.36 +   - "[Contributor] elects to include this software in this distribution
   34.37 +   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   34.38 +   - single choice of license, a recipient has the option to distribute
   34.39 +   - your version of this file under either the CDDL, the GPL Version 2 or
   34.40 +   - to extend the choice of license to its licensees as provided above.
   34.41 +   - However, if you add GPL Version 2 code and therefore, elected the GPL
   34.42 +   - Version 2 license, then the option applies only if the new code is
   34.43 +   - made subject to such option by the copyright holder.
   34.44 +  -->
   34.45 +<HTML>
   34.46 +<HEAD>
   34.47 +<TITLE>Lookup Library SPI</TITLE>
   34.48 +<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
   34.49 +</HEAD>
   34.50 +<BODY>
   34.51 +<H1>Lookup library SPI</H1>
   34.52 +This document describe usage of the SPI provided by the Lookup Library
   34.53 +(for those seeking how to use lookup instance please
   34.54 +check <A href="lookup-api.html">the API document</A>).
   34.55 +<p>
   34.56 +By using the SPI you can create lookups that can be used by the users of the
   34.57 +Lookup API. While the Lookup API consists of a couple of classes in the package
   34.58 +<em>org.openide.util.*</EM>,
   34.59 +the SPI has its own package <em>org.openide.util.lookup.*</EM>.
   34.60 +
   34.61 +<H2> Simple lookups </H2>
   34.62 +Let us start with the simplest case. You have decided that your newly created
   34.63 +object will provide an API in the form of a getLookup() method. You have to
   34.64 +return a functional lookup from this call. You can use static methods in class
   34.65 +<a href="@TOP@org/openide/util/lookup/Lookups.html">
   34.66 +<code>Lookups</code></A> to create a lookup for you. If you want only one
   34.67 +object to be returned, just call 
   34.68 +<a href="@TOP@org/openide/util/lookup/Lookups.html#singleton(java.lang.Object)">
   34.69 +<code>Lookups.singleton(x)</code></A> where x is the object to be 
   34.70 +returned by the lookup. Or if you want to supply more objects, use a call to the method
   34.71 +<a href="@TOP@org/openide/util/lookup/Lookups.html#fixed(java.lang.Object...)">
   34.72 +<code>fixed(Object []x)</CODE></A>.
   34.73 +<EM> Note: </EM> The lookups returned from methods <code>singleton(...)</code> and
   34.74 +<code>fixed(...)</code> do <EM>
   34.75 +not </EM> support dynamic changes and attaching listeners. Their content is
   34.76 +fixed from the time you call the creating method.
   34.77 +
   34.78 +<H2> ProxyLookup </H2>
   34.79 +There can be situations where you get a lookup object from someone else and you
   34.80 +want your lookup to return exactly the instances from the original lookup plus
   34.81 +your own results. Here the class ProxyLookup comes into the play.
   34.82 +<p>
   34.83 +You simply create a new lookup like this:
   34.84 +
   34.85 +<pre>
   34.86 +    <font class="keyword">import</FONT> org.openide.util.Lookup;
   34.87 +    <font class="keyword">import</FONT> org.openide.util.lookup.*;
   34.88 +
   34.89 +    <font class="type">Lookup</font> <font class="variable-name">lookup1</font> = ...;
   34.90 +
   34.91 +    <font class="type">Lookup</font> <font class="variable-name">lookup2</font> = Lookups.singleton(MyService.<font class="keyword">class</font>);
   34.92 +    <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">ProxyLookup</font>(<font class="keyword">new</font> <font class="type">Lookup</font>[] { lookup, lookup2 });
   34.93 +</pre>
   34.94 +
   34.95 +<H2> AbstractLookup </H2>
   34.96 +<!-- This paragraph originally copied from
   34.97 +@TOP@org/openide/doc-files/services-api.html#lookup-impl
   34.98 +-->
   34.99 +
  34.100 +<p>The most powerful way to provide a lookup is to directly define
  34.101 +what instances and items it should provide, by subclassing. For this,
  34.102 +
  34.103 +<a href="@TOP@org/openide/util/lookup/AbstractLookup.html"><code>AbstractLookup</code></a>
  34.104 +
  34.105 +is recommended as it is easiest to use.
  34.106 +
  34.107 +<p>The simplest way to use <code>AbstractLookup</code> is to use its
  34.108 +public constructor (in which case you need not subclass it). Here you
  34.109 +provide an
  34.110 +
  34.111 +<a href="@TOP@org/openide/util/lookup/AbstractLookup.Content.html"><code>AbstractLookup.Content</code></a>
  34.112 +
  34.113 +object which you have created and hold on to privately, and which
  34.114 +keeps track of instances and permits them to be registered and
  34.115 +deregistered. Often
  34.116 +
  34.117 +<a href="@TOP@org/openide/util/lookup/InstanceContent.html"><code>InstanceContent</code></a>
  34.118 +
  34.119 +is used as the content implementation. To add something to the lookup,
  34.120 +simply use
  34.121 +
  34.122 +<a href="@TOP@org/openide/util/lookup/InstanceContent.html#add(java.lang.Object)"><code>add(Object)</code></a>
  34.123 +
  34.124 +(and <code>remove(Object)</code> for the reverse). These may be called
  34.125 +at any time and will update the set of registered instances (firing
  34.126 +result changes as needed).
  34.127 +
  34.128 +<pre>
  34.129 +    <font class="keyword">import</FONT> org.openide.util.lookup.*;
  34.130 +    <font class="type">InstanceContent</font> <font class="variable-name">ic</font> = <font class="keyword">new</font> <font class="type">InstanceContent</font> ();
  34.131 +    ic.add(firstObject);
  34.132 +    <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">AbstractLookup</font> (ic);
  34.133 +</pre>
  34.134 +
  34.135 +<p>In case it is expensive to actually compute the object in the
  34.136 +lookup, but there is some cheap "key" which can easily generate it,
  34.137 +you may instead register the key by passing in an
  34.138 +
  34.139 +<a href="@TOP@org/openide/util/lookup/InstanceContent.Convertor.html"><code>InstanceContent.Convertor</code></a>.
  34.140 +
  34.141 +This convertor translates the key to the real instance that the lookup
  34.142 +client sees, if and when needed. For example, if you have a long list
  34.143 +of class names and wish to register default instances of each class,
  34.144 +you might actually register the class name as the key, and supply a
  34.145 +convertor which really loads the class and instantiates it. This makes
  34.146 +it easy to set up the lookup, but nothing is really loaded until
  34.147 +someone asks for it.
  34.148 +
  34.149 +</BODY>
  34.150 +</HTML>
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/package.html	Mon Dec 14 20:58:39 2009 +0100
    35.3 @@ -0,0 +1,48 @@
    35.4 +<!--
    35.5 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    35.6 +
    35.7 +Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    35.8 +
    35.9 +
   35.10 +The contents of this file are subject to the terms of either the GNU
   35.11 +General Public License Version 2 only ("GPL") or the Common
   35.12 +Development and Distribution License("CDDL") (collectively, the
   35.13 +"License"). You may not use this file except in compliance with the
   35.14 +License. You can obtain a copy of the License at
   35.15 +http://www.netbeans.org/cddl-gplv2.html
   35.16 +or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   35.17 +specific language governing permissions and limitations under the
   35.18 +License.  When distributing the software, include this License Header
   35.19 +Notice in each file and include the License file at
   35.20 +nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   35.21 +particular file as subject to the "Classpath" exception as provided
   35.22 +by Sun in the GPL Version 2 section of the License file that
   35.23 +accompanied this code. If applicable, add the following below the
   35.24 +License Header, with the fields enclosed by brackets [] replaced by
   35.25 +your own identifying information:
   35.26 +"Portions Copyrighted [year] [name of copyright owner]"
   35.27 +
   35.28 +Contributor(s):
   35.29 +
   35.30 +The Original Software is NetBeans. The Initial Developer of the Original
   35.31 +Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   35.32 +Microsystems, Inc. All Rights Reserved.
   35.33 +
   35.34 +If you wish your version of this file to be governed by only the CDDL
   35.35 +or only the GPL Version 2, indicate your decision by adding
   35.36 +"[Contributor] elects to include this software in this distribution
   35.37 +under the [CDDL or GPL Version 2] license." If you do not indicate a
   35.38 +single choice of license, a recipient has the option to distribute
   35.39 +your version of this file under either the CDDL, the GPL Version 2 or
   35.40 +to extend the choice of license to its licensees as provided above.
   35.41 +However, if you add GPL Version 2 code and therefore, elected the GPL
   35.42 +Version 2 license, then the option applies only if the new code is
   35.43 +made subject to such option by the copyright holder.
   35.44 +-->
   35.45 +
   35.46 +<html>
   35.47 +<body>
   35.48 +Support classes for the Registration and {@link org.openide.util.Lookup} extension mechanism.
   35.49 +Read more: <a href="doc-files/index.html">Lookup Library</a>
   35.50 +</body>
   35.51 +</html>
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/openide.util.lookup/src/org/openide/util/package.html	Mon Dec 14 20:58:39 2009 +0100
    36.3 @@ -0,0 +1,50 @@
    36.4 +<!--
    36.5 +   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    36.6 +   -
    36.7 +   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    36.8 +   -
    36.9 +   - The contents of this file are subject to the terms of either the GNU
   36.10 +   - General Public License Version 2 only ("GPL") or the Common
   36.11 +   - Development and Distribution License("CDDL") (collectively, the
   36.12 +   - "License"). You may not use this file except in compliance with the
   36.13 +   - License. You can obtain a copy of the License at
   36.14 +   - http://www.netbeans.org/cddl-gplv2.html
   36.15 +   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   36.16 +   - specific language governing permissions and limitations under the
   36.17 +   - License.  When distributing the software, include this License Header
   36.18 +   - Notice in each file and include the License file at
   36.19 +   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   36.20 +   - particular file as subject to the "Classpath" exception as provided
   36.21 +   - by Sun in the GPL Version 2 section of the License file that
   36.22 +   - accompanied this code. If applicable, add the following below the
   36.23 +   - License Header, with the fields enclosed by brackets [] replaced by
   36.24 +   - your own identifying information:
   36.25 +   - "Portions Copyrighted [year] [name of copyright owner]"
   36.26 +   -
   36.27 +   - Contributor(s):
   36.28 +   -
   36.29 +   - The Original Software is NetBeans. The Initial Developer of the Original
   36.30 +   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   36.31 +   - Microsystems, Inc. All Rights Reserved.
   36.32 +   -
   36.33 +   - If you wish your version of this file to be governed by only the CDDL
   36.34 +   - or only the GPL Version 2, indicate your decision by adding
   36.35 +   - "[Contributor] elects to include this software in this distribution
   36.36 +   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   36.37 +   - single choice of license, a recipient has the option to distribute
   36.38 +   - your version of this file under either the CDDL, the GPL Version 2 or
   36.39 +   - to extend the choice of license to its licensees as provided above.
   36.40 +   - However, if you add GPL Version 2 code and therefore, elected the GPL
   36.41 +   - Version 2 license, then the option applies only if the new code is
   36.42 +   - made subject to such option by the copyright holder.
   36.43 +  -->
   36.44 +
   36.45 +<html>
   36.46 +<body>
   36.47 +
   36.48 +Client API part of the
   36.49 +<a href="http://top/org/openide/util/lookup/doc-files/lookup-api.html">Lookup</a>
   36.50 +interfaces.
   36.51 +
   36.52 +</body>
   36.53 +</html>
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/openide.util.lookup/test/unit/src/org/bar/Comparator2.java	Mon Dec 14 20:58:39 2009 +0100
    37.3 @@ -0,0 +1,7 @@
    37.4 +
    37.5 +package org.bar;
    37.6 +
    37.7 +public class Comparator2 implements java.util.Comparator {
    37.8 +    public int compare(Object o1, Object o2) {return 0;}
    37.9 +    public boolean equals(Object obj) {return true;}
   37.10 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/openide.util.lookup/test/unit/src/org/bar/Comparator3.java	Mon Dec 14 20:58:39 2009 +0100
    38.3 @@ -0,0 +1,7 @@
    38.4 +
    38.5 +package org.bar;
    38.6 +
    38.7 +public class Comparator3 implements java.util.Comparator {
    38.8 +    public int compare(Object o1, Object o2) {return 0;}
    38.9 +    public boolean equals(Object obj) {return true;}
   38.10 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/openide.util.lookup/test/unit/src/org/bar/Implementation2.java	Mon Dec 14 20:58:39 2009 +0100
    39.3 @@ -0,0 +1,3 @@
    39.4 +package org.bar;
    39.5 +import org.foo.Interface;
    39.6 +public class Implementation2 implements Interface {}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/openide.util.lookup/test/unit/src/org/bar/Iterator2.java	Mon Dec 14 20:58:39 2009 +0100
    40.3 @@ -0,0 +1,11 @@
    40.4 +
    40.5 +package org.bar;
    40.6 +
    40.7 +public class Iterator2 implements java.util.Iterator {
    40.8 +    public boolean hasNext() {return false;}
    40.9 +    
   40.10 +    public Object next() {return null;}
   40.11 +    
   40.12 +    public void remove() {}
   40.13 +   
   40.14 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/openide.util.lookup/test/unit/src/org/foo/Interface.java	Mon Dec 14 20:58:39 2009 +0100
    41.3 @@ -0,0 +1,2 @@
    41.4 +package org.foo;
    41.5 +public interface Interface {}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/openide.util.lookup/test/unit/src/org/foo/impl/Comparator1.java	Mon Dec 14 20:58:39 2009 +0100
    42.3 @@ -0,0 +1,7 @@
    42.4 +
    42.5 +package org.foo.impl;
    42.6 +
    42.7 +public class Comparator1 implements java.util.Comparator {
    42.8 +    public int compare(Object o1, Object o2) {return 0;}
    42.9 +    public boolean equals(Object obj) {return true;}
   42.10 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/openide.util.lookup/test/unit/src/org/foo/impl/Implementation1.java	Mon Dec 14 20:58:39 2009 +0100
    43.3 @@ -0,0 +1,3 @@
    43.4 +package org.foo.impl;
    43.5 +import org.foo.Interface;
    43.6 +public class Implementation1 implements Interface {}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/openide.util.lookup/test/unit/src/org/foo/impl/Iterator1.java	Mon Dec 14 20:58:39 2009 +0100
    44.3 @@ -0,0 +1,11 @@
    44.4 +
    44.5 +package org.foo.impl;
    44.6 +
    44.7 +public class Iterator1 implements java.util.Iterator {
    44.8 +    public boolean hasNext() {return false;}
    44.9 +    
   44.10 +    public Object next() {return null;}
   44.11 +    
   44.12 +    public void remove() {}
   44.13 +   
   44.14 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/openide.util.lookup/test/unit/src/org/foo/impl/Runnable1.java	Mon Dec 14 20:58:39 2009 +0100
    45.3 @@ -0,0 +1,6 @@
    45.4 +
    45.5 +package org.foo.impl;
    45.6 +
    45.7 +public class Runnable1 implements Runnable {
    45.8 +   public void run () {}
    45.9 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/openide.util.lookup/test/unit/src/org/netbeans/modules/openide/util/ActiveQueueTest.java	Mon Dec 14 20:58:39 2009 +0100
    46.3 @@ -0,0 +1,132 @@
    46.4 +/*
    46.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    46.6 + *
    46.7 + * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
    46.8 + *
    46.9 + * The contents of this file are subject to the terms of either the GNU
   46.10 + * General Public License Version 2 only ("GPL") or the Common
   46.11 + * Development and Distribution License("CDDL") (collectively, the
   46.12 + * "License"). You may not use this file except in compliance with the
   46.13 + * License. You can obtain a copy of the License at
   46.14 + * http://www.netbeans.org/cddl-gplv2.html
   46.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   46.16 + * specific language governing permissions and limitations under the
   46.17 + * License.  When distributing the software, include this License Header
   46.18 + * Notice in each file and include the License file at
   46.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   46.20 + * particular file as subject to the "Classpath" exception as provided
   46.21 + * by Sun in the GPL Version 2 section of the License file that
   46.22 + * accompanied this code. If applicable, add the following below the
   46.23 + * License Header, with the fields enclosed by brackets [] replaced by
   46.24 + * your own identifying information:
   46.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   46.26 + *
   46.27 + * If you wish your version of this file to be governed by only the CDDL
   46.28 + * or only the GPL Version 2, indicate your decision by adding
   46.29 + * "[Contributor] elects to include this software in this distribution
   46.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   46.31 + * single choice of license, a recipient has the option to distribute
   46.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   46.33 + * to extend the choice of license to its licensees as provided above.
   46.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   46.35 + * Version 2 license, then the option applies only if the new code is
   46.36 + * made subject to such option by the copyright holder.
   46.37 + *
   46.38 + * Contributor(s):
   46.39 + *
   46.40 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
   46.41 + */
   46.42 +
   46.43 +package org.netbeans.modules.openide.util;
   46.44 +
   46.45 +import java.lang.ref.Reference;
   46.46 +import java.lang.ref.ReferenceQueue;
   46.47 +import java.lang.ref.WeakReference;
   46.48 +import java.net.URL;
   46.49 +import java.net.URLClassLoader;
   46.50 +import org.netbeans.junit.NbTestCase;
   46.51 +
   46.52 +/**
   46.53 + *
   46.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   46.55 + */
   46.56 +public class ActiveQueueTest extends NbTestCase{
   46.57 +
   46.58 +    public ActiveQueueTest(String name) {
   46.59 +        super(name);
   46.60 +    }
   46.61 +
   46.62 +    public void testMemoryLeak() throws Exception {
   46.63 +        final Class<?> u1 = ActiveQueue.class;
   46.64 +        class L extends URLClassLoader {
   46.65 +            public L() {
   46.66 +                super(new URL[] {u1.getProtectionDomain().getCodeSource().getLocation()}, u1.getClassLoader().getParent());
   46.67 +            }
   46.68 +            @Override
   46.69 +            protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
   46.70 +                if (name.equals(u1.getName()) || name.startsWith(u1.getName() + "$")) {
   46.71 +                    Class c = findLoadedClass(name);
   46.72 +                    if (c == null) {
   46.73 +                        c = findClass(name);
   46.74 +                    }
   46.75 +                    if (resolve) {
   46.76 +                        resolveClass(c);
   46.77 +                    }
   46.78 +                    return c;
   46.79 +                } else {
   46.80 +                    return super.loadClass(name, resolve);
   46.81 +                }
   46.82 +            }
   46.83 +        }
   46.84 +        ClassLoader l = new L();
   46.85 +        Class<?> u2 = l.loadClass(u1.getName());
   46.86 +        assertEquals(l, u2.getClassLoader());
   46.87 +        Object obj = new Object();
   46.88 +        @SuppressWarnings("unchecked")
   46.89 +        ReferenceQueue<Object> q = (ReferenceQueue<Object>) u2.getMethod("queue").invoke(null);
   46.90 +        RunnableRef ref = new RunnableRef(obj, q);
   46.91 +        synchronized (ref) {
   46.92 +            obj = null;
   46.93 +            assertGC("Ref should be GC'ed as usual", ref);
   46.94 +            ref.wait();
   46.95 +            assertTrue("Run method has been executed", ref.executed);
   46.96 +        }
   46.97 +        Reference<?> r = new WeakReference<Object>(u2);
   46.98 +        q = null;
   46.99 +        u2 = null;
  46.100 +        l = null;
  46.101 +        assertGC("#86625: Utilities.class can also be collected now", r);
  46.102 +    }
  46.103 +
  46.104 +
  46.105 +    private static class RunnableRef extends WeakReference<Object>
  46.106 +    implements Runnable {
  46.107 +        public boolean wait;
  46.108 +        public boolean entered;
  46.109 +        public boolean executed;
  46.110 +
  46.111 +        public RunnableRef (Object o) {
  46.112 +            this(o, ActiveQueue.queue());
  46.113 +        }
  46.114 +
  46.115 +        public RunnableRef(Object o, ReferenceQueue<Object> q) {
  46.116 +            super(o, q);
  46.117 +        }
  46.118 +
  46.119 +        public synchronized void run () {
  46.120 +            entered = true;
  46.121 +            if (wait) {
  46.122 +                // notify we are here
  46.123 +                notify ();
  46.124 +                try {
  46.125 +                    wait ();
  46.126 +                } catch (InterruptedException ex) {
  46.127 +                }
  46.128 +            }
  46.129 +            executed = true;
  46.130 +
  46.131 +            notifyAll ();
  46.132 +        }
  46.133 +    }
  46.134 +
  46.135 +}
  46.136 \ No newline at end of file
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/openide.util.lookup/test/unit/src/org/netbeans/modules/openide/util/ServiceProviderProcessorTest.java	Mon Dec 14 20:58:39 2009 +0100
    47.3 @@ -0,0 +1,180 @@
    47.4 +/*
    47.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    47.6 + *
    47.7 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    47.8 + *
    47.9 + * The contents of this file are subject to the terms of either the GNU
   47.10 + * General Public License Version 2 only ("GPL") or the Common
   47.11 + * Development and Distribution License("CDDL") (collectively, the
   47.12 + * "License"). You may not use this file except in compliance with the
   47.13 + * License. You can obtain a copy of the License at
   47.14 + * http://www.netbeans.org/cddl-gplv2.html
   47.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   47.16 + * specific language governing permissions and limitations under the
   47.17 + * License.  When distributing the software, include this License Header
   47.18 + * Notice in each file and include the License file at
   47.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   47.20 + * particular file as subject to the "Classpath" exception as provided
   47.21 + * by Sun in the GPL Version 2 section of the License file that
   47.22 + * accompanied this code. If applicable, add the following below the
   47.23 + * License Header, with the fields enclosed by brackets [] replaced by
   47.24 + * your own identifying information:
   47.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   47.26 + *
   47.27 + * If you wish your version of this file to be governed by only the CDDL
   47.28 + * or only the GPL Version 2, indicate your decision by adding
   47.29 + * "[Contributor] elects to include this software in this distribution
   47.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   47.31 + * single choice of license, a recipient has the option to distribute
   47.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   47.33 + * to extend the choice of license to its licensees as provided above.
   47.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   47.35 + * Version 2 license, then the option applies only if the new code is
   47.36 + * made subject to such option by the copyright holder.
   47.37 + *
   47.38 + * Contributor(s):
   47.39 + *
   47.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   47.41 + */
   47.42 +
   47.43 +package org.netbeans.modules.openide.util;
   47.44 +
   47.45 +import java.io.ByteArrayOutputStream;
   47.46 +import java.io.File;
   47.47 +import java.util.ArrayList;
   47.48 +import java.util.Arrays;
   47.49 +import java.util.Collections;
   47.50 +import java.util.Comparator;
   47.51 +import java.util.List;
   47.52 +import org.netbeans.junit.NbTestCase;
   47.53 +import org.openide.util.Lookup;
   47.54 +import org.openide.util.lookup.Lookups;
   47.55 +import org.openide.util.lookup.ServiceProvider;
   47.56 +import org.openide.util.lookup.ServiceProviders;
   47.57 +import org.openide.util.test.AnnotationProcessorTestUtils;
   47.58 +
   47.59 +public class ServiceProviderProcessorTest extends NbTestCase {
   47.60 +
   47.61 +    public ServiceProviderProcessorTest(String n) {
   47.62 +        super(n);
   47.63 +    }
   47.64 +
   47.65 +    private static List<Class<?>> classesOf(Iterable<?> objects) {
   47.66 +        List<Class<?>> cs = new ArrayList<Class<?>>();
   47.67 +        for (Object o : objects) {
   47.68 +            cs.add(o.getClass());
   47.69 +        }
   47.70 +        return cs;
   47.71 +    }
   47.72 +
   47.73 +    private static List<Class<?>> classesOfLookup(Class<?> xface) {
   47.74 +        return classesOf(Lookup.getDefault().lookupAll(xface));
   47.75 +    }
   47.76 +
   47.77 +    private static List<Class<?>> sortClassList(List<Class<?>> classes) {
   47.78 +        List<Class<?>> sorted = new ArrayList<Class<?>>(classes);
   47.79 +        Collections.sort(sorted, new Comparator<Class<?>>() {
   47.80 +            public int compare(Class<?> c1, Class<?> c2) {
   47.81 +                return c1.getName().compareTo(c2.getName());
   47.82 +            }
   47.83 +        });
   47.84 +        return sorted;
   47.85 +    }
   47.86 +
   47.87 +    public void testBasicUsage() throws Exception {
   47.88 +        assertEquals(Collections.singletonList(Implementation.class), classesOfLookup(Interface.class));
   47.89 +    }
   47.90 +    public interface Interface {}
   47.91 +    @ServiceProvider(service=Interface.class)
   47.92 +    public static class Implementation implements Interface {}
   47.93 +
   47.94 +    public void testPosition() throws Exception {
   47.95 +        assertEquals(Arrays.<Class<?>>asList(OrderedImpl3.class, OrderedImpl2.class, OrderedImpl1.class), classesOfLookup(OrderedInterface.class));
   47.96 +    }
   47.97 +    public interface OrderedInterface {}
   47.98 +    @ServiceProvider(service=OrderedInterface.class)
   47.99 +    public static class OrderedImpl1 implements OrderedInterface {}
  47.100 +    @ServiceProvider(service=OrderedInterface.class, position=200)
  47.101 +    public static class OrderedImpl2 implements OrderedInterface {}
  47.102 +    @ServiceProvider(service=OrderedInterface.class, position=100)
  47.103 +    public static class OrderedImpl3 implements OrderedInterface {}
  47.104 +
  47.105 +    public void testPath() throws Exception {
  47.106 +        assertEquals(Collections.singletonList(PathImplementation.class), classesOf(Lookups.forPath("some/path").lookupAll(Interface.class)));
  47.107 +    }
  47.108 +    @ServiceProvider(service=Interface.class, path="some/path")
  47.109 +    public static class PathImplementation implements Interface {}
  47.110 +
  47.111 +    public void testSupersedes() throws Exception {
  47.112 +        assertEquals(Arrays.<Class<?>>asList(Overrider.class, Unrelated.class), sortClassList(classesOfLookup(CancellableInterface.class)));
  47.113 +    }
  47.114 +    public interface CancellableInterface {}
  47.115 +    @ServiceProvider(service=CancellableInterface.class)
  47.116 +    public static class Overridden implements CancellableInterface {}
  47.117 +    @ServiceProvider(service=CancellableInterface.class, supersedes="org.netbeans.modules.openide.util.ServiceProviderProcessorTest$Overridden")
  47.118 +    public static class Overrider implements CancellableInterface {}
  47.119 +    @ServiceProvider(service=CancellableInterface.class)
  47.120 +    public static class Unrelated implements CancellableInterface {}
  47.121 +
  47.122 +    public void testMultipleRegistrations() throws Exception {
  47.123 +        assertEquals(Collections.singletonList(Multitasking.class), classesOfLookup(Interface1.class));
  47.124 +        assertEquals(Collections.singletonList(Multitasking.class), classesOfLookup(Interface2.class));
  47.125 +    }
  47.126 +    public interface Interface1 {}
  47.127 +    public interface Interface2 {}
  47.128 +    @ServiceProviders({@ServiceProvider(service=Interface1.class), @ServiceProvider(service=Interface2.class)})
  47.129 +    public static class Multitasking implements Interface1, Interface2 {}
  47.130 +
  47.131 +    public void testErrorReporting() throws Exception {
  47.132 +        clearWorkDir();
  47.133 +        File src = new File(getWorkDir(), "src");
  47.134 +        File dest = new File(getWorkDir(), "classes");
  47.135 +        String xfaceName = Interface.class.getCanonicalName();
  47.136 +
  47.137 +        AnnotationProcessorTestUtils.makeSource(src, "p.C1",
  47.138 +                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
  47.139 +                "public class C1 implements " + xfaceName + " {}");
  47.140 +        ByteArrayOutputStream baos = new ByteArrayOutputStream();
  47.141 +        assertTrue(AnnotationProcessorTestUtils.runJavac(src, "C1", dest, null, baos));
  47.142 +
  47.143 +        AnnotationProcessorTestUtils.makeSource(src, "p.C2",
  47.144 +                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
  47.145 +                "class C2 implements " + xfaceName + " {}");
  47.146 +        baos = new ByteArrayOutputStream();
  47.147 +        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C2", dest, null, baos));
  47.148 +        assertTrue(baos.toString(), baos.toString().contains("public"));
  47.149 +
  47.150 +        AnnotationProcessorTestUtils.makeSource(src, "p.C3",
  47.151 +                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
  47.152 +                "public class C3 implements " + xfaceName + " {",
  47.153 +                "public C3(boolean x) {}",
  47.154 +                "}");
  47.155 +        baos = new ByteArrayOutputStream();
  47.156 +        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C3", dest, null, baos));
  47.157 +        assertTrue(baos.toString(), baos.toString().contains("constructor"));
  47.158 +
  47.159 +        AnnotationProcessorTestUtils.makeSource(src, "p.C4",
  47.160 +                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
  47.161 +                "public class C4 implements " + xfaceName + " {",
  47.162 +                "C4() {}",
  47.163 +                "}");
  47.164 +        baos = new ByteArrayOutputStream();
  47.165 +        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C4", dest, null, baos));
  47.166 +        assertTrue(baos.toString(), baos.toString().contains("constructor"));
  47.167 +
  47.168 +        AnnotationProcessorTestUtils.makeSource(src, "p.C5",
  47.169 +                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
  47.170 +                "public abstract class C5 implements " + xfaceName + " {}");
  47.171 +        baos = new ByteArrayOutputStream();
  47.172 +        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C5", dest, null, baos));
  47.173 +        assertTrue(baos.toString(), baos.toString().contains("abstract"));
  47.174 +
  47.175 +        AnnotationProcessorTestUtils.makeSource(src, "p.C6",
  47.176 +                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
  47.177 +                "public class C6 {}");
  47.178 +        baos = new ByteArrayOutputStream();
  47.179 +        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C6", dest, null, baos));
  47.180 +        assertTrue(baos.toString(), baos.toString().contains("assignable"));
  47.181 +    }
  47.182 +
  47.183 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupArrayStorageTest.java	Mon Dec 14 20:58:39 2009 +0100
    48.3 @@ -0,0 +1,120 @@
    48.4 +/*
    48.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    48.6 + *
    48.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    48.8 + *
    48.9 + * The contents of this file are subject to the terms of either the GNU
   48.10 + * General Public License Version 2 only ("GPL") or the Common
   48.11 + * Development and Distribution License("CDDL") (collectively, the
   48.12 + * "License"). You may not use this file except in compliance with the
   48.13 + * License. You can obtain a copy of the License at
   48.14 + * http://www.netbeans.org/cddl-gplv2.html
   48.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   48.16 + * specific language governing permissions and limitations under the
   48.17 + * License.  When distributing the software, include this License Header
   48.18 + * Notice in each file and include the License file at
   48.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   48.20 + * particular file as subject to the "Classpath" exception as provided
   48.21 + * by Sun in the GPL Version 2 section of the License file that
   48.22 + * accompanied this code. If applicable, add the following below the
   48.23 + * License Header, with the fields enclosed by brackets [] replaced by
   48.24 + * your own identifying information:
   48.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   48.26 + *
   48.27 + * Contributor(s):
   48.28 + *
   48.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   48.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   48.31 + * Microsystems, Inc. All Rights Reserved.
   48.32 + *
   48.33 + * If you wish your version of this file to be governed by only the CDDL
   48.34 + * or only the GPL Version 2, indicate your decision by adding
   48.35 + * "[Contributor] elects to include this software in this distribution
   48.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   48.37 + * single choice of license, a recipient has the option to distribute
   48.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   48.39 + * to extend the choice of license to its licensees as provided above.
   48.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   48.41 + * Version 2 license, then the option applies only if the new code is
   48.42 + * made subject to such option by the copyright holder.
   48.43 + */
   48.44 +
   48.45 +package org.openide.util.lookup;
   48.46 +
   48.47 +import junit.framework.*;
   48.48 +import org.netbeans.junit.*;
   48.49 +import org.openide.util.Lookup;
   48.50 +
   48.51 +public class AbstractLookupArrayStorageTest extends AbstractLookupBaseHid {
   48.52 +    public AbstractLookupArrayStorageTest(java.lang.String testName) {
   48.53 +        super(testName, null);
   48.54 +    }
   48.55 +
   48.56 +    public static TestSuite suite () {
   48.57 +        NbTestSuite suite = new NbTestSuite ();
   48.58 +        suite.addTest (new PL (2));
   48.59 +        suite.addTest (new AL (1));
   48.60 +        suite.addTest (new AL (-1));
   48.61 +        suite.addTest (new PL (-1));
   48.62 +        suite.addTest (new AL (5));
   48.63 +        suite.addTest (new PL (3));
   48.64 +        suite.addTest (new AL (2000));
   48.65 +        suite.addTest (new PL (2000));
   48.66 +        return suite;
   48.67 +    }
   48.68 +
   48.69 +    static final class AL extends ArrayTestSuite {
   48.70 +        public AL (int trash) {
   48.71 +            super (trash);
   48.72 +        }
   48.73 +        
   48.74 +        public Lookup createLookup (Lookup lookup) {
   48.75 +            return lookup;
   48.76 +        }
   48.77 +        
   48.78 +        public void clearCaches () {
   48.79 +        }
   48.80 +        
   48.81 +    }
   48.82 +    
   48.83 +    static final class PL extends ArrayTestSuite {
   48.84 +        public PL (int trash) {
   48.85 +            super (trash);
   48.86 +        }
   48.87 +        
   48.88 +        public Lookup createLookup (Lookup lookup) {
   48.89 +            return  new ProxyLookup (new Lookup[] { lookup });
   48.90 +        }
   48.91 +        
   48.92 +        public void clearCaches () {
   48.93 +        }
   48.94 +        
   48.95 +    }
   48.96 +    
   48.97 +    private static abstract class ArrayTestSuite extends NbTestSuite 
   48.98 +    implements AbstractLookupBaseHid.Impl {
   48.99 +        private int trash;
  48.100 +        
  48.101 +        public ArrayTestSuite (int trash) {
  48.102 +            super (AbstractLookupArrayStorageTest.class);
  48.103 +            this.trash = trash;
  48.104 +            
  48.105 +            int cnt = this.countTestCases();
  48.106 +            for (int i = 0; i < cnt; i++) {
  48.107 +                Object o = this.testAt (i);
  48.108 +                AbstractLookupBaseHid t = (AbstractLookupBaseHid)o;
  48.109 +                t.impl = this;
  48.110 +            }
  48.111 +        }
  48.112 +        
  48.113 +        public Lookup createInstancesLookup (InstanceContent ic) {
  48.114 +            if (trash == -1) {
  48.115 +                return new AbstractLookup (ic, new ArrayStorage ());
  48.116 +            } else {
  48.117 +                return new AbstractLookup (ic, new ArrayStorage (new Integer (trash)));
  48.118 +            }
  48.119 +        }
  48.120 +        
  48.121 +        
  48.122 +    }
  48.123 +}
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupAsynchExecutorTest.java	Mon Dec 14 20:58:39 2009 +0100
    49.3 @@ -0,0 +1,108 @@
    49.4 +/*
    49.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    49.6 + *
    49.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    49.8 + *
    49.9 + * The contents of this file are subject to the terms of either the GNU
   49.10 + * General Public License Version 2 only ("GPL") or the Common
   49.11 + * Development and Distribution License("CDDL") (collectively, the
   49.12 + * "License"). You may not use this file except in compliance with the
   49.13 + * License. You can obtain a copy of the License at
   49.14 + * http://www.netbeans.org/cddl-gplv2.html
   49.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   49.16 + * specific language governing permissions and limitations under the
   49.17 + * License.  When distributing the software, include this License Header
   49.18 + * Notice in each file and include the License file at
   49.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   49.20 + * particular file as subject to the "Classpath" exception as provided
   49.21 + * by Sun in the GPL Version 2 section of the License file that
   49.22 + * accompanied this code. If applicable, add the following below the
   49.23 + * License Header, with the fields enclosed by brackets [] replaced by
   49.24 + * your own identifying information:
   49.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   49.26 + *
   49.27 + * Contributor(s):
   49.28 + *
   49.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   49.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   49.31 + * Microsystems, Inc. All Rights Reserved.
   49.32 + *
   49.33 + * If you wish your version of this file to be governed by only the CDDL
   49.34 + * or only the GPL Version 2, indicate your decision by adding
   49.35 + * "[Contributor] elects to include this software in this distribution
   49.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   49.37 + * single choice of license, a recipient has the option to distribute
   49.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   49.39 + * to extend the choice of license to its licensees as provided above.
   49.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   49.41 + * Version 2 license, then the option applies only if the new code is
   49.42 + * made subject to such option by the copyright holder.
   49.43 + */
   49.44 +
   49.45 +package org.openide.util.lookup;
   49.46 +
   49.47 +import java.util.ArrayList;
   49.48 +import java.util.List;
   49.49 +import java.util.concurrent.Executor;
   49.50 +import org.netbeans.junit.NbTestCase;
   49.51 +import org.openide.util.Lookup;
   49.52 +import org.openide.util.LookupEvent;
   49.53 +import org.openide.util.LookupListener;
   49.54 +
   49.55 +public class AbstractLookupAsynchExecutorTest extends NbTestCase implements Executor {
   49.56 +    private List<Runnable> toRun = new ArrayList<Runnable>();
   49.57 +
   49.58 +
   49.59 +    public AbstractLookupAsynchExecutorTest(java.lang.String testName) {
   49.60 +        super(testName);
   49.61 +    }
   49.62 +
   49.63 +    public void testCanProxyLookupHaveWrongResults() {
   49.64 +        final InstanceContent ic = new InstanceContent(this);
   49.65 +        final AbstractLookup lookup = new AbstractLookup(ic);
   49.66 +
   49.67 +        class L implements LookupListener {
   49.68 +            ProxyLookup pl;
   49.69 +            Lookup.Result<String> original;
   49.70 +            Lookup.Result<String> wrapped;
   49.71 +            boolean ok;
   49.72 +
   49.73 +            public void test() {
   49.74 +                pl = new ProxyLookup(lookup);
   49.75 +                original = lookup.lookupResult(String.class);
   49.76 +
   49.77 +                original.addLookupListener(this);
   49.78 +
   49.79 +                wrapped = pl.lookupResult(String.class);
   49.80 +
   49.81 +                assertEquals("Original empty", 0, original.allInstances().size());
   49.82 +                assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
   49.83 +
   49.84 +                ic.add("Hello!");
   49.85 +            }
   49.86 +
   49.87 +            public void resultChanged(LookupEvent ev) {
   49.88 +                ok = true;
   49.89 +                assertContainsHello();
   49.90 +            }
   49.91 +
   49.92 +            public void assertContainsHello() {
   49.93 +                assertEquals("Original has hello", 1, original.allInstances().size());
   49.94 +                assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
   49.95 +            }
   49.96 +
   49.97 +        }
   49.98 +        L listener = new L();
   49.99 +        listener.test();
  49.100 +        listener.assertContainsHello();
  49.101 +        for (Runnable r : toRun) {
  49.102 +            r.run();
  49.103 +        }
  49.104 +        assertTrue("Listener called", listener.ok);
  49.105 +    }
  49.106 +
  49.107 +    public void execute(Runnable command) {
  49.108 +        toRun.add(command);
  49.109 +    }
  49.110 +
  49.111 +}
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java	Mon Dec 14 20:58:39 2009 +0100
    50.3 @@ -0,0 +1,2088 @@
    50.4 +/*
    50.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    50.6 + *
    50.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    50.8 + *
    50.9 + * The contents of this file are subject to the terms of either the GNU
   50.10 + * General Public License Version 2 only ("GPL") or the Common
   50.11 + * Development and Distribution License("CDDL") (collectively, the
   50.12 + * "License"). You may not use this file except in compliance with the
   50.13 + * License. You can obtain a copy of the License at
   50.14 + * http://www.netbeans.org/cddl-gplv2.html
   50.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   50.16 + * specific language governing permissions and limitations under the
   50.17 + * License.  When distributing the software, include this License Header
   50.18 + * Notice in each file and include the License file at
   50.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   50.20 + * particular file as subject to the "Classpath" exception as provided
   50.21 + * by Sun in the GPL Version 2 section of the License file that
   50.22 + * accompanied this code. If applicable, add the following below the
   50.23 + * License Header, with the fields enclosed by brackets [] replaced by
   50.24 + * your own identifying information:
   50.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   50.26 + *
   50.27 + * Contributor(s):
   50.28 + *
   50.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   50.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   50.31 + * Microsystems, Inc. All Rights Reserved.
   50.32 + *
   50.33 + * If you wish your version of this file to be governed by only the CDDL
   50.34 + * or only the GPL Version 2, indicate your decision by adding
   50.35 + * "[Contributor] elects to include this software in this distribution
   50.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   50.37 + * single choice of license, a recipient has the option to distribute
   50.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   50.39 + * to extend the choice of license to its licensees as provided above.
   50.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   50.41 + * Version 2 license, then the option applies only if the new code is
   50.42 + * made subject to such option by the copyright holder.
   50.43 + */
   50.44 +
   50.45 +package org.openide.util.lookup;
   50.46 +
   50.47 +import java.io.ByteArrayInputStream;
   50.48 +import java.io.ByteArrayOutputStream;
   50.49 +import java.io.ObjectInputStream;
   50.50 +import java.io.ObjectOutputStream;
   50.51 +import java.io.Serializable;
   50.52 +import java.lang.ref.WeakReference;
   50.53 +import java.lang.ref.Reference;
   50.54 +import java.util.ArrayList;
   50.55 +import java.util.Arrays;
   50.56 +import java.util.Collection;
   50.57 +import java.util.Collections;
   50.58 +import java.util.Iterator;
   50.59 +import java.util.LinkedList;
   50.60 +import java.util.List;
   50.61 +import java.util.concurrent.Executors;
   50.62 +import java.util.concurrent.TimeUnit;
   50.63 +import javax.swing.ActionMap;
   50.64 +import javax.swing.InputMap;
   50.65 +import org.netbeans.junit.NbTestCase;
   50.66 +import org.openide.util.Lookup;
   50.67 +import org.openide.util.Lookup.Template;
   50.68 +import org.openide.util.LookupEvent;
   50.69 +import org.openide.util.LookupListener;
   50.70 +
   50.71 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   50.72 +public class AbstractLookupBaseHid extends NbTestCase {
   50.73 +    private static AbstractLookupBaseHid running;
   50.74 +
   50.75 +    /** instance content to work with */
   50.76 +    InstanceContent ic;
   50.77 +    /** the lookup to work on */
   50.78 +    protected Lookup instanceLookup;
   50.79 +    /** the lookup created to work with */
   50.80 +    private Lookup lookup;
   50.81 +    /** implementation of methods that can influence the behaviour */
   50.82 +    Impl impl;
   50.83 +    
   50.84 +    protected AbstractLookupBaseHid(String testName, Impl impl) {
   50.85 +        super(testName);
   50.86 +        if (impl == null && (this instanceof Impl)) {
   50.87 +            impl = (Impl)this;
   50.88 +        }
   50.89 +        this.impl = impl;
   50.90 +    }
   50.91 +    
   50.92 +    protected @Override void setUp() {
   50.93 +        this.ic = new InstanceContent ();
   50.94 +        
   50.95 +        beforeActualTest(getName());
   50.96 +        
   50.97 +        this.instanceLookup = createInstancesLookup (ic);
   50.98 +        this.lookup = createLookup (instanceLookup);
   50.99 +        running = this;
  50.100 +    }        
  50.101 +    
  50.102 +    protected @Override void tearDown() {
  50.103 +        running = null;
  50.104 +    }
  50.105 +    
  50.106 +    /** The methods to influence test behaviour */
  50.107 +    public static interface Impl {
  50.108 +        /** Creates the initial abstract lookup.
  50.109 +         */
  50.110 +        public Lookup createInstancesLookup (InstanceContent ic);
  50.111 +        /** Creates an lookup for given lookup. This class just returns 
  50.112 +         * the object passed in, but subclasses can be different.
  50.113 +         * @param lookup in lookup
  50.114 +         * @return a lookup to use
  50.115 +         */
  50.116 +        public Lookup createLookup (Lookup lookup);
  50.117 +        
  50.118 +        /** If the impl has any caches that would prevent the system
  50.119 +         * to not garbage collect correctly, then clear them now.
  50.120 +         */
  50.121 +        public void clearCaches ();
  50.122 +    }
  50.123 +    
  50.124 +    private Lookup createInstancesLookup (InstanceContent ic) {
  50.125 +        return impl.createInstancesLookup (ic);
  50.126 +    }
  50.127 +    
  50.128 +    private Lookup createLookup (Lookup lookup) {
  50.129 +        return impl.createLookup (lookup);
  50.130 +    }
  50.131 +    
  50.132 +    /** instances that we register */
  50.133 +    private static Object[] INSTANCES = new Object[] {
  50.134 +        new Integer (10), 
  50.135 +        new Object ()
  50.136 +    };
  50.137 +    
  50.138 +    /** Test if first is really first.
  50.139 +     */
  50.140 +    public void testFirst () {
  50.141 +        Integer i1 = 1;
  50.142 +        Integer i2 = 2;
  50.143 +        
  50.144 +        ic.add (i1);
  50.145 +        ic.add (i2);
  50.146 +        
  50.147 +        Integer found = lookup.lookup(Integer.class);
  50.148 +        if (found != i1) {
  50.149 +            fail ("First object is not first: " + found + " != " + i1);
  50.150 +        }
  50.151 +        
  50.152 +        List<Integer> list = new ArrayList<Integer>();
  50.153 +        list.add (i2);
  50.154 +        list.add (i1);
  50.155 +        ic.set (list, null);
  50.156 +        
  50.157 +        found = lookup.lookup (Integer.class);
  50.158 +        if (found != i2) {
  50.159 +            fail ("Second object is not first after reorder: " + found + " != " + i2);
  50.160 +        }
  50.161 +        
  50.162 +    }
  50.163 +
  50.164 +    public void testToString() {
  50.165 +        String txt = lookup.toString();
  50.166 +        assertNotNull("Something is there", txt);
  50.167 +        assertTrue("Something2: " + txt, txt.length() > 0);
  50.168 +    }
  50.169 +
  50.170 +
  50.171 +    /** Tests ordering of items in the lookup.
  50.172 +    */
  50.173 +    public void testOrder () {
  50.174 +        addInstances (INSTANCES);
  50.175 +
  50.176 +        if (INSTANCES[0] != lookup.lookup (INSTANCES[0].getClass ())) {
  50.177 +            fail ("First object in intances not found");
  50.178 +        }
  50.179 +
  50.180 +        Iterator<?> all = lookup.lookupAll(Object.class).iterator();
  50.181 +        checkIterator ("Difference between instances added and found", all, Arrays.asList (INSTANCES));
  50.182 +    }
  50.183 +    
  50.184 +    /** Checks the reorder of items in lookup reflects the result.
  50.185 +     * Testing both classes and interfaces, because they are often treated
  50.186 +     * especially.
  50.187 +     */
  50.188 +    public void testReorder () {
  50.189 +        String s1 = "s2";
  50.190 +        String s2 = "s1";
  50.191 +        Runnable r1 = new Runnable () {
  50.192 +            public void run () {}
  50.193 +        };
  50.194 +        Runnable r2 = new Runnable () {
  50.195 +            public void run () {}
  50.196 +        };
  50.197 +        List<Object> l = new ArrayList<Object>();
  50.198 +
  50.199 +        l.add (s1);
  50.200 +        l.add (s2);
  50.201 +        l.add (r1);
  50.202 +        l.add (r2);
  50.203 +        ic.set (l, null);
  50.204 +     
  50.205 +        assertEquals ("s1 is found", s1, lookup.lookup (String.class));
  50.206 +        assertEquals ("r1 is found", r1, lookup.lookup (Runnable.class));
  50.207 +        
  50.208 +        Collections.reverse (l);
  50.209 +        
  50.210 +        ic.set (l, null);
  50.211 +        
  50.212 +        assertEquals ("s2 is found", s2, lookup.lookup (String.class));
  50.213 +        assertEquals ("r2 is found", r2, lookup.lookup (Runnable.class));
  50.214 +    }
  50.215 +    
  50.216 +    /** Tries to set empty collection to the lookup.
  50.217 +     */
  50.218 +    public void testSetEmpty () {
  50.219 +        ic.add ("A serializable string");
  50.220 +        lookup.lookup (Serializable.class);
  50.221 +        
  50.222 +        ic.set (Collections.emptyList(), null);
  50.223 +    }
  50.224 +    
  50.225 +    /** Tests a more complex reorder on nodes.
  50.226 +     */
  50.227 +    public void testComplexReorder () {
  50.228 +        Integer i1 = 1;
  50.229 +        Long i2 = 2L;
  50.230 +        
  50.231 +        List<Object> l = new ArrayList<Object>();
  50.232 +        l.add (i1);
  50.233 +        l.add (i2);
  50.234 +        ic.set (l, null);
  50.235 +        
  50.236 +        assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
  50.237 +        assertEquals ("Find long", i2, lookup.lookup (Long.class));
  50.238 +        assertEquals ("Find number", i1, lookup.lookup (Number.class));
  50.239 +        
  50.240 +        Collections.reverse (l);
  50.241 +        
  50.242 +        ic.set (l, null);
  50.243 +        
  50.244 +        assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
  50.245 +        assertEquals ("Find long", i2, lookup.lookup (Long.class));
  50.246 +        assertEquals ("Find number", i2, lookup.lookup (Number.class));
  50.247 +    }
  50.248 +    
  50.249 +    /** Checks whether setPairs keeps the order.
  50.250 +     */
  50.251 +    public void testSetPairs () {
  50.252 +        // test setPairs method
  50.253 +        List<Object> li = new ArrayList<Object>();
  50.254 +        li.addAll (Arrays.asList (INSTANCES));
  50.255 +        ic.set (li, null);
  50.256 +        
  50.257 +        Lookup.Result<Object> res = lookup.lookupResult(Object.class);
  50.258 +        Iterator<?> all = res.allInstances().iterator();
  50.259 +        checkIterator ("Original order not kept", all, li);
  50.260 +        
  50.261 +        // reverse the order
  50.262 +        Collections.reverse (li);
  50.263 +        
  50.264 +        // change the pairs
  50.265 +        LL listener = new LL (res);
  50.266 +        res.addLookupListener (listener);
  50.267 +        ic.set (li, null);
  50.268 +        if (listener.getCount () != 1) {
  50.269 +            fail ("Result has not changed even we set reversed order");
  50.270 +        }
  50.271 +        
  50.272 +        all = res.allInstances ().iterator ();
  50.273 +        checkIterator ("Reversed order not kept", all, li);
  50.274 +    }
  50.275 +
  50.276 +    /** Checks whether setPairs fires correct events.
  50.277 +     */
  50.278 +    public void testSetPairsFire () {
  50.279 +        // test setPairs method
  50.280 +        List<Object> li = new ArrayList<Object>();
  50.281 +        li.addAll (Arrays.asList (INSTANCES));
  50.282 +        ic.set (li, null);
  50.283 +        
  50.284 +        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
  50.285 +        Iterator<?> all = res.allInstances().iterator();
  50.286 +        checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
  50.287 +        
  50.288 +        // change the pairs
  50.289 +        LL listener = new LL (res);
  50.290 +        res.addLookupListener (listener);
  50.291 +
  50.292 +        List<Object> l2 = new ArrayList<Object>(li);
  50.293 +        l2.remove (INSTANCES[0]);
  50.294 +        ic.set (l2, null);
  50.295 +
  50.296 +        all = lookup.lookupAll(Object.class).iterator();
  50.297 +        checkIterator ("The removed integer is not noticed", all, l2);
  50.298 +
  50.299 +        if (listener.getCount () != 1) {
  50.300 +            fail ("Nothing has not been fired");
  50.301 +        }
  50.302 +    }
  50.303 +
  50.304 +    /** Checks whether set pairs does not fire when they should not.
  50.305 +    */
  50.306 +    public void testSetPairsDoesNotFire () {
  50.307 +        Object tmp = new Object ();
  50.308 +
  50.309 +        List<Object> li = new ArrayList<Object>();
  50.310 +        li.add (tmp);
  50.311 +        li.addAll (Arrays.asList (INSTANCES));
  50.312 +        ic.set (li, null);
  50.313 +        
  50.314 +        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
  50.315 +        Iterator<?> all = res.allInstances ().iterator ();
  50.316 +        checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
  50.317 +        
  50.318 +        // change the pairs
  50.319 +        LL listener = new LL (res);
  50.320 +        res.addLookupListener (listener);
  50.321 +
  50.322 +        List<Object> l2 = new ArrayList<Object>(li);
  50.323 +        l2.remove (tmp);
  50.324 +        ic.set (l2, null);
  50.325 +
  50.326 +        all = lookup.lookupAll(Object.class).iterator();
  50.327 +        checkIterator ("The removed integer is not noticed", all, l2);
  50.328 +
  50.329 +        if (listener.getCount () != 0) {
  50.330 +            fail ("Something has been fired");
  50.331 +        }
  50.332 +    }
  50.333 +    
  50.334 +    /** Test whether after registration it is possible to find registered objects
  50.335 +    * 
  50.336 +     */
  50.337 +    public void testLookupAndAdd () throws Exception {
  50.338 +        addInstances (INSTANCES);
  50.339 +
  50.340 +        for (int i = 0; i < INSTANCES.length; i++) {
  50.341 +            Object obj = INSTANCES[i];
  50.342 +            findAll (lookup, obj.getClass (), true);
  50.343 +        }
  50.344 +    }
  50.345 +
  50.346 +    /** Tries to find all classes and superclasses in the lookup.
  50.347 +    */
  50.348 +    private void findAll(Lookup lookup, Class<?> clazz, boolean shouldBeThere) {
  50.349 +        if (clazz == null) return;
  50.350 +
  50.351 +        Object found = lookup.lookup (clazz);
  50.352 +        if (found == null) {
  50.353 +            if (shouldBeThere) {
  50.354 +                // should find at either instance or something else, but must
  50.355 +                // find at least something
  50.356 +                fail ("Lookup (" + clazz.getName () + ") found nothing");
  50.357 +            }
  50.358 +        } else {
  50.359 +            if (!shouldBeThere) {
  50.360 +                // should find at either instance or something else, but must
  50.361 +                // find at least something
  50.362 +                fail ("Lookup (" + clazz.getName () + ") found " + found);
  50.363 +            }
  50.364 +        }
  50.365 +
  50.366 +        Lookup.Result<?> res = lookup.lookupResult(clazz);
  50.367 +        Collection<?> collection = res.allInstances();
  50.368 +
  50.369 +        for (int i = 0; i < INSTANCES.length; i++) {
  50.370 +            boolean isSubclass = clazz.isInstance (INSTANCES[i]);
  50.371 +            boolean isThere = collection.contains (INSTANCES[i]);
  50.372 +
  50.373 +            if (isSubclass != isThere) {
  50.374 +                // a problem found
  50.375 +                // should find at either instance or something else, but must
  50.376 +                // find at least something
  50.377 +                fail ("Lookup.Result (" + clazz.getName () + ") for " + INSTANCES[i] + " is subclass: " + isSubclass + " isThere: " + isThere);
  50.378 +            }
  50.379 +        }
  50.380 +
  50.381 +        // go on for superclasses
  50.382 +
  50.383 +        findAll (lookup, clazz.getSuperclass (), shouldBeThere);
  50.384 +
  50.385 +        Class[] ies = clazz.getInterfaces ();
  50.386 +        for (int i = 0; i < ies.length; i++) {
  50.387 +            findAll (lookup, ies[i], shouldBeThere);
  50.388 +        }
  50.389 +    }
  50.390 +    
  50.391 +    /** Test if it is possible to remove a registered object. */
  50.392 +    public void testRemoveRegisteredObject() {
  50.393 +        Integer inst = new Integer(10);
  50.394 +        
  50.395 +        ic.add(inst);
  50.396 +        if (lookup.lookup(inst.getClass()) == null) {
  50.397 +            // should find an instance
  50.398 +            fail("Lookup (" + inst.getClass().getName () + ") found nothing");
  50.399 +        }
  50.400 +        
  50.401 +        ic.remove(inst);
  50.402 +        if (lookup.lookup(inst.getClass()) != null) {
  50.403 +            // should NOT find an instance
  50.404 +            fail("Lookup (" + inst.getClass().getName () +
  50.405 +                ") found an instance after remove operation");
  50.406 +        }
  50.407 +    }
  50.408 +    
  50.409 +    public void testCanReturnReallyStrangeResults () throws Exception {
  50.410 +        class QueryingPair extends AbstractLookup.Pair<Object> {
  50.411 +            private Integer i = 434;
  50.412 +            
  50.413 +            //
  50.414 +            // do the test
  50.415 +            //
  50.416 +            
  50.417 +            public void doTest () throws Exception {
  50.418 +                ic.add (i);
  50.419 +                ic.addPair (this);
  50.420 +                
  50.421 +                Object found = lookup.lookup (QueryingPair.class);
  50.422 +                assertEquals ("This object is found", this, found);
  50.423 +            }
  50.424 +            
  50.425 +            
  50.426 +            //
  50.427 +            // Implementation of pair
  50.428 +            // 
  50.429 +        
  50.430 +            public String getId() {
  50.431 +                return getType ().toString();
  50.432 +            }
  50.433 +
  50.434 +            public String getDisplayName() {
  50.435 +                return getId ();
  50.436 +            }
  50.437 +
  50.438 +            public Class<?> getType() {
  50.439 +                return getClass ();
  50.440 +            }
  50.441 +
  50.442 +            protected boolean creatorOf(Object obj) {
  50.443 +                return obj == this;
  50.444 +            }
  50.445 +
  50.446 +            protected boolean instanceOf(Class<?> c) {
  50.447 +                assertEquals ("Integer found or exception is thrown", i, lookup.lookup (Integer.class));
  50.448 +                return c.isAssignableFrom(getType ());
  50.449 +            }
  50.450 +
  50.451 +            public Object getInstance() {
  50.452 +                return this;
  50.453 +            }
  50.454 +            
  50.455 +            
  50.456 +        }
  50.457 +        
  50.458 +        
  50.459 +        QueryingPair qp = new QueryingPair ();
  50.460 +        qp.doTest ();
  50.461 +    }
  50.462 +    
  50.463 +    /** Test of firing events. */
  50.464 +    public void testLookupListener() {
  50.465 +        Object inst = 10;
  50.466 +        Lookup.Result<?> res = lookup.lookupResult(inst.getClass());
  50.467 +        res.allInstances ();
  50.468 +        
  50.469 +        LL listener = new LL(res);
  50.470 +        res.addLookupListener(listener);
  50.471 +        
  50.472 +        ic.add(inst);
  50.473 +        if (listener.getCount() == 0) {
  50.474 +            fail("None event fired during NbLookup.addPair()");
  50.475 +        }
  50.476 +        
  50.477 +        ic.remove(inst);
  50.478 +        if (listener.getCount() == 0) {
  50.479 +            fail("None event fired during NbLookup.removePair()");
  50.480 +        }
  50.481 +        
  50.482 +        ic.add(inst);
  50.483 +        if (listener.getCount() == 0) {
  50.484 +            fail("None event fired during second NbLookup.addPair()");
  50.485 +        }
  50.486 +        
  50.487 +        ic.remove(inst);
  50.488 +        if (listener.getCount() == 0) {
  50.489 +            fail("None event fired during second NbLookup.removePair()");
  50.490 +        }
  50.491 +    }
  50.492 +    
  50.493 +    /** Testing identity of the lookup.
  50.494 +     */
  50.495 +    public void testId () {
  50.496 +        Lookup.Template<?> templ;
  50.497 +        int cnt;
  50.498 +        
  50.499 +        addInstances (INSTANCES);
  50.500 +        
  50.501 +        Lookup.Result<?> res = lookup.lookupResult(Object.class);
  50.502 +        for (AbstractLookup.Item<?> item : res.allItems()) {
  50.503 +            
  50.504 +            templ = new Lookup.Template<Object>(null, item.getId(), null);
  50.505 +            cnt = lookup.lookup (templ).allInstances ().size ();
  50.506 +            if (cnt != 1) {
  50.507 +                fail ("Identity lookup failed. Instances = " + cnt);
  50.508 +            }
  50.509 +
  50.510 +            templ = makeTemplate(item.getType(), item.getId());
  50.511 +            cnt = lookup.lookup (templ).allInstances ().size ();
  50.512 +            if (cnt != 1) {
  50.513 +                fail ("Identity lookup with type failed. Instances = " + cnt);
  50.514 +            }
  50.515 +            
  50.516 +            templ = makeTemplate(this.getClass(), item.getId());
  50.517 +            cnt = lookup.lookup (templ).allInstances ().size ();
  50.518 +            if (cnt != 0) {
  50.519 +                fail ("Identity lookup with wrong type failed. Instances = " + cnt);
  50.520 +            }
  50.521 +            
  50.522 +            templ = new Lookup.Template<Object>(null, null, item.getInstance());
  50.523 +            cnt = lookup.lookup (templ).allInstances ().size ();
  50.524 +            if (cnt != 1) {
  50.525 +                fail ("Instance lookup failed. Instances = " + cnt);
  50.526 +            }
  50.527 +
  50.528 +            templ = new Lookup.Template<Object>(null, item.getId(), item.getInstance());
  50.529 +            cnt = lookup.lookup (templ).allInstances ().size ();
  50.530 +            if (cnt != 1) {
  50.531 +                fail ("Instance & identity lookup failed. Instances = " + cnt);
  50.532 +            }
  50.533 +            
  50.534 +        }
  50.535 +    }
  50.536 +    private static <T> Lookup.Template<T> makeTemplate(Class<T> clazz, String id) { // captures type parameter
  50.537 +        return new Lookup.Template<T>(clazz, id, null);
  50.538 +    }
  50.539 +    
  50.540 +    /** Tests adding and removing.
  50.541 +     */
  50.542 +    public void testAddAndRemove () throws Exception {
  50.543 +        Object map = new javax.swing.ActionMap ();
  50.544 +        LL ll = new LL ();
  50.545 +        
  50.546 +        Lookup.Result<?> res = lookup.lookupResult(map.getClass());
  50.547 +        res.allItems();
  50.548 +        res.addLookupListener (ll);
  50.549 +        ll.source = res;
  50.550 +        
  50.551 +        ic.add (map);
  50.552 +        
  50.553 +        assertEquals ("First change when adding", ll.getCount (), 1);
  50.554 +        
  50.555 +        ic.remove (map);
  50.556 +        
  50.557 +        assertEquals ("Second when removing", ll.getCount (), 1);
  50.558 +        
  50.559 +        ic.add (map);
  50.560 +        
  50.561 +        assertEquals ("Third when readding", ll.getCount (), 1);
  50.562 +        
  50.563 +        ic.remove (map);
  50.564 +        
  50.565 +        assertEquals ("Forth when reremoving", ll.getCount (), 1);
  50.566 +        
  50.567 +    }
  50.568 +    
  50.569 +    /** Will a class garbage collect even it is registered in lookup.
  50.570 +     */
  50.571 +    public void testGarbageCollect () throws Exception {
  50.572 +        ClassLoader l = new CL ();
  50.573 +        Class<?> c = l.loadClass(Garbage.class.getName());
  50.574 +        Reference<?> ref = new WeakReference<Object>(c);
  50.575 +
  50.576 +        lookup.lookup (c);
  50.577 +        
  50.578 +        // now test garbage collection
  50.579 +        c = null;
  50.580 +        l = null;
  50.581 +        impl.clearCaches ();
  50.582 +        assertGC ("The classloader has not been garbage collected!", ref);
  50.583 +    }
  50.584 +                
  50.585 +    /** Items are the same as results.
  50.586 +     */
  50.587 +    public void testItemsAndIntances () {
  50.588 +        addInstances (INSTANCES);
  50.589 +        
  50.590 +        Lookup.Result<Object> r = lookup.lookupResult(Object.class);
  50.591 +        Collection<? extends Lookup.Item<?>> items = r.allItems();
  50.592 +        Collection<?> insts = r.allInstances();
  50.593 +        
  50.594 +        if (items.size () != insts.size ()) {
  50.595 +            fail ("Different size of sets");
  50.596 +        }
  50.597 +
  50.598 +        for (Lookup.Item<?> item : items) {
  50.599 +            if (!insts.contains (item.getInstance ())) {
  50.600 +                fail ("Intance " + item.getInstance () + " is missing in " + insts);
  50.601 +            }
  50.602 +        }
  50.603 +    }
  50.604 +    
  50.605 +    /** Checks search for interface.
  50.606 +     */
  50.607 +    public void testSearchForInterface () {
  50.608 +        Lookup.Template<Serializable> t = new Lookup.Template<Serializable>(Serializable.class, null, null);
  50.609 +        
  50.610 +        assertNull("Nothing to find", lookup.lookupItem (t));
  50.611 +        
  50.612 +        Serializable s = new Serializable () {};
  50.613 +        ic.add (s);
  50.614 +        
  50.615 +        Lookup.Item item = lookup.lookupItem (t);
  50.616 +        assertNotNull ("Something found", item);
  50.617 +    }
  50.618 +
  50.619 +    /** Test to add broken item if it incorrectly answers instanceOf questions.
  50.620 +     */
  50.621 +    public void testIncorectInstanceOf40364 () {
  50.622 +        final Long sharedLong = new Long (0);
  50.623 +        
  50.624 +        class P extends AbstractLookup.Pair<Object> {
  50.625 +            public boolean isLong;
  50.626 +            
  50.627 +            P (boolean b) {
  50.628 +                isLong = b;
  50.629 +            }
  50.630 +            
  50.631 +            protected boolean creatorOf (Object obj) {
  50.632 +                return obj == sharedLong;
  50.633 +            }
  50.634 +            
  50.635 +            public String getDisplayName () {
  50.636 +                return "";
  50.637 +            }
  50.638 +            
  50.639 +            public String getId () {
  50.640 +                return "";
  50.641 +            }
  50.642 +            
  50.643 +            public Object getInstance () {
  50.644 +                return sharedLong;
  50.645 +            }
  50.646 +            
  50.647 +            public Class<?> getType() {
  50.648 +                return isLong ? Long.class : Number.class;
  50.649 +            }
  50.650 +            
  50.651 +            protected boolean instanceOf(Class<?> c) {
  50.652 +                return c.isAssignableFrom (getType ());
  50.653 +            }
  50.654 +    
  50.655 +            public @Override int hashCode() {
  50.656 +                return getClass ().hashCode ();
  50.657 +            }    
  50.658 +
  50.659 +            public @Override boolean equals(Object obj) {
  50.660 +                return obj != null && getClass ().equals (obj.getClass ());
  50.661 +            }
  50.662 +        }
  50.663 +        
  50.664 +        // to create the right structure in the lookup
  50.665 +        lookup.lookup (Object.class);
  50.666 +        lookup.lookup (Long.class);
  50.667 +        lookup.lookup (Number.class);
  50.668 +        
  50.669 +        P lng1 = new P (true);
  50.670 +        ic.addPair (lng1);
  50.671 +
  50.672 +        P lng2 = new P (false);
  50.673 +        ic.setPairs (Collections.singleton (lng2));
  50.674 +        
  50.675 +        Collection<? extends Lookup.Item<?>> res = lookup.lookupResult(Object.class).allItems();
  50.676 +        assertEquals ("Just one pair", 1, res.size ());
  50.677 +    }
  50.678 +
  50.679 +    public void testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly () throws Exception {
  50.680 +        class X implements TestInterfaceInheritanceA, TestInterfaceInheritanceB {
  50.681 +        }
  50.682 +        final X shared = new X ();
  50.683 +        
  50.684 +        class P extends AbstractLookup.Pair<Object> {
  50.685 +            public int howLong;
  50.686 +            
  50.687 +            P (int b) {
  50.688 +                howLong = b;
  50.689 +            }
  50.690 +            
  50.691 +            protected boolean creatorOf (Object obj) {
  50.692 +                return obj == shared;
  50.693 +            }
  50.694 +            
  50.695 +            public String getDisplayName () {
  50.696 +                return "";
  50.697 +            }
  50.698 +            
  50.699 +            public String getId () {
  50.700 +                return "";
  50.701 +            }
  50.702 +            
  50.703 +            public Object getInstance () {
  50.704 +                return shared;
  50.705 +            }
  50.706 +            
  50.707 +            public Class<?> getType() {
  50.708 +                return howLong == 0 ? TestInterfaceInheritanceB.class : TestInterfaceInheritanceA.class;
  50.709 +            }
  50.710 +            
  50.711 +            protected boolean instanceOf(Class<?> c) {
  50.712 +                return c.isAssignableFrom (getType ());
  50.713 +            }
  50.714 +    
  50.715 +            public @Override int hashCode() {
  50.716 +                return getClass ().hashCode ();
  50.717 +            }    
  50.718 +
  50.719 +            public @Override boolean equals(Object obj) {
  50.720 +                if (obj instanceof P) {
  50.721 +                    P p = (P)obj;
  50.722 +                    if (this.howLong > 0) {
  50.723 +                        this.howLong--;
  50.724 +                        return false;
  50.725 +                    }
  50.726 +                    if (p.howLong > 0) {
  50.727 +                        p.howLong--;
  50.728 +                        return false;
  50.729 +                    }
  50.730 +                    return getClass ().equals (p.getClass ());
  50.731 +                }
  50.732 +                return false;
  50.733 +            }
  50.734 +        }
  50.735 +        
  50.736 +        // to create the right structure in the lookup
  50.737 +        Lookup.Result<?> a = lookup.lookupResult(TestInterfaceInheritanceA.class);
  50.738 +        Lookup.Result<?> b = lookup.lookupResult(TestInterfaceInheritanceB.class);
  50.739 +        
  50.740 +        P lng1 = new P (0);
  50.741 +        ic.addPair (lng1);
  50.742 +        
  50.743 +        assertEquals ("One in a", 1, a.allItems ().size ());
  50.744 +        assertEquals ("One in b", 1, b.allItems ().size ());
  50.745 +
  50.746 +        P lng2 = new P (1);
  50.747 +        
  50.748 +
  50.749 +        /* Following call used to generate this exception:
  50.750 +    java.lang.IllegalStateException: Duplicate pair in treePair1:  pair2:  index1: 0 index2: 0 item1: org.openide.util.lookup.AbstractLookupBaseHid$1X@1a457b6 item2: org.openide.util.lookup.AbstractLookupBaseHid$1X@1a457b6 id1: 7a78d3 id2: 929206
  50.751 +	at org.openide.util.lookup.ALPairComparator.compare(ALPairComparator.java:52)
  50.752 +	at java.util.Arrays.mergeSort(Arrays.java:1284)
  50.753 +	at java.util.Arrays.sort(Arrays.java:1223)
  50.754 +	at java.util.Collections.sort(Collections.java:159)
  50.755 +	at org.openide.util.lookup.InheritanceTree.retainAllInterface(InheritanceTree.java:753)
  50.756 +	at org.openide.util.lookup.InheritanceTree.retainAll(InheritanceTree.java:183)
  50.757 +	at org.openide.util.lookup.DelegatingStorage.retainAll(DelegatingStorage.java:83)
  50.758 +	at org.openide.util.lookup.AbstractLookup.setPairsAndCollectListeners(AbstractLookup.java:238)
  50.759 +	at org.openide.util.lookup.AbstractLookup.setPairs(AbstractLookup.java:203)
  50.760 +	at org.openide.util.lookup.AbstractLookup$Content.setPairs(AbstractLookup.java:885)
  50.761 +	at org.openide.util.lookup.AbstractLookupBaseHid.testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly(AbstractLookupBaseHid.java:696)
  50.762 +	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  50.763 +	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  50.764 +	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  50.765 +	at org.netbeans.junit.NbTestCase.run(NbTestCase.java:119)
  50.766 +    */  
  50.767 +        ic.setPairs (Collections.singleton (lng2));
  50.768 +
  50.769 +        
  50.770 +    }
  50.771 +    
  50.772 +    public void testInstancesArePreservedFoundWhenFixing48590 () throws Exception {
  50.773 +        class X implements Runnable, Serializable {
  50.774 +            public void run () {
  50.775 +                
  50.776 +            }
  50.777 +            
  50.778 +            public void assertOnlyMe (String msg, Lookup.Result<?> res) {
  50.779 +                Collection<?> col = res.allInstances();
  50.780 +                assertEquals (msg + " just one", 1, col.size ());
  50.781 +                assertSame (msg + " and it is me", this, col.iterator ().next ());
  50.782 +            }
  50.783 +        }
  50.784 +        
  50.785 +        Lookup.Result<?> runnable = lookup.lookupResult(Runnable.class);
  50.786 +        Lookup.Result<?> serial = lookup.lookupResult(Serializable.class);
  50.787 +        
  50.788 +        
  50.789 +        X x = new X ();
  50.790 +        ic.add (x);
  50.791 +        
  50.792 +        
  50.793 +        x.assertOnlyMe ("x implements it (1)", runnable);
  50.794 +        x.assertOnlyMe ("x implements it (2)", serial);
  50.795 +        
  50.796 +        ic.set (Collections.singleton (x), null);
  50.797 +        
  50.798 +        x.assertOnlyMe ("x implements it (3)", runnable);
  50.799 +        x.assertOnlyMe ("x implements it (4)", serial);
  50.800 +    }
  50.801 +    
  50.802 +    /** Testing lookup of inherited classes. */
  50.803 +    public void testInheritance() {
  50.804 +        class A {}
  50.805 +        class B extends A implements java.rmi.Remote {}
  50.806 +        class BB extends B {}
  50.807 +        class C extends A implements java.rmi.Remote {}
  50.808 +        class D extends A {}
  50.809 +        
  50.810 +        A[] types = {new B(), new BB(), new C(), new D()};
  50.811 +        
  50.812 +        for (int i = 0; i < types.length; i++) {
  50.813 +            ic.add(types[i]);
  50.814 +            if (lookup.lookup(types[i].getClass()) == null) {
  50.815 +                // should find an instance
  50.816 +                fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
  50.817 +            }
  50.818 +        }
  50.819 +        
  50.820 +        int size1, size2;
  50.821 +        
  50.822 +        //interface query
  50.823 +        size1 = lookup.lookupAll(java.rmi.Remote.class).size();
  50.824 +        size2 = countInstances(types, java.rmi.Remote.class);
  50.825 +        
  50.826 +        if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
  50.827 +        
  50.828 +        // superclass query
  50.829 +        size1 = lookup.lookupAll(A.class).size();
  50.830 +        size2 = countInstances(types, A.class);
  50.831 +        
  50.832 +        if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
  50.833 +    }
  50.834 +    
  50.835 +    /** Test interface inheritance.
  50.836 +     */
  50.837 +    public void testInterfaceInheritance() {
  50.838 +        TestInterfaceInheritanceA[] types = {
  50.839 +            new TestInterfaceInheritanceB() {},
  50.840 +            new TestInterfaceInheritanceBB() {},
  50.841 +            new TestInterfaceInheritanceC() {},
  50.842 +            new TestInterfaceInheritanceD() {}
  50.843 +        };
  50.844 +        
  50.845 +        for (int i = 0; i < types.length; i++) {
  50.846 +            ic.add(types[i]);
  50.847 +            if (lookup.lookup(types[i].getClass()) == null) {
  50.848 +                // should find an instance
  50.849 +                fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
  50.850 +            }
  50.851 +        }
  50.852 +        
  50.853 +        int size1, size2;
  50.854 +        
  50.855 +        //interface query
  50.856 +        LL l = new LL ();
  50.857 +        Lookup.Result<?> res = lookup.lookupResult(java.rmi.Remote.class);
  50.858 +        l.source = res;
  50.859 +        size1 = res.allInstances().size();
  50.860 +        size2 = countInstances(types, java.rmi.Remote.class);
  50.861 +        
  50.862 +        if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
  50.863 +        
  50.864 +        // superclass query
  50.865 +        size1 = lookup.lookupAll(TestInterfaceInheritanceA.class).size();
  50.866 +        size2 = countInstances(types, TestInterfaceInheritanceA.class);
  50.867 +        
  50.868 +        if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
  50.869 +        
  50.870 +        res.addLookupListener (l);
  50.871 +        ic.remove (types[0]);
  50.872 +        
  50.873 +        if (l.getCount () != 1) {
  50.874 +            fail ("No notification that a Remote is removed");
  50.875 +        }
  50.876 +    }
  50.877 +    
  50.878 +    /** Checks whether the AbstractLookup is guarded against modifications
  50.879 +     * while doing some kind of modification.
  50.880 +     */
  50.881 +    public void testModificationArePreventedWhenDoingModifications () throws Exception {
  50.882 +        BrokenPair broken = new BrokenPair (true, false);
  50.883 +        ic.addPair (broken);
  50.884 +        
  50.885 +        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
  50.886 +        Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
  50.887 +        assertEquals ("Broken is found", broken, item);
  50.888 +    }
  50.889 +    
  50.890 +    public void testModificationArePreventedWhenDoingModificationsResult () throws Exception {
  50.891 +        BrokenPair broken = new BrokenPair (false, true);
  50.892 +        ic.addPair (broken);
  50.893 +        
  50.894 +        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
  50.895 +        
  50.896 +        Collection<? extends BrokenPair> c = lookup.lookup (templ).allInstances();
  50.897 +        assertEquals ("One item", 1, c.size ());
  50.898 +        assertEquals ("Broken is found again", broken, c.iterator().next ());
  50.899 +    }
  50.900 +    
  50.901 +    public void testModificationArePreventedWhenDoingModificationsItemAndResult () throws Exception {
  50.902 +        BrokenPair broken = new BrokenPair (false, true);
  50.903 +        ic.addPair (broken);
  50.904 +        
  50.905 +        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
  50.906 +        Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
  50.907 +        assertEquals ("Broken is found", broken, item);
  50.908 +        
  50.909 +        Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
  50.910 +        assertEquals ("One item", 1, c.size ());
  50.911 +        assertEquals ("Broken is found again", broken, c.iterator().next ());
  50.912 +    }
  50.913 +
  50.914 +    public void testModificationArePreventedWhenDoingModificationsResultAndItem () throws Exception {
  50.915 +        BrokenPair broken = new BrokenPair (false, true);
  50.916 +        ic.addPair (broken);
  50.917 +        
  50.918 +        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
  50.919 +        Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
  50.920 +        assertEquals ("One item", 1, c.size ());
  50.921 +        assertEquals ("Broken is found again", broken, c.iterator().next ());
  50.922 +        
  50.923 +        Object item = lookup.lookupItem (templ);
  50.924 +        assertEquals ("Broken is found", broken, item);
  50.925 +    }
  50.926 +    
  50.927 +    public void testAddALotOfPairsIntoTheLookupOneByOne () throws Exception {
  50.928 +        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
  50.929 +        for (int i = 0; i < 1000; i++) {
  50.930 +            ic.add(i);
  50.931 +        }
  50.932 +        assertEquals (
  50.933 +            "there is the right count", 
  50.934 +            1000, 
  50.935 +            res.allItems().size ()
  50.936 +        );
  50.937 +    }
  50.938 +    
  50.939 +    public void testAddALotOfPairsIntoTheLookup () throws Exception {
  50.940 +        List<Integer> arr = new ArrayList<Integer>();
  50.941 +        for (int i = 0; i < 1000; i++) {
  50.942 +            arr.add(i);
  50.943 +        }
  50.944 +        ic.set (arr, null);
  50.945 +        
  50.946 +        assertEquals (
  50.947 +            "there is the right count", 
  50.948 +            1000, 
  50.949 +            lookup.lookupResult(Integer.class).allItems().size()
  50.950 +        );
  50.951 +    }
  50.952 +
  50.953 +    
  50.954 +    public void testDoubleAddIssue35274 () throws Exception {
  50.955 +        class P extends AbstractLookup.Pair<Object> {
  50.956 +            protected boolean creatorOf(Object obj) { return false; }
  50.957 +            public String getDisplayName() { return ""; }
  50.958 +            public String getId() { return ""; }
  50.959 +            public Object getInstance() { return null; }
  50.960 +            public Class<?> getType() { return Object.class; }
  50.961 +            protected boolean instanceOf(Class<?> c) { return c.isAssignableFrom(getType ()); }
  50.962 +            public @Override int hashCode() {return getClass().hashCode();}
  50.963 +            public @Override boolean equals(Object obj) {return getClass() == obj.getClass();}
  50.964 +        }
  50.965 +        
  50.966 +        P p = new P ();
  50.967 +        
  50.968 +        ic.addPair (p);
  50.969 +        ic.addPair (p);
  50.970 +        
  50.971 +        Lookup.Result<Object> result = lookup.lookupResult(Object.class);
  50.972 +        Collection res = result.allItems ();
  50.973 +        assertEquals ("One item there", 1, res.size ());
  50.974 +        assertTrue ("It is the p", p == res.iterator ().next ());
  50.975 +        
  50.976 +        P p2 = new P ();
  50.977 +        ic.addPair (p2);
  50.978 +        
  50.979 +        Reference<?> ref = new WeakReference<Object>(result);
  50.980 +        result = null;
  50.981 +        assertGC ("The result can disappear", ref);
  50.982 +        
  50.983 +        impl.clearCaches ();
  50.984 +        
  50.985 +        result = lookup.lookupResult(Object.class);
  50.986 +        res = result.allItems ();
  50.987 +        assertEquals ("One item is still there", 1, res.size ());
  50.988 +        assertTrue ("But the p2 replaced p", p2 == res.iterator ().next ());
  50.989 +        
  50.990 +    }
  50.991 +    
  50.992 +    /** Test for proper serialization.
  50.993 +     */
  50.994 +    public void testSerializationSupport () throws Exception {
  50.995 +        doSerializationSupport (1);
  50.996 +    }
  50.997 +    public void testDoubleSerializationSupport () throws Exception {
  50.998 +        doSerializationSupport (2);
  50.999 +    }
 50.1000 +
 50.1001 +    private void doSerializationSupport (int count) throws Exception {
 50.1002 +        if (lookup instanceof Serializable) {
 50.1003 +            ic.addPair (new SerialPair ("1"));
 50.1004 +            ic.addPair (new SerialPair ("2"));
 50.1005 +            ic.addPair (new SerialPair ("3"));
 50.1006 +
 50.1007 +            Lookup l = (Lookup)reserialize(lookup);
 50.1008 +
 50.1009 +            assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
 50.1010 +
 50.1011 +            assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
 50.1012 +
 50.1013 +            while (count-- > 0) {
 50.1014 +                l = (Lookup)reserialize(l);
 50.1015 +            }
 50.1016 +
 50.1017 +            assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
 50.1018 +
 50.1019 +            assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
 50.1020 +        }
 50.1021 +    }
 50.1022 +
 50.1023 +    /** When a lookup with two different versions of the same class 
 50.1024 +     * get's serialized, the results may be very bad. 
 50.1025 +     */
 50.1026 +    public void testSerializationOfTwoClassesWithTheSameName () throws Exception {
 50.1027 +        if (lookup instanceof Serializable) {
 50.1028 +            doTwoSerializedClasses (false, false);
 50.1029 +        }
 50.1030 +    }
 50.1031 +    public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSave () throws Exception {
 50.1032 +        if (lookup instanceof Serializable) {
 50.1033 +            doTwoSerializedClasses (true, false);
 50.1034 +        }
 50.1035 +    }
 50.1036 +    public void testSerializationOfTwoClassesWithTheSameNameWithBroken () throws Exception {
 50.1037 +        if (lookup instanceof Serializable) {
 50.1038 +            doTwoSerializedClasses (false, true);
 50.1039 +        }
 50.1040 +    }
 50.1041 +    public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSaveWithBroken () throws Exception {
 50.1042 +        if (lookup instanceof Serializable) {
 50.1043 +            doTwoSerializedClasses (true, true);
 50.1044 +        }
 50.1045 +    }
 50.1046 +   
 50.1047 +    private void doTwoSerializedClasses (boolean queryBeforeSerialization, boolean useBroken) throws Exception {
 50.1048 +        ClassLoader loader = new CL ();
 50.1049 +        Class c = loader.loadClass (Garbage.class.getName ());
 50.1050 +
 50.1051 +        // in case of InheritanceTree it creates a slot for class Garbage
 50.1052 +        lookup.lookup(c);
 50.1053 +
 50.1054 +        // but creates new instance and adds it into the lookup
 50.1055 +        // without querying for it
 50.1056 +        loader = new CL ();
 50.1057 +        c = loader.loadClass (Garbage.class.getName ());
 50.1058 +
 50.1059 +        Object theInstance = c.newInstance ();
 50.1060 +
 50.1061 +        ic.addPair (new SerialPair (theInstance));
 50.1062 +
 50.1063 +        Broken2Pair broken = null;
 50.1064 +        if (useBroken) {
 50.1065 +            broken = new Broken2Pair ();
 50.1066 +            ic.addPair (broken);
 50.1067 +            
 50.1068 +            assertNull (
 50.1069 +                "We need to create the slot for the List as " +
 50.1070 +                "the Broken2Pair will ask for it after deserialization", 
 50.1071 +                lookup.lookup (java.awt.List.class)
 50.1072 +            );
 50.1073 +        }
 50.1074 +
 50.1075 +        if (queryBeforeSerialization) {
 50.1076 +            assertEquals ("Instance is found", theInstance, lookup.lookup (c));
 50.1077 +        }
 50.1078 +        
 50.1079 +        // replace the old lookup with new one
 50.1080 +        lookup = (Lookup)reserialize(lookup);
 50.1081 +        
 50.1082 +        Lookup.Result result = lookup.lookup (new Lookup.Template (Garbage.class));
 50.1083 +        assertEquals ("One item is the result", 1, result.allInstances ().size ());
 50.1084 +        Object r = result.allInstances ().iterator ().next ();
 50.1085 +        assertNotNull("A value is found", r);
 50.1086 +        assertEquals ("It is of the right class", Garbage.class, r.getClass());
 50.1087 +    }
 50.1088 +   
 50.1089 +    /** Test of reorder and item change which used to fail on interfaces.
 50.1090 +     */
 50.1091 +    public void testReoderingIssue13779 () throws Exception {
 50.1092 +        LinkedList arr = new LinkedList ();
 50.1093 +        
 50.1094 +        class R extends Exception implements Cloneable {
 50.1095 +        }
 50.1096 +        Object o1 = new R ();
 50.1097 +        Object o2 = new R ();
 50.1098 +        Object o3 = new R ();
 50.1099 +        
 50.1100 +        arr.add (o1);
 50.1101 +        arr.add (o2);
 50.1102 +        
 50.1103 +        ic.set (arr, null);
 50.1104 +        
 50.1105 +        Lookup.Result objectResult = lookup.lookup (new Lookup.Template (Exception.class));
 50.1106 +        Lookup.Result interfaceResult = lookup.lookup (new Lookup.Template (Cloneable.class));
 50.1107 +        objectResult.allItems ();
 50.1108 +        interfaceResult.allItems ();
 50.1109 +        
 50.1110 +        LL l1 = new LL (objectResult);
 50.1111 +        LL l2 = new LL (interfaceResult);
 50.1112 +        
 50.1113 +        objectResult.addLookupListener(l1);
 50.1114 +        interfaceResult.addLookupListener(l2);
 50.1115 +        
 50.1116 +        arr.addFirst (o3);
 50.1117 +        
 50.1118 +        ic.set (arr, null);
 50.1119 +        
 50.1120 +        assertEquals ("One change on objects", 1, l1.getCount ());
 50.1121 +        assertEquals ("One change on interfaces", 1, l2.getCount ());
 50.1122 +        
 50.1123 +        arr.addFirst (new Cloneable () { });
 50.1124 +        ic.set (arr, null);
 50.1125 +        
 50.1126 +        assertEquals ("No change on objects", 0, l1.getCount ());
 50.1127 +        assertEquals ("But one change on interfaces", 1, l2.getCount ());
 50.1128 +        
 50.1129 +    }
 50.1130 +    
 50.1131 +    public void testDeadlockBetweenProxyResultAndLookupIssue47772 () throws Exception {
 50.1132 +        final String myModule = "My Module";
 50.1133 +        ic.add (myModule);
 50.1134 +        
 50.1135 +        class MyProxy extends ProxyLookup {
 50.1136 +            public MyProxy () {
 50.1137 +                super (new Lookup[] { lookup });
 50.1138 +            }
 50.1139 +        }
 50.1140 +        final MyProxy my = new MyProxy ();
 50.1141 +        
 50.1142 +        final Lookup.Result allModules = my.lookup (new Lookup.Template (String.class));
 50.1143 +        
 50.1144 +        class PairThatNeedsInfoAboutModules extends AbstractLookup.Pair {
 50.1145 +            public String getDisplayName () {
 50.1146 +                return "Need a module";
 50.1147 +            }
 50.1148 +            public String getId () {
 50.1149 +                return getDisplayName ();
 50.1150 +            }
 50.1151 +            public Class getType () {
 50.1152 +                return Integer.class;
 50.1153 +            }
 50.1154 +            protected boolean instanceOf (Class c) {
 50.1155 +                if (c == Integer.class) {
 50.1156 +                    synchronized (this) {
 50.1157 +                        notifyAll ();
 50.1158 +                        try {
 50.1159 +                            wait (1000);
 50.1160 +                        } catch (InterruptedException ex) {
 50.1161 +                            fail (ex.getMessage ());
 50.1162 +                        }
 50.1163 +                    }
 50.1164 +                    java.util.Collection coll = allModules.allInstances ();
 50.1165 +                    assertEquals ("Size is 1", 1, coll.size ());
 50.1166 +                    assertEquals ("My module is there", myModule, coll.iterator ().next ());
 50.1167 +                }
 50.1168 +                return c.isAssignableFrom (Integer.class);
 50.1169 +            }
 50.1170 +            
 50.1171 +            public Object getInstance () {
 50.1172 +                return new Integer (10);
 50.1173 +            }
 50.1174 +            
 50.1175 +            protected boolean creatorOf (Object obj) {
 50.1176 +                return new Integer (10).equals (obj);
 50.1177 +            }
 50.1178 +        }
 50.1179 +        
 50.1180 +        PairThatNeedsInfoAboutModules pair = new PairThatNeedsInfoAboutModules ();
 50.1181 +        ic.addPair (pair);
 50.1182 +        
 50.1183 +        synchronized (pair) {
 50.1184 +            class BlockInInstanceOf implements Runnable {
 50.1185 +                public void run () {
 50.1186 +                    Integer i = my.lookup(Integer.class);
 50.1187 +                    assertEquals (new Integer (10), i);
 50.1188 +                }
 50.1189 +            }
 50.1190 +            BlockInInstanceOf blk = new BlockInInstanceOf ();
 50.1191 +            Executors.newSingleThreadScheduledExecutor().schedule(blk, 0, TimeUnit.MICROSECONDS);
 50.1192 +            pair.wait ();
 50.1193 +        }
 50.1194 +        
 50.1195 +        java.util.Collection coll = allModules.allInstances ();
 50.1196 +        assertEquals ("Size is 1", 1, coll.size ());
 50.1197 +        assertEquals ("My module is there", myModule, coll.iterator ().next ());
 50.1198 +    }
 50.1199 +
 50.1200 +    public void testAWayToGenerateProblem13779 () {
 50.1201 +        ic.add (new Integer (1));
 50.1202 +        ic.add (new Integer (2));
 50.1203 +        ic.add (new Integer (1));
 50.1204 +        ic.add (new Integer (2));
 50.1205 +        
 50.1206 +        Collection c = lookup.lookup (new Lookup.Template (Integer.class)).allInstances ();
 50.1207 +        assertEquals ("There are two objects", 2, c.size ());
 50.1208 +        
 50.1209 +    }
 50.1210 +    
 50.1211 +    /** Replacing items with different objects.
 50.1212 +     */
 50.1213 +    public void testReplacingObjectsDoesNotGenerateException () throws Exception {
 50.1214 +        LinkedList arr = new LinkedList ();
 50.1215 +        
 50.1216 +        class R extends Exception implements Cloneable {
 50.1217 +        }
 50.1218 +        arr.add (new R ());
 50.1219 +        arr.add (new R ());
 50.1220 +        
 50.1221 +        ic.set (arr, null);
 50.1222 +        
 50.1223 +        arr.clear();
 50.1224 +        
 50.1225 +        arr.add (new R ());
 50.1226 +        arr.add (new R ());
 50.1227 +        
 50.1228 +        ic.set (arr, null);
 50.1229 +    }
 50.1230 +
 50.1231 +    public void testAfterDeserializationNoQueryIsPeformedOnAlreadyQueriedObjects() throws Exception {
 50.1232 +        if (! (lookup instanceof Serializable)) {
 50.1233 +            // well this test works only for serializable lookups
 50.1234 +            return;
 50.1235 +        }
 50.1236 +        
 50.1237 +        SerialPair my = new SerialPair ("no");
 50.1238 +        ic.addPair (my);
 50.1239 +        
 50.1240 +        Lookup.Result res = lookup.lookup (new Lookup.Template (String.class));
 50.1241 +        assertEquals ("One instance", 1, res.allInstances().size ());
 50.1242 +        assertEquals ("my.instanceOf called once", 1, my.countInstanceOf);
 50.1243 +        
 50.1244 +        Lookup serial = (Lookup)reserialize(lookup);
 50.1245 +        
 50.1246 +        Lookup.Result r2 = serial.lookup(new Lookup.Template(String.class));
 50.1247 +        
 50.1248 +        assertEquals ("One item", 1, r2.allItems ().size ());
 50.1249 +        Object one = r2.allItems().iterator().next ();
 50.1250 +        assertEquals ("The right class", SerialPair.class, one.getClass());
 50.1251 +        SerialPair p = (SerialPair)one;
 50.1252 +        
 50.1253 +        assertEquals ("p.instanceOf has not been queried", 0, p.countInstanceOf);
 50.1254 +    }
 50.1255 +    
 50.1256 +    /** Checks the iterator */
 50.1257 +    private <T> void checkIterator(String msg, Iterator<? extends T> it1, List<? extends T> list) {
 50.1258 +        int cnt = 0;
 50.1259 +        Iterator<? extends T> it2 = list.iterator();
 50.1260 +        while (it1.hasNext () && it2.hasNext ()) {
 50.1261 +            T n1 = it1.next();
 50.1262 +            T n2 = it2.next();
 50.1263 +            
 50.1264 +            if (n1 != n2) {
 50.1265 +                fail (msg + " iterator[" + cnt + "] = " + n1 + " but list[" + cnt + "] = " + n2);
 50.1266 +            }
 50.1267 +            
 50.1268 +            cnt++;
 50.1269 +        }
 50.1270 +        
 50.1271 +        if (it1.hasNext ()) {
 50.1272 +            fail ("Iterator has more elements than list");
 50.1273 +        }
 50.1274 +        
 50.1275 +        if (it2.hasNext ()) {
 50.1276 +            fail ("List has more elements than iterator");
 50.1277 +        }
 50.1278 +    }
 50.1279 +    
 50.1280 +    
 50.1281 +    public void testResultsAreUnmodifyableOrAtLeastTheyDoNotPropagateToCache() throws Exception {
 50.1282 +        String s = "Ahoj";
 50.1283 +        
 50.1284 +        ic.add(s);
 50.1285 +        
 50.1286 +        Lookup.Result res = lookup.lookup(new Template(String.class));
 50.1287 +        
 50.1288 +        for (int i = 1; i < 5; i++) {
 50.1289 +            Collection c1 = res.allInstances();
 50.1290 +            Collection c2 = res.allClasses();
 50.1291 +            Collection c3 = res.allItems();
 50.1292 +
 50.1293 +            assertTrue(i + ": c1 has it", c1.contains(s));
 50.1294 +            assertTrue(i + ": c2 has it", c2.contains(s.getClass()));
 50.1295 +            assertEquals(i + ": c3 has one", 1, c3.size());
 50.1296 +            Lookup.Item item = (Lookup.Item) c3.iterator().next();
 50.1297 +            assertEquals(i + ": c3 has it", s, item.getInstance());
 50.1298 +
 50.1299 +            try {
 50.1300 +                c1.remove(s);
 50.1301 +                assertEquals("No elements now", 0, c1.size());
 50.1302 +            } catch (UnsupportedOperationException ex) {
 50.1303 +                // ok, this need not be supported
 50.1304 +            }
 50.1305 +            try {
 50.1306 +                c2.remove(s.getClass());
 50.1307 +                assertEquals("No elements now", 0, c2.size());
 50.1308 +            } catch (UnsupportedOperationException ex) {
 50.1309 +                // ok, this need not be supported
 50.1310 +            }
 50.1311 +            try {
 50.1312 +                c3.remove(item);
 50.1313 +                assertEquals("No elements now", 0, c3.size());
 50.1314 +            } catch (UnsupportedOperationException ex) {
 50.1315 +                // ok, this need not be supported
 50.1316 +            }
 50.1317 +        }
 50.1318 +    }
 50.1319 +    
 50.1320 +    public void testSomeProblemWithDVBFrameworkSeemsToBeInLookup() {
 50.1321 +        for (int i = 0; i < 5; i++) {
 50.1322 +            ic.add(lookup);
 50.1323 +            assertEquals("Can be found", lookup, lookup.lookup(lookup.getClass()));
 50.1324 +            ic.set(Collections.EMPTY_LIST, null);
 50.1325 +        }        
 50.1326 +    }
 50.1327 +
 50.1328 +    public void testListeningAndQueryingByTwoListenersInstances() {
 50.1329 +        doListeningAndQueryingByTwoListeners(0);
 50.1330 +    }
 50.1331 +    public void testListeningAndQueryingByTwoListenersClasses() {
 50.1332 +        doListeningAndQueryingByTwoListeners(1);        
 50.1333 +    }
 50.1334 +    public void testListeningAndQueryingByTwoListenersItems() {
 50.1335 +        doListeningAndQueryingByTwoListeners(2);
 50.1336 +    }
 50.1337 +    
 50.1338 +    
 50.1339 +    private void doListeningAndQueryingByTwoListeners(final int type) {
 50.1340 +        class L implements LookupListener {
 50.1341 +            Lookup.Result integer = lookup.lookup(new Template(Integer.class));
 50.1342 +            Lookup.Result number = lookup.lookup(new Template(Number.class));
 50.1343 +            Lookup.Result serial = lookup.lookup(new Template(Serializable.class));
 50.1344 +            
 50.1345 +            {
 50.1346 +                integer.addLookupListener(this);
 50.1347 +                number.addLookupListener(this);
 50.1348 +                serial.addLookupListener(this);
 50.1349 +            }
 50.1350 +            
 50.1351 +            int round;
 50.1352 +            
 50.1353 +            public void resultChanged(LookupEvent ev) {
 50.1354 +                Collection c1 = get(type, integer);
 50.1355 +                Collection c2 = get(type, number);
 50.1356 +                Collection c3 = get(type, serial);
 50.1357 +                
 50.1358 +                assertEquals("round " + round + " c1 vs. c2", c1, c2);
 50.1359 +                assertEquals("round " + round + " c1 vs. c3", c1, c3);
 50.1360 +                assertEquals("round " + round + " c2 vs. c3", c2, c3);
 50.1361 +                
 50.1362 +                round++;
 50.1363 +            }            
 50.1364 +
 50.1365 +            private Collection get(int type, Lookup.Result res) {
 50.1366 +                Collection c;
 50.1367 +                switch(type) {
 50.1368 +                    case 0: c = res.allInstances(); break;
 50.1369 +                    case 1: c = res.allClasses(); break;
 50.1370 +                    case 2: c = res.allItems(); break;
 50.1371 +                    default: c = null; fail("Type: " + type); break;
 50.1372 +                }
 50.1373 +                
 50.1374 +                assertNotNull(c);
 50.1375 +                return new ArrayList(c);
 50.1376 +            }
 50.1377 +        }
 50.1378 +        
 50.1379 +        L listener = new L();
 50.1380 +        listener.resultChanged(null);
 50.1381 +        
 50.1382 +        for(int i = 0; i < 100; i++) {
 50.1383 +            ic.add(new Integer(i));
 50.1384 +        }
 50.1385 +        
 50.1386 +        assertEquals("3x100+1 checks", 301, listener.round);
 50.1387 +    }
 50.1388 +    
 50.1389 +    public void testChangeOfNodeDoesNotFireChangeInActionMap() {
 50.1390 +        ActionMap am = new ActionMap();
 50.1391 +        Lookup s = Lookups.singleton(am);
 50.1392 +        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, false, 0);
 50.1393 +    }
 50.1394 +    public void testChangeOfNodeDoesNotFireChangeInActionMapSimple() {
 50.1395 +        ActionMap am = new ActionMap();
 50.1396 +        Lookup s = Lookups.singleton(am);
 50.1397 +        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, true, 0);
 50.1398 +    }
 50.1399 +
 50.1400 +    public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookupSimple() {
 50.1401 +        doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(true);
 50.1402 +    }
 50.1403 +    
 50.1404 +    public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup() {
 50.1405 +        doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(false);
 50.1406 +    }
 50.1407 +    private void doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(boolean wrapBySimple) {
 50.1408 +        final ActionMap am = new ActionMap();
 50.1409 +        
 50.1410 +        class Before extends AbstractLookup {
 50.1411 +            public InstanceContent ic;
 50.1412 +            public Before() {
 50.1413 +                this(new InstanceContent());
 50.1414 +            }
 50.1415 +            
 50.1416 +            private Before(InstanceContent ic) {
 50.1417 +                super(ic);
 50.1418 +                this.ic = ic;
 50.1419 +            }
 50.1420 +
 50.1421 +            protected @Override void beforeLookup(Template template) {
 50.1422 +                if (ic != null) {
 50.1423 +                    ic.add(am);
 50.1424 +                    ic = null;
 50.1425 +                }
 50.1426 +            }
 50.1427 +        }
 50.1428 +        
 50.1429 +        Before s = new Before();
 50.1430 +        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, wrapBySimple, 1);
 50.1431 +        
 50.1432 +        assertNull("beforeLookup called once", s.ic);
 50.1433 +    }
 50.1434 +    
 50.1435 +    private void doChangeOfNodeDoesNotFireChangeInActionMap(final ActionMap am, Lookup actionMapLookup, final boolean wrapBySimple, int firstChange) {
 50.1436 +        Lookup[] lookups = { lookup, actionMapLookup };
 50.1437 +        
 50.1438 +        class Provider implements Lookup.Provider {
 50.1439 +            ProxyLookup delegate;
 50.1440 +            Lookup query;
 50.1441 +            
 50.1442 +            public Provider(Lookup[] arr) {
 50.1443 +                if (wrapBySimple) {
 50.1444 +                    delegate = new ProxyLookup(arr);
 50.1445 +                    query = Lookups.proxy(this);
 50.1446 +                } else {
 50.1447 +                    query = delegate = new ProxyLookup(arr);
 50.1448 +                }
 50.1449 +            }
 50.1450 +            
 50.1451 +            public Lookup getLookup() {
 50.1452 +                return delegate;
 50.1453 +            }
 50.1454 +            
 50.1455 +            public void setLookups(Lookup... arr) {
 50.1456 +                if (wrapBySimple) {
 50.1457 +                    delegate = new ProxyLookup(arr);                    
 50.1458 +                } else {
 50.1459 +                    delegate.setLookups(arr);
 50.1460 +                }
 50.1461 +            }
 50.1462 +        }
 50.1463 +        
 50.1464 +        Provider p = new Provider(lookups);
 50.1465 +        
 50.1466 +        Lookup.Result res = p.query.lookup(new Lookup.Template(ActionMap.class));
 50.1467 +        LL ll = new LL();
 50.1468 +        res.addLookupListener(ll);
 50.1469 +
 50.1470 +        Collection c = res.allInstances();
 50.1471 +        assertFalse("Has next", c.isEmpty());
 50.1472 +        
 50.1473 +        ActionMap am1 = (ActionMap)c.iterator().next();
 50.1474 +        assertEquals("Am is there", am, am1);
 50.1475 +        
 50.1476 +        assertEquals("Correct # of changes in first get", firstChange, ll.getCount());
 50.1477 +        
 50.1478 +        Object m1 = new InputMap();
 50.1479 +        Object m2 = new InputMap();
 50.1480 +        
 50.1481 +        ic.add(m1);
 50.1482 +        assertEquals("No change in ActionMap 1", 0, ll.getCount());
 50.1483 +        ic.set(Collections.singletonList(m2), null);
 50.1484 +        assertEquals("No change in ActionMap 2", 0, ll.getCount());
 50.1485 +        ic.add(m2);
 50.1486 +        assertEquals("No change in ActionMap 3", 0, ll.getCount());
 50.1487 +        p.setLookups(lookup, actionMapLookup, Lookup.EMPTY);
 50.1488 +        assertEquals("No change in ActionMap 4", 0, ll.getCount());
 50.1489 +        
 50.1490 +        ActionMap am2 = p.query.lookup(ActionMap.class);
 50.1491 +        assertEquals("Still the same action map", am, am2);
 50.1492 +        
 50.1493 +        
 50.1494 +        class Before extends AbstractLookup {
 50.1495 +            public InstanceContent ic;
 50.1496 +            public Before() {
 50.1497 +                this(new InstanceContent());
 50.1498 +            }
 50.1499 +            
 50.1500 +            private Before(InstanceContent ic) {
 50.1501 +                super(ic);
 50.1502 +                this.ic = ic;
 50.1503 +            }
 50.1504 +
 50.1505 +            protected @Override void beforeLookup(Template template) {
 50.1506 +                if (ic != null) {
 50.1507 +                    ic.add(am);
 50.1508 +                    ic = null;
 50.1509 +                }
 50.1510 +            }
 50.1511 +        }
 50.1512 +        
 50.1513 +        Before s = new Before();
 50.1514 +        
 50.1515 +        // adding different Before, but returning the same instance
 50.1516 +        // this happens with metaInfServices lookup often, moreover
 50.1517 +        // it adds the instance in beforeLookup, which confuses a lot
 50.1518 +        p.setLookups(new Lookup[]{ lookup, new Before() });
 50.1519 +        assertEquals("No change in ActionMap 5", 0, ll.getCount());
 50.1520 +        
 50.1521 +        
 50.1522 +    }
 50.1523 +
 50.1524 +    public void testTasklistsCase() throws Exception {
 50.1525 +        ic.remove(new Object());
 50.1526 +    }
 50.1527 +    
 50.1528 +    
 50.1529 +
 50.1530 +    public void testMultipleListeners() {
 50.1531 +        Object object = new ImplementationObject();
 50.1532 +        ic.add(object);
 50.1533 +        
 50.1534 +        Listener[] listeners = new Listener[4];
 50.1535 +        Lookup.Result result = lookup.lookup(new Lookup.Template(LookupObject.class));
 50.1536 +        for(int i = 0; i < listeners.length; ++i) {
 50.1537 +            listeners[i] = new Listener();
 50.1538 +            result.addLookupListener(listeners[i]);
 50.1539 +        }
 50.1540 +        // initialize listening
 50.1541 +        result.allItems();
 50.1542 +        
 50.1543 +        ic.remove(object);
 50.1544 +        
 50.1545 +        // Apparently, only odd-numbered listeners get called when there are multiple LookupListeners on a result
 50.1546 +        //for(int i = 0; i < listeners.length; ++i) {
 50.1547 +        //    System.out.println("Listener " + i + ": " + listeners[i].wasCalled());            
 50.1548 +        //}
 50.1549 +        for(int i = 0; i < listeners.length; ++i) {
 50.1550 +            assertTrue("Listener " + i + " called", listeners[i].wasCalled());
 50.1551 +        }
 50.1552 +    }
 50.1553 +
 50.1554 +    static Object reserialize(Object o) throws Exception {
 50.1555 +        ByteArrayOutputStream os = new ByteArrayOutputStream();
 50.1556 +        ObjectOutputStream oos = new ObjectOutputStream(os);
 50.1557 +        oos.writeObject(o);
 50.1558 +        oos.close();
 50.1559 +
 50.1560 +        ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
 50.1561 +        ObjectInputStream ois = new ObjectInputStream(is);
 50.1562 +        return ois.readObject();
 50.1563 +    }
 50.1564 +    
 50.1565 +    private class Listener implements LookupListener {
 50.1566 +        private boolean listenerCalled = false;
 50.1567 +        
 50.1568 +        public void resultChanged(LookupEvent ev) {
 50.1569 +            listenerCalled = true;
 50.1570 +        }
 50.1571 +        
 50.1572 +        public boolean wasCalled() {
 50.1573 +            return listenerCalled;
 50.1574 +        }
 50.1575 +        
 50.1576 +        public void reset() {
 50.1577 +            listenerCalled = false;
 50.1578 +        }
 50.1579 +    }
 50.1580 +    
 50.1581 +    private interface LookupObject {}
 50.1582 +    private class ImplementationObject implements LookupObject {}
 50.1583 +    private class NullObject implements LookupObject {}
 50.1584 +    
 50.1585 +    
 50.1586 +    public void testReturnSomethingElseThenYouClaimYouWillReturn() {
 50.1587 +        class Liar extends AbstractLookup.Pair {
 50.1588 +            public Object obj;
 50.1589 +            
 50.1590 +            protected boolean instanceOf(Class c) {
 50.1591 +                return c.isAssignableFrom(String.class);
 50.1592 +            }
 50.1593 +
 50.1594 +            protected boolean creatorOf(Object obj) {
 50.1595 +                return this.obj == obj;
 50.1596 +            }
 50.1597 +
 50.1598 +            public Object getInstance() {
 50.1599 +                return this.obj;
 50.1600 +            }
 50.1601 +
 50.1602 +            public Class getType() {
 50.1603 +                return String.class;
 50.1604 +            }
 50.1605 +
 50.1606 +            public String getId() {
 50.1607 +                return String.class.getName();
 50.1608 +            }
 50.1609 +
 50.1610 +            public String getDisplayName() {
 50.1611 +                return getId();
 50.1612 +            }
 50.1613 +        }
 50.1614 +        
 50.1615 +        
 50.1616 +        Liar l = new Liar();
 50.1617 +        l.obj = new Integer(5);
 50.1618 +        
 50.1619 +        this.ic.addPair(l);
 50.1620 +        
 50.1621 +        Collection c = lookup.lookup(new Lookup.Template(String.class)).allInstances();
 50.1622 +        assertTrue("It is empty: " + c, c.isEmpty());
 50.1623 +    }
 50.1624 +
 50.1625 +    public void testCanProxyLookupHaveWrongResults() {
 50.1626 +        class L implements LookupListener {
 50.1627 +            ProxyLookup pl;
 50.1628 +            Lookup.Result<String> original;
 50.1629 +            Lookup.Result<String> wrapped;
 50.1630 +            boolean ok;
 50.1631 +
 50.1632 +            public void test() {
 50.1633 +                pl = new ProxyLookup(lookup);
 50.1634 +                original = lookup.lookupResult(String.class);
 50.1635 +
 50.1636 +                original.addLookupListener(this);
 50.1637 +
 50.1638 +                wrapped = pl.lookupResult(String.class);
 50.1639 +
 50.1640 +                assertEquals("Original empty", 0, original.allInstances().size());
 50.1641 +                assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
 50.1642 +
 50.1643 +                ic.add("Hello!");
 50.1644 +            }
 50.1645 +
 50.1646 +            public void resultChanged(LookupEvent ev) {
 50.1647 +                ok = true;
 50.1648 +
 50.1649 +                assertEquals("Original has hello", 1, original.allInstances().size());
 50.1650 +                assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
 50.1651 +            }
 50.1652 +
 50.1653 +        }
 50.1654 +        L listener = new L();
 50.1655 +        listener.test();
 50.1656 +        assertTrue("Listener called", listener.ok);
 50.1657 +    }
 50.1658 +
 50.1659 +    public void testObjectFromInstanceContentConverterDisappearsIfNotReferenced() {
 50.1660 +        Conv converter = new Conv("foo");
 50.1661 +        ic.add (converter, converter);
 50.1662 +        Lookup lkp = instanceLookup;
 50.1663 +        StringBuilder sb = lookup.lookup (StringBuilder.class);
 50.1664 +        assertNotNull (sb);
 50.1665 +        int hash = System.identityHashCode(sb);
 50.1666 +        assertEquals ("foo", sb.toString());
 50.1667 +        Reference<StringBuilder> r = new WeakReference<StringBuilder>(sb);
 50.1668 +        sb = null;
 50.1669 +        assertGC("Lookup held onto object", r);
 50.1670 +        sb = lookup.lookup (StringBuilder.class);
 50.1671 +        assertNotSame(hash, System.identityHashCode(sb));
 50.1672 +        r = new WeakReference<StringBuilder>(sb);
 50.1673 +        sb = null;
 50.1674 +        assertGC("Lookup held onto object", r);
 50.1675 +        ic.remove (converter, converter);
 50.1676 +        Reference <InstanceContent.Convertor> cref = new WeakReference<InstanceContent.Convertor>(converter);
 50.1677 +        converter = null;
 50.1678 +        assertGC("Converter still referenced", cref); 
 50.1679 +
 50.1680 +        sb = lkp.lookup(StringBuilder.class);
 50.1681 +        assertNull ("Converter removed from lookup, but object it " +
 50.1682 +                "created still present:'" + sb +"'", sb);
 50.1683 +        converter = new Conv("bar");
 50.1684 +        ic.add (converter, converter);
 50.1685 +        assertNotNull (lkp.lookup(StringBuilder.class));
 50.1686 +        assertEquals ("bar", lkp.lookup(StringBuilder.class).toString());
 50.1687 +    }
 50.1688 +
 50.1689 +    private static class Conv implements InstanceContent.Convertor<Conv, StringBuilder> {
 50.1690 +        private final String str;
 50.1691 +        private Conv (String str) {
 50.1692 +            this.str = str;
 50.1693 +        }
 50.1694 +
 50.1695 +        public StringBuilder convert(Conv obj) {
 50.1696 +            return new StringBuilder (str);
 50.1697 +        }
 50.1698 +
 50.1699 +        public Class<? extends StringBuilder> type(Conv obj) {
 50.1700 +            return StringBuilder.class;
 50.1701 +        }
 50.1702 +
 50.1703 +        public String id(Conv obj) {
 50.1704 +            return "Foo";
 50.1705 +        }
 50.1706 +
 50.1707 +        public String displayName(Conv obj) {
 50.1708 +            return "Foo";
 50.1709 +        }
 50.1710 +    } // end of Conv
 50.1711 +
 50.1712 +    public void testCanGCResults() throws Exception {
 50.1713 +        class L implements LookupListener {
 50.1714 +            int cnt;
 50.1715 +            
 50.1716 +            public void resultChanged(LookupEvent ev) {
 50.1717 +                cnt++;
 50.1718 +            }
 50.1719 +            
 50.1720 +        }
 50.1721 +        L listener1 = new L();
 50.1722 +        L listener2 = new L();
 50.1723 +        
 50.1724 +        Lookup.Result<String> res1 = this.instanceLookup.lookupResult(String.class);
 50.1725 +        Lookup.Result<String> res2 = this.lookup.lookupResult(String.class);
 50.1726 +        
 50.1727 +        assertEquals("Empty1", 0, res1.allItems().size());
 50.1728 +        assertEquals("Empty2", 0, res2.allItems().size());
 50.1729 +        
 50.1730 +        res1.addLookupListener(listener1);
 50.1731 +        res2.addLookupListener(listener2);
 50.1732 +        
 50.1733 +        addInstances(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
 50.1734 +        this.ic.add("Ahoj");
 50.1735 +        
 50.1736 +        assertEquals("Change1", 1, listener1.cnt);
 50.1737 +        assertEquals("Change2", 1, listener2.cnt);
 50.1738 +        
 50.1739 +        assertEquals("Full1", 1, res1.allItems().size());
 50.1740 +        assertEquals("Full2", 1, res2.allItems().size());
 50.1741 +        
 50.1742 +        
 50.1743 +        Reference<Object> ref2 = new WeakReference<Object>(res2);
 50.1744 +        res2 = null;
 50.1745 +        assertGC("Result can disappear", ref2);
 50.1746 +    }
 50.1747 +    
 50.1748 +    void beforeActualTest(String n) {
 50.1749 +        if (n.equals("testEqualsIsNotCalledTooMuch")) {
 50.1750 +            CntPair.cnt = 0;
 50.1751 +            CntPair.hashCnt = 0;
 50.1752 +            CntPair.instances = 0;
 50.1753 +            int how = 1000;
 50.1754 +
 50.1755 +            for(int i = 0; i < how; i++) {
 50.1756 +                this.ic.addPair(new CntPair("x" + i));
 50.1757 +            }
 50.1758 +
 50.1759 +            assertEquals("No equals called", 0, CntPair.cnt);
 50.1760 +            assertEquals("1000 instances ", how, CntPair.instances);
 50.1761 +        }
 50.1762 +    }
 50.1763 +    
 50.1764 +    public void testEqualsIsNotCalledTooMuch() throws Exception {
 50.1765 +        // most of the work done in beforeActualTest
 50.1766 +
 50.1767 +        // desirable: assertEquals("no comparitions", 0, CntPair.cnt);
 50.1768 +        // works for InheritanceTree, but not for ArrayStorage, but array
 50.1769 +        // storages are generally small
 50.1770 +        
 50.1771 +        if (CntPair.cnt > 12000) {
 50.1772 +            fail("Too much comparitions " + CntPair.cnt);
 50.1773 +        }
 50.1774 +        if (CntPair.hashCnt > 40000) {
 50.1775 +            fail("Too much hashes: " + CntPair.hashCnt);
 50.1776 +        }
 50.1777 +        
 50.1778 +        assertEquals("instaces is enough", 1000, CntPair.instances);
 50.1779 +    }
 50.1780 +    
 50.1781 +    /** Adds instances to the instance lookup.
 50.1782 +     */
 50.1783 +    private void addInstances (Object... instances) {
 50.1784 +        for (int i = 0; i < instances.length; i++) {
 50.1785 +            ic.add(instances[i]);
 50.1786 +        }
 50.1787 +    }
 50.1788 +    
 50.1789 +    /** Count instances of clazz in an array. */
 50.1790 +    private int countInstances (Object[] objs, Class clazz) {
 50.1791 +        int count = 0;
 50.1792 +        for (int i = 0; i < objs.length; i++) {
 50.1793 +            if (clazz.isInstance(objs[i])) count++;
 50.1794 +        }
 50.1795 +        return count;
 50.1796 +    }
 50.1797 +    
 50.1798 +    /** Counting listener */
 50.1799 +    protected static class LL implements LookupListener {
 50.1800 +        private int count = 0;
 50.1801 +        public Object source;
 50.1802 +        public Thread changesIn;
 50.1803 +        
 50.1804 +        public LL () {
 50.1805 +            this (null);
 50.1806 +        }
 50.1807 +        
 50.1808 +        public LL (Object source) {
 50.1809 +            this.source = source;
 50.1810 +        }
 50.1811 +        
 50.1812 +        public void resultChanged(LookupEvent ev) {
 50.1813 +            if (changesIn != null) {
 50.1814 +                assertEquals("Changes in the same thread", changesIn, Thread.currentThread());
 50.1815 +            } else {
 50.1816 +                changesIn = Thread.currentThread();
 50.1817 +            }
 50.1818 +            ++count;
 50.1819 +            if (source != null) {
 50.1820 +                assertSame ("Source is the same", source, ev.getSource ());
 50.1821 +//                assertSame ("Result is the same", source, ev.getResult ());
 50.1822 +            }
 50.1823 +        }
 50.1824 +
 50.1825 +        public int getCount() {
 50.1826 +            int i = count;
 50.1827 +            count = 0;
 50.1828 +            return i;
 50.1829 +        }
 50.1830 +    };
 50.1831 +
 50.1832 +    /** A set of interfaces for testInterfaceInheritance
 50.1833 +     */
 50.1834 +    interface TestInterfaceInheritanceA {}
 50.1835 +    interface TestInterfaceInheritanceB extends TestInterfaceInheritanceA, java.rmi.Remote {}
 50.1836 +    interface TestInterfaceInheritanceBB extends TestInterfaceInheritanceB {}
 50.1837 +    interface TestInterfaceInheritanceC extends TestInterfaceInheritanceA, java.rmi.Remote {}
 50.1838 +    interface TestInterfaceInheritanceD extends TestInterfaceInheritanceA {}
 50.1839 +    
 50.1840 +    /** A special class for garbage test */
 50.1841 +    public static final class Garbage extends Object implements Serializable {
 50.1842 +        static final long serialVersionUID = 435340912534L;
 50.1843 +    }
 50.1844 +    
 50.1845 +
 50.1846 +    /* A classloader that can load one class in a special way */
 50.1847 +    private static class CL extends ClassLoader {
 50.1848 +        public CL () {
 50.1849 +            super (null);
 50.1850 +        }
 50.1851 +
 50.1852 +        public @Override Class findClass(String name) throws ClassNotFoundException {
 50.1853 +            if (name.equals (Garbage.class.getName ())) {
 50.1854 +                String n = name.replace ('.', '/');
 50.1855 +                java.io.InputStream is = getClass ().getResourceAsStream ("/" + n + ".class");
 50.1856 +                byte[] arr = new byte[8096];
 50.1857 +                try {
 50.1858 +                    int cnt = is.read (arr);
 50.1859 +                    if (cnt == arr.length) {
 50.1860 +                        fail ("Buffer to load the class is not big enough");
 50.1861 +                    }
 50.1862 +
 50.1863 +                    return defineClass (name, arr, 0, cnt);
 50.1864 +                } catch (java.io.IOException ex) {
 50.1865 +                        ex.printStackTrace();
 50.1866 +                        fail ("IO Exception");
 50.1867 +                        return null;
 50.1868 +                }
 50.1869 +            } else {
 50.1870 +                return null;
 50.1871 +            }
 50.1872 +        }
 50.1873 +
 50.1874 +        /** Convert obj to other object. There is no need to implement
 50.1875 +         * cache mechanism. It is provided by AbstractLookup.Item.getInstance().
 50.1876 +         * Method should be called more than once because Lookup holds
 50.1877 +         * just weak reference.
 50.1878 +         */
 50.1879 +        public Object convert(Object obj) {
 50.1880 +            return null;
 50.1881 +        }
 50.1882 +
 50.1883 +        /** Return type of converted object. */
 50.1884 +        public Class type(Object obj) {
 50.1885 +            try {
 50.1886 +                return loadClass (Garbage.class.getName ());
 50.1887 +            } catch (ClassNotFoundException ex) {
 50.1888 +                fail ("Class not found");
 50.1889 +                throw new InternalError ();
 50.1890 +            }
 50.1891 +        }
 50.1892 +    }
 50.1893 +    
 50.1894 +    private static final class CntPair extends AbstractLookup.Pair {
 50.1895 +        private static int instances;
 50.1896 +        private String txt;
 50.1897 +        
 50.1898 +        public CntPair(String txt) {
 50.1899 +            this.txt = txt;
 50.1900 +            instances++;
 50.1901 +        }
 50.1902 +
 50.1903 +        public static int hashCnt;
 50.1904 +        @Override
 50.1905 +        public int hashCode() {
 50.1906 +            hashCnt++;
 50.1907 +            return txt.hashCode() + 3777;
 50.1908 +        }
 50.1909 +
 50.1910 +        public static int cnt;
 50.1911 +        @Override
 50.1912 +        public boolean equals(Object obj) {
 50.1913 +            cnt++;
 50.1914 +            
 50.1915 +            if (obj == null) {
 50.1916 +                return false;
 50.1917 +            }
 50.1918 +            if (getClass() != obj.getClass()) {
 50.1919 +                return false;
 50.1920 +            }
 50.1921 +            final CntPair other = (CntPair) obj;
 50.1922 +            if (this.txt != other.txt && (this.txt == null || !this.txt.equals(other.txt))) {
 50.1923 +                return false;
 50.1924 +            }
 50.1925 +            return true;
 50.1926 +        }
 50.1927 +
 50.1928 +        protected boolean instanceOf(Class c) {
 50.1929 +            return c.isAssignableFrom(String.class);
 50.1930 +        }
 50.1931 +
 50.1932 +        protected boolean creatorOf(Object obj) {
 50.1933 +            return obj == txt;
 50.1934 +        }
 50.1935 +
 50.1936 +        public Object getInstance() {
 50.1937 +            return txt;
 50.1938 +        }
 50.1939 +
 50.1940 +        public Class getType() {
 50.1941 +            return String.class;
 50.1942 +        }
 50.1943 +
 50.1944 +        public String getId() {
 50.1945 +            return txt;
 50.1946 +        }
 50.1947 +
 50.1948 +        public String getDisplayName() {
 50.1949 +            return txt;
 50.1950 +        }
 50.1951 +        
 50.1952 +    }
 50.1953 +
 50.1954 +    public static final class SerialPair extends AbstractLookup.Pair
 50.1955 +    implements java.io.Serializable {
 50.1956 +        static final long serialVersionUID = 54305834L;
 50.1957 +        private Object value;
 50.1958 +        public transient int countInstanceOf;
 50.1959 +        
 50.1960 +        public SerialPair (Object value) {
 50.1961 +            this.value = value;
 50.1962 +        }
 50.1963 +        
 50.1964 +        protected boolean creatorOf(Object obj) {
 50.1965 +            return obj == value;
 50.1966 +        }
 50.1967 +        
 50.1968 +        public String getDisplayName() {
 50.1969 +            return getId ();
 50.1970 +        }
 50.1971 +        
 50.1972 +        public String getId() {
 50.1973 +            return value.toString();
 50.1974 +        }
 50.1975 +        
 50.1976 +        public Object getInstance() {
 50.1977 +            return value;
 50.1978 +        }
 50.1979 +        
 50.1980 +        public Class getType() {
 50.1981 +            return value.getClass ();
 50.1982 +        }
 50.1983 +        
 50.1984 +        protected boolean instanceOf(Class c) {
 50.1985 +            countInstanceOf++;
 50.1986 +            return c.isInstance(value);
 50.1987 +        }
 50.1988 +    } // end of SerialPair
 50.1989 +    
 50.1990 +    private static class BrokenPair extends AbstractLookup.Pair {
 50.1991 +        private transient ThreadLocal IN = new ThreadLocal ();
 50.1992 +        private boolean checkModify;
 50.1993 +        private boolean checkQuery;
 50.1994 +        
 50.1995 +        public BrokenPair (boolean checkModify, boolean checkQuery) {
 50.1996 +            this.checkModify = checkModify;
 50.1997 +            this.checkQuery = checkQuery;
 50.1998 +        }
 50.1999 +        
 50.2000 +        protected boolean creatorOf(Object obj) { return this == obj; }
 50.2001 +        public String getDisplayName() { return "Broken"; }
 50.2002 +        public String getId() { return "broken"; }
 50.2003 +        public Object getInstance() { return this; }
 50.2004 +        public Class getType() { return getClass (); }
 50.2005 +        protected boolean instanceOf(Class c) { 
 50.2006 +            
 50.2007 +            if (checkQuery) {
 50.2008 +                if (IN.get () == null) {
 50.2009 +                    try {
 50.2010 +                        IN.set (this);
 50.2011 +                        // broken behaviour, tries to modify the lookup
 50.2012 +                        // queries have to survive
 50.2013 +
 50.2014 +                        running.lookup.lookup (java.awt.List.class);
 50.2015 +
 50.2016 +                        // 
 50.2017 +                        // creation of new result has to survive as well
 50.2018 +                        Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.Button.class));
 50.2019 +                        Collection all = myQuery.allItems ();
 50.2020 +                    } finally {
 50.2021 +                        IN.set (null);
 50.2022 +                    }
 50.2023 +                }
 50.2024 +            }
 50.2025 +                
 50.2026 +
 50.2027 +            if (checkModify) {
 50.2028 +                //
 50.2029 +                // modifications should fail
 50.2030 +                //
 50.2031 +
 50.2032 +                try {
 50.2033 +                    running.ic.addPair (new SerialPair (""));
 50.2034 +                    fail ("Modification from a query should be prohibited");
 50.2035 +                } catch (IllegalStateException ex) {
 50.2036 +                }
 50.2037 +                
 50.2038 +                try {
 50.2039 +                    running.ic.removePair (this);
 50.2040 +                    fail ("This has to throw the exception");
 50.2041 +                } catch (IllegalStateException ex) {
 50.2042 +                }
 50.2043 +                try {
 50.2044 +                    running.ic.setPairs (Collections.EMPTY_SET);
 50.2045 +                    fail ("This has to throw the exception as well");
 50.2046 +                } catch (IllegalStateException ex) {
 50.2047 +                }
 50.2048 +            }
 50.2049 +            
 50.2050 +            return c.isAssignableFrom(getType ()); 
 50.2051 +        }
 50.2052 +    } // end of BrokenPair
 50.2053 +    
 50.2054 +    private static class Broken2Pair extends AbstractLookup.Pair {
 50.2055 +        static final long serialVersionUID = 4532587018501L;
 50.2056 +        public transient ThreadLocal IN;
 50.2057 +        
 50.2058 +        public Broken2Pair () {
 50.2059 +        }
 50.2060 +        
 50.2061 +        private void writeObject (java.io.ObjectOutputStream oos) throws java.io.IOException {
 50.2062 +        }
 50.2063 +        
 50.2064 +        private void readObject (java.io.ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException {
 50.2065 +            IN = new ThreadLocal ();
 50.2066 +        }
 50.2067 +        
 50.2068 +        protected boolean creatorOf(Object obj) { return this == obj; }
 50.2069 +        public String getDisplayName() { return "Broken"; }
 50.2070 +        public String getId() { return "broken"; }
 50.2071 +        public Object getInstance() { return this; }
 50.2072 +        public Class getType() { return getClass (); }
 50.2073 +        protected boolean instanceOf(Class c) { 
 50.2074 +            
 50.2075 +            // behaviour gets broken only after deserialization
 50.2076 +            if (IN != null && IN.get () == null) {
 50.2077 +                try {
 50.2078 +                    IN.set (this);
 50.2079 +
 50.2080 +                    // creation of new result has to survive as well
 50.2081 +                    Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.List.class));
 50.2082 +                    Collection all = myQuery.allItems ();
 50.2083 +                } finally {
 50.2084 +                    IN.set (null);
 50.2085 +                }
 50.2086 +            }
 50.2087 +            
 50.2088 +            return c.isAssignableFrom(getType ()); 
 50.2089 +        }
 50.2090 +    } // end of Broken2Pair    
 50.2091 +}
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupExecutorTest.java	Mon Dec 14 20:58:39 2009 +0100
    51.3 @@ -0,0 +1,98 @@
    51.4 +/*
    51.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    51.6 + *
    51.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    51.8 + *
    51.9 + * The contents of this file are subject to the terms of either the GNU
   51.10 + * General Public License Version 2 only ("GPL") or the Common
   51.11 + * Development and Distribution License("CDDL") (collectively, the
   51.12 + * "License"). You may not use this file except in compliance with the
   51.13 + * License. You can obtain a copy of the License at
   51.14 + * http://www.netbeans.org/cddl-gplv2.html
   51.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   51.16 + * specific language governing permissions and limitations under the
   51.17 + * License.  When distributing the software, include this License Header
   51.18 + * Notice in each file and include the License file at
   51.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   51.20 + * particular file as subject to the "Classpath" exception as provided
   51.21 + * by Sun in the GPL Version 2 section of the License file that
   51.22 + * accompanied this code. If applicable, add the following below the
   51.23 + * License Header, with the fields enclosed by brackets [] replaced by
   51.24 + * your own identifying information:
   51.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   51.26 + *
   51.27 + * Contributor(s):
   51.28 + *
   51.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   51.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   51.31 + * Microsystems, Inc. All Rights Reserved.
   51.32 + *
   51.33 + * If you wish your version of this file to be governed by only the CDDL
   51.34 + * or only the GPL Version 2, indicate your decision by adding
   51.35 + * "[Contributor] elects to include this software in this distribution
   51.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   51.37 + * single choice of license, a recipient has the option to distribute
   51.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   51.39 + * to extend the choice of license to its licensees as provided above.
   51.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   51.41 + * Version 2 license, then the option applies only if the new code is
   51.42 + * made subject to such option by the copyright holder.
   51.43 + */
   51.44 +
   51.45 +package org.openide.util.lookup;
   51.46 +
   51.47 +import java.util.concurrent.Executor;
   51.48 +import org.openide.util.Lookup;
   51.49 +import org.openide.util.LookupEvent;
   51.50 +import org.openide.util.LookupListener;
   51.51 +
   51.52 +public class AbstractLookupExecutorTest extends AbstractLookupBaseHid 
   51.53 +implements AbstractLookupBaseHid.Impl, Executor, LookupListener {
   51.54 +    Lookup.Result<?> res;
   51.55 +    
   51.56 +    
   51.57 +    public AbstractLookupExecutorTest(java.lang.String testName) {
   51.58 +        super(testName, null);
   51.59 +    }
   51.60 +
   51.61 +    //
   51.62 +    // Impl of AbstractLookupBaseHid.Impl
   51.63 +    //
   51.64 +
   51.65 +    /** Creates the initial abstract lookup.
   51.66 +     */
   51.67 +    public Lookup createInstancesLookup (InstanceContent ic) {
   51.68 +        ic.attachExecutor(this);
   51.69 +        Lookup l = new AbstractLookup (ic, new InheritanceTree ());
   51.70 +        return l;
   51.71 +    }
   51.72 +    
   51.73 +    /** Creates an lookup for given lookup. This class just returns 
   51.74 +     * the object passed in, but subclasses can be different.
   51.75 +     * @param lookup in lookup
   51.76 +     * @return a lookup to use
   51.77 +     */
   51.78 +    public Lookup createLookup (Lookup lookup) {
   51.79 +        res = lookup.lookupResult(Object.class);
   51.80 +        res.addLookupListener(this);
   51.81 +        return lookup;
   51.82 +    }
   51.83 +
   51.84 +    public void clearCaches () {
   51.85 +    }    
   51.86 +
   51.87 +    ThreadLocal<Object> ME = new ThreadLocal<Object>();
   51.88 +    public void execute(Runnable command) {
   51.89 +        assertEquals("Not yet set", null, ME.get());
   51.90 +        ME.set(this);
   51.91 +        try {
   51.92 +            command.run();
   51.93 +        } finally {
   51.94 +            ME.set(null);
   51.95 +        }
   51.96 +    }
   51.97 +
   51.98 +    public void resultChanged(LookupEvent ev) {
   51.99 +        assertEquals("Changes delivered only from execute method", this, ME.get());
  51.100 +    }
  51.101 +}
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupMemoryTest.java	Mon Dec 14 20:58:39 2009 +0100
    52.3 @@ -0,0 +1,158 @@
    52.4 +/*
    52.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    52.6 + *
    52.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    52.8 + *
    52.9 + * The contents of this file are subject to the terms of either the GNU
   52.10 + * General Public License Version 2 only ("GPL") or the Common
   52.11 + * Development and Distribution License("CDDL") (collectively, the
   52.12 + * "License"). You may not use this file except in compliance with the
   52.13 + * License. You can obtain a copy of the License at
   52.14 + * http://www.netbeans.org/cddl-gplv2.html
   52.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   52.16 + * specific language governing permissions and limitations under the
   52.17 + * License.  When distributing the software, include this License Header
   52.18 + * Notice in each file and include the License file at
   52.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   52.20 + * particular file as subject to the "Classpath" exception as provided
   52.21 + * by Sun in the GPL Version 2 section of the License file that
   52.22 + * accompanied this code. If applicable, add the following below the
   52.23 + * License Header, with the fields enclosed by brackets [] replaced by
   52.24 + * your own identifying information:
   52.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   52.26 + *
   52.27 + * Contributor(s):
   52.28 + *
   52.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   52.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   52.31 + * Microsystems, Inc. All Rights Reserved.
   52.32 + *
   52.33 + * If you wish your version of this file to be governed by only the CDDL
   52.34 + * or only the GPL Version 2, indicate your decision by adding
   52.35 + * "[Contributor] elects to include this software in this distribution
   52.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   52.37 + * single choice of license, a recipient has the option to distribute
   52.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   52.39 + * to extend the choice of license to its licensees as provided above.
   52.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   52.41 + * Version 2 license, then the option applies only if the new code is
   52.42 + * made subject to such option by the copyright holder.
   52.43 + */
   52.44 +
   52.45 +package org.openide.util.lookup;
   52.46 +
   52.47 +import java.util.*;
   52.48 +import org.netbeans.junit.*;
   52.49 +import org.netbeans.modules.openide.util.ActiveQueue;
   52.50 +import org.openide.util.Lookup;
   52.51 +
   52.52 +/** Testing memory consumption of various AbstractLookup aspects.
   52.53 + */
   52.54 +public class AbstractLookupMemoryTest extends NbTestCase {
   52.55 +    public AbstractLookupMemoryTest(java.lang.String testName) {
   52.56 +        super(testName);
   52.57 +    }
   52.58 +
   52.59 +    public static void main(java.lang.String[] args) {
   52.60 +        junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupMemoryTest.class));
   52.61 +    }
   52.62 +
   52.63 +    public void testEmptySize () {
   52.64 +        AbstractLookup instanceLookup = new AbstractLookup ();
   52.65 +        assertSize ("Empty lookup should be small", 16, instanceLookup);
   52.66 +        
   52.67 +        InstanceContent ic = new InstanceContent ();
   52.68 +        instanceLookup = new AbstractLookup (ic);
   52.69 +        assertSize ("Lookup with InstanceContent should be small as well", 16, instanceLookup);
   52.70 +    }
   52.71 +
   52.72 +    public void testPairSize () {
   52.73 +        AbstractLookup.Pair pair = new EmptyPair ();
   52.74 +        assertSize ("Pair occupies only 16 bytes", 16, pair);
   52.75 +    }
   52.76 +    
   52.77 +    public void testPairWithOnePointerSize () {
   52.78 +        AbstractLookup.Pair pair = new OneItemPair ();
   52.79 +        assertSize ("Pair occupies only 16 bytes", 16, pair);
   52.80 +    }
   52.81 +    
   52.82 +    public void testLookupWithPairs () {
   52.83 +        Lookup.Template<Object> t = new Lookup.Template<Object>(Object.class);
   52.84 +        class L implements org.openide.util.LookupListener {
   52.85 +            public int cnt;
   52.86 +            public void resultChanged (org.openide.util.LookupEvent ev) {
   52.87 +                cnt++;
   52.88 +            }
   52.89 +        }
   52.90 +        L listener = new L ();
   52.91 +        L listener2 = new L ();
   52.92 +
   52.93 +        EmptyPair[] pairs = {
   52.94 +            new EmptyPair(),
   52.95 +            new EmptyPair(),
   52.96 +            new EmptyPair(),
   52.97 +            new EmptyPair(),
   52.98 +        };
   52.99 +        Object[] ignore = {
  52.100 +            pairs[0],
  52.101 +            pairs[1],
  52.102 +            pairs[2],
  52.103 +            pairs[3],
  52.104 +            t,
  52.105 +            ActiveQueue.queue(),
  52.106 +            listener,
  52.107 +            listener2,
  52.108 +            new Integer (11) // trashhold is shared
  52.109 +        };
  52.110 +        
  52.111 +        AbstractLookup.Content c = new AbstractLookup.Content ();
  52.112 +        AbstractLookup l = new AbstractLookup (c, (Integer)ignore[ignore.length - 1]);
  52.113 +
  52.114 +        c.addPair ((EmptyPair)ignore[0]);
  52.115 +        assertSize ("Should be really small (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
  52.116 +        
  52.117 +        c.addPair ((EmptyPair)ignore[1]);
  52.118 +        assertSize ("Is bigger I guess (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
  52.119 +        
  52.120 +        c.setPairs(Arrays.asList(pairs).subList(0, 3));
  52.121 +        assertSize ("Even bigger (not counting the pair sizes)", Collections.singleton (l), 64, ignore);
  52.122 +        
  52.123 +        c.setPairs(Arrays.asList(pairs).subList(0, 4));
  52.124 +        assertSize ("Now not that much(not counting the pair sizes)", Collections.singleton (l), 64, ignore);
  52.125 +        
  52.126 +        Lookup.Result res = l.lookup (t);
  52.127 +        
  52.128 +        assertSize ("After creating a result", Collections.singleton (l), 120, ignore);
  52.129 +        
  52.130 +        res.addLookupListener (listener);
  52.131 +        
  52.132 +        assertSize ("And attaching one listener", Collections.singleton (l), 120, ignore);
  52.133 +
  52.134 +        res.addLookupListener (listener2);
  52.135 +        assertSize ("Second listener makes the situation much worse", Collections.singleton (l), 200, ignore);
  52.136 +        res.removeLookupListener(listener2);
  52.137 +        assertSize ("But removing it returns us back to original size", Collections.singleton (l), 120, ignore);
  52.138 +        
  52.139 +        
  52.140 +        assertEquals ("Current for pairs are in", res.allItems ().size (), 4); // also activates the listener
  52.141 +        assertSize ("and making the listener to work", Collections.singleton (l), 120, ignore);
  52.142 +        
  52.143 +        c.removePair ((EmptyPair)ignore[0]);
  52.144 +        assertEquals ("A changes has been delivered", 1, listener.cnt);
  52.145 +    }
  52.146 +
  52.147 +    /** Simple pair with no data */
  52.148 +    private static class EmptyPair extends AbstractLookup.Pair {
  52.149 +        protected boolean creatorOf(Object obj) { return false; }
  52.150 +        public String getDisplayName() { return ""; }
  52.151 +        public String getId() { return ""; }
  52.152 +        public Object getInstance() { return null; }
  52.153 +        public Class getType() { return Object.class; }
  52.154 +        protected boolean instanceOf(Class c) { return c == getType (); }
  52.155 +    } // end of EmptyPair
  52.156 +    
  52.157 +    /** Pair with one item (like InstanceContent.Pair) */
  52.158 +    private static class OneItemPair extends EmptyPair {
  52.159 +        private Object pointer;
  52.160 +    }
  52.161 +}
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    53.3 @@ -0,0 +1,353 @@
    53.4 +/*
    53.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    53.6 + *
    53.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    53.8 + *
    53.9 + * The contents of this file are subject to the terms of either the GNU
   53.10 + * General Public License Version 2 only ("GPL") or the Common
   53.11 + * Development and Distribution License("CDDL") (collectively, the
   53.12 + * "License"). You may not use this file except in compliance with the
   53.13 + * License. You can obtain a copy of the License at
   53.14 + * http://www.netbeans.org/cddl-gplv2.html
   53.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   53.16 + * specific language governing permissions and limitations under the
   53.17 + * License.  When distributing the software, include this License Header
   53.18 + * Notice in each file and include the License file at
   53.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   53.20 + * particular file as subject to the "Classpath" exception as provided
   53.21 + * by Sun in the GPL Version 2 section of the License file that
   53.22 + * accompanied this code. If applicable, add the following below the
   53.23 + * License Header, with the fields enclosed by brackets [] replaced by
   53.24 + * your own identifying information:
   53.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   53.26 + *
   53.27 + * Contributor(s):
   53.28 + *
   53.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   53.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   53.31 + * Microsystems, Inc. All Rights Reserved.
   53.32 + *
   53.33 + * If you wish your version of this file to be governed by only the CDDL
   53.34 + * or only the GPL Version 2, indicate your decision by adding
   53.35 + * "[Contributor] elects to include this software in this distribution
   53.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   53.37 + * single choice of license, a recipient has the option to distribute
   53.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   53.39 + * to extend the choice of license to its licensees as provided above.
   53.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   53.41 + * Version 2 license, then the option applies only if the new code is
   53.42 + * made subject to such option by the copyright holder.
   53.43 + */
   53.44 +
   53.45 +package org.openide.util.lookup;
   53.46 +
   53.47 +import java.util.concurrent.ExecutionException;
   53.48 +
   53.49 +import java.lang.ref.WeakReference;
   53.50 +import java.util.*;
   53.51 +import java.util.concurrent.Executors;
   53.52 +import java.util.concurrent.TimeUnit;
   53.53 +import junit.framework.Test;
   53.54 +import org.netbeans.junit.*;
   53.55 +import org.openide.util.Lookup;
   53.56 +import org.openide.util.lookup.AbstractLookup.Pair;
   53.57 +
   53.58 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   53.59 +public class AbstractLookupTest extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
   53.60 +    public AbstractLookupTest(java.lang.String testName) {
   53.61 +        super(testName, null);
   53.62 +    }
   53.63 +
   53.64 +    //
   53.65 +    // Impl of AbstractLookupBaseHid.Impl
   53.66 +    //
   53.67 +
   53.68 +    /** Creates the initial abstract lookup.
   53.69 +     */
   53.70 +    public Lookup createInstancesLookup (InstanceContent ic) {
   53.71 +        return new AbstractLookup (ic, new InheritanceTree ());
   53.72 +    }
   53.73 +    
   53.74 +    /** Creates an lookup for given lookup. This class just returns 
   53.75 +     * the object passed in, but subclasses can be different.
   53.76 +     * @param lookup in lookup
   53.77 +     * @return a lookup to use
   53.78 +     */
   53.79 +    public Lookup createLookup (Lookup lookup) {
   53.80 +        return lookup;
   53.81 +    }
   53.82 +
   53.83 +    public void clearCaches () {
   53.84 +    }    
   53.85 +
   53.86 +    static class LkpResultCanBeGargageCollectedAndClearsTheResult extends AbstractLookup {
   53.87 +        public int cleared;
   53.88 +        public int dirty;
   53.89 +
   53.90 +        synchronized @Override boolean cleanUpResult(Template t) {
   53.91 +            boolean res = super.cleanUpResult (t);
   53.92 +            if (res) {
   53.93 +                cleared++;
   53.94 +            } else {
   53.95 +                dirty++;
   53.96 +            }
   53.97 +
   53.98 +            notifyAll ();
   53.99 +
  53.100 +            return res;
  53.101 +        }
  53.102 +    }
  53.103 +    public void testResultCanBeGargageCollectedAndClearsTheResult () throws Exception {
  53.104 +        LkpResultCanBeGargageCollectedAndClearsTheResult lkp = new LkpResultCanBeGargageCollectedAndClearsTheResult ();
  53.105 +        assertSize ("24 for AbstractLookup, 8 for two ints", 32, lkp);
  53.106 +        synchronized (lkp) {
  53.107 +            Lookup.Result res = lkp.lookup (new Lookup.Template (getClass ()));
  53.108 +            res.allItems();
  53.109 +            
  53.110 +            WeakReference ref = new WeakReference (res);
  53.111 +            res = null;
  53.112 +            assertGC ("Reference can get cleared", ref);
  53.113 +         
  53.114 +            // wait till we 
  53.115 +            while (lkp.cleared == 0 && lkp.dirty == 0) {
  53.116 +                lkp.wait ();
  53.117 +            }
  53.118 +            
  53.119 +            assertEquals ("No dirty cleanups", 0, lkp.dirty);
  53.120 +            assertEquals ("One final cleanup", 1, lkp.cleared);
  53.121 +        }
  53.122 +        //assertSize ("Everything has been cleaned to original size", 32, lkp);
  53.123 +        
  53.124 +    }
  53.125 +    
  53.126 +    public void testPairCannotBeUsedInMoreThanOneLookupAtOnce () throws Exception {
  53.127 +        /** Simple pair with no data */
  53.128 +        class EmptyPair extends AbstractLookup.Pair {
  53.129 +            protected boolean creatorOf(Object obj) { return false; }
  53.130 +            public String getDisplayName() { return "Empty"; }
  53.131 +            public String getId() { return "empty"; }
  53.132 +            public Object getInstance() { return null; }
  53.133 +            public Class getType() { return Object.class; }
  53.134 +            protected boolean instanceOf(Class c) { return c == getType (); }
  53.135 +        } // end of EmptyPair
  53.136 +        
  53.137 +        AbstractLookup.Content c1 = new AbstractLookup.Content ();
  53.138 +        AbstractLookup.Content c2 = new AbstractLookup.Content ();
  53.139 +        AbstractLookup l1 = new AbstractLookup (c1);
  53.140 +        AbstractLookup l2 = new AbstractLookup (c2);
  53.141 +        
  53.142 +        EmptyPair empty = new EmptyPair ();
  53.143 +        c1.addPair (empty);
  53.144 +        Lookup.Result res = l1.lookup (new Lookup.Template (Object.class));
  53.145 +        assertEquals (
  53.146 +            "Pair is really found", empty, 
  53.147 +            res.allItems ().iterator().next ()
  53.148 +        );
  53.149 +        try {
  53.150 +            c2.addPair (empty);
  53.151 +            fail ("It should not be possible to add pair to two lookups");
  53.152 +        } catch (IllegalStateException ex) {
  53.153 +            // ok, exception is fine
  53.154 +        }
  53.155 +        assertEquals (
  53.156 +            "L2 is still empty", Collections.EMPTY_LIST, 
  53.157 +            new ArrayList (l2.lookup (new Lookup.Template (Object.class)).allItems ())
  53.158 +        );
  53.159 +    }
  53.160 +    
  53.161 +    public void testInitializationCanBeDoneFromAnotherThread () {
  53.162 +        class MyLkp extends AbstractLookup implements Runnable {
  53.163 +            private InstanceContent ic;
  53.164 +            private boolean direct;
  53.165 +            
  53.166 +            public MyLkp (boolean direct) {
  53.167 +                this (direct, new InstanceContent ());
  53.168 +            }
  53.169 +                
  53.170 +            private MyLkp (boolean direct, InstanceContent ic) {
  53.171 +                super (ic);
  53.172 +                this.direct = direct;
  53.173 +                this.ic = ic;
  53.174 +            }
  53.175 +            
  53.176 +            protected @Override void initialize() {
  53.177 +                if (direct) {
  53.178 +                    run ();
  53.179 +                } else {
  53.180 +                    try {
  53.181 +                        Executors.newSingleThreadScheduledExecutor().schedule(this, 0, TimeUnit.MICROSECONDS).get();
  53.182 +                    } catch (InterruptedException ex) {
  53.183 +                        ex.printStackTrace();
  53.184 +                    } catch (ExecutionException ex) {
  53.185 +                        ex.printStackTrace();
  53.186 +                    }
  53.187 +                }
  53.188 +            }
  53.189 +            
  53.190 +            public void run () {
  53.191 +                ic.add (this);
  53.192 +                ic.remove (this);
  53.193 +                ic.set (Collections.nCopies(10, this), null);
  53.194 +                ic.set (Collections.EMPTY_LIST, null);
  53.195 +                ic.add (AbstractLookupTest.this);
  53.196 +            }
  53.197 +        }
  53.198 +        
  53.199 +        assertEquals ("The test should be there", this, new MyLkp (true).lookup (Object.class));
  53.200 +        assertEquals ("and in async mode as well", this, new MyLkp (false).lookup (Object.class));
  53.201 +    }
  53.202 +    
  53.203 +    public void testBeforeLookupIsCalled () {
  53.204 +        class BeforeL extends AbstractLookup {
  53.205 +            public ArrayList list = new ArrayList ();
  53.206 +            public String toAdd;
  53.207 +            public InstanceContent ic;
  53.208 +            
  53.209 +            public BeforeL () {
  53.210 +                this (new InstanceContent ());
  53.211 +            }
  53.212 +            
  53.213 +            private BeforeL (InstanceContent c) {
  53.214 +                super (c);
  53.215 +                this.ic = c;
  53.216 +            }
  53.217 +        
  53.218 +            protected @Override void beforeLookup(Template t) {
  53.219 +                if (toAdd != null) {
  53.220 +                    list.add (0, new SerialPair (toAdd));
  53.221 +                    setPairs (list);
  53.222 +                } else {
  53.223 +                    ic.add (new Integer (1));
  53.224 +                }
  53.225 +            }
  53.226 +        }
  53.227 +        
  53.228 +        BeforeL lookup = new BeforeL ();
  53.229 +        
  53.230 +        lookup.toAdd = "First";
  53.231 +        assertEquals ("First if found", "First", lookup.lookup (String.class));
  53.232 +        
  53.233 +        lookup.toAdd = "2";
  53.234 +        assertEquals ("2 is not first", "2", lookup.lookup (String.class));
  53.235 +        
  53.236 +        Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
  53.237 +        for (int i = 3; i < 20; i++) {
  53.238 +            lookup.toAdd = String.valueOf (i);
  53.239 +            assertEquals (i + " items are now there", i, res.allInstances ().size ());
  53.240 +        }
  53.241 +        for (int i = 20; i < 35; i++) {
  53.242 +            lookup.toAdd = String.valueOf (i);
  53.243 +            assertEquals (i + " items are now there", i, res.allItems ().size ());
  53.244 +        }
  53.245 +        
  53.246 +        assertEquals ("Just strings are there now", 1, res.allClasses ().size ());
  53.247 +        lookup.toAdd = null; // this will add integer
  53.248 +        assertEquals ("Two classes now", 2, res.allClasses ().size ());
  53.249 +    }
  53.250 +
  53.251 +    public void testInconsistentAfterDeserIssue71744() throws Exception {
  53.252 +        InheritanceTree inhTree = new InheritanceTree();
  53.253 +
  53.254 +        AbstractLookup al = new AbstractLookup(new AbstractLookup.Content(), inhTree);
  53.255 +        {
  53.256 +
  53.257 +            Collection r = al.lookup(new Lookup.Template(Integer.class)).allInstances();
  53.258 +            assertEquals("None", 0, r.size());
  53.259 +        }
  53.260 +
  53.261 +        ICP item = new ICP(new Integer(10));
  53.262 +        al.addPair(item);
  53.263 +        al.removePair(item);
  53.264 +
  53.265 +        AbstractLookup newLookup = (AbstractLookup)reserialize(al);
  53.266 +
  53.267 +        newLookup.lookup(Number.class);
  53.268 +
  53.269 +
  53.270 +        newLookup.addPair(new ICP(new Long(20)));
  53.271 +
  53.272 +        {
  53.273 +
  53.274 +            Collection r = newLookup.lookup(new Lookup.Template(Number.class)).allInstances();
  53.275 +            assertEquals("one", 1, r.size());
  53.276 +/*
  53.277 +            Iterator it = r.iterator();
  53.278 +            assertEquals(new Integer(10), it.next());
  53.279 +            assertEquals(new Long(20), it.next());*/
  53.280 +        }
  53.281 +    }
  53.282 +
  53.283 +    public void testMatchesIssue130673() {
  53.284 +        class BrokenPairReturningNullID extends Pair<Object> {
  53.285 +            @Override
  53.286 +            protected boolean instanceOf(Class<?> c) {
  53.287 +                return false;
  53.288 +            }
  53.289 +
  53.290 +            @Override
  53.291 +            protected boolean creatorOf(Object obj) {
  53.292 +                return false;
  53.293 +            }
  53.294 +
  53.295 +            @Override
  53.296 +            public Object getInstance() {
  53.297 +                return null;
  53.298 +            }
  53.299 +
  53.300 +            @Override
  53.301 +            public Class<? extends Object> getType() {
  53.302 +                return null;
  53.303 +            }
  53.304 +
  53.305 +            @Override
  53.306 +            public String getId() {
  53.307 +                return null;
  53.308 +            }
  53.309 +
  53.310 +            @Override
  53.311 +            public String getDisplayName() {
  53.312 +                return null;
  53.313 +            }
  53.314 +        }
  53.315 +        BrokenPairReturningNullID broken = new BrokenPairReturningNullID();
  53.316 +        
  53.317 +        
  53.318 +        Lookup.Template<String> t = new Lookup.Template<String>(String.class, "ID", null);
  53.319 +        boolean not = AbstractLookup.matches(t, broken, true);
  53.320 +        assertFalse("Does not match the template, but throws no exception", not);
  53.321 +    }
  53.322 +    
  53.323 +    private static final class ICP extends AbstractLookup.Pair {
  53.324 +        private Number s;
  53.325 +
  53.326 +        public ICP (Number s) {
  53.327 +            this.s = s;
  53.328 +        }
  53.329 +
  53.330 +
  53.331 +        protected boolean instanceOf(Class c) {
  53.332 +            return c.isInstance(s);
  53.333 +        }
  53.334 +
  53.335 +        protected boolean creatorOf(Object obj) {
  53.336 +            return s == obj;
  53.337 +        }
  53.338 +
  53.339 +        public Object getInstance() {
  53.340 +            return s;
  53.341 +        }
  53.342 +
  53.343 +        public Class getType() {
  53.344 +            return s.getClass();
  53.345 +        }
  53.346 +
  53.347 +        public String getId() {
  53.348 +            return s.toString();
  53.349 +        }
  53.350 +
  53.351 +        public String getDisplayName() {
  53.352 +            return getId();
  53.353 +        }
  53.354 +
  53.355 +    }
  53.356 +}
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    54.3 @@ -0,0 +1,228 @@
    54.4 +/*
    54.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    54.6 + *
    54.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    54.8 + *
    54.9 + * The contents of this file are subject to the terms of either the GNU
   54.10 + * General Public License Version 2 only ("GPL") or the Common
   54.11 + * Development and Distribution License("CDDL") (collectively, the
   54.12 + * "License"). You may not use this file except in compliance with the
   54.13 + * License. You can obtain a copy of the License at
   54.14 + * http://www.netbeans.org/cddl-gplv2.html
   54.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   54.16 + * specific language governing permissions and limitations under the
   54.17 + * License.  When distributing the software, include this License Header
   54.18 + * Notice in each file and include the License file at
   54.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   54.20 + * particular file as subject to the "Classpath" exception as provided
   54.21 + * by Sun in the GPL Version 2 section of the License file that
   54.22 + * accompanied this code. If applicable, add the following below the
   54.23 + * License Header, with the fields enclosed by brackets [] replaced by
   54.24 + * your own identifying information:
   54.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   54.26 + *
   54.27 + * Contributor(s):
   54.28 + *
   54.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   54.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   54.31 + * Microsystems, Inc. All Rights Reserved.
   54.32 + *
   54.33 + * If you wish your version of this file to be governed by only the CDDL
   54.34 + * or only the GPL Version 2, indicate your decision by adding
   54.35 + * "[Contributor] elects to include this software in this distribution
   54.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   54.37 + * single choice of license, a recipient has the option to distribute
   54.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   54.39 + * to extend the choice of license to its licensees as provided above.
   54.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   54.41 + * Version 2 license, then the option applies only if the new code is
   54.42 + * made subject to such option by the copyright holder.
   54.43 + */
   54.44 +
   54.45 +package org.openide.util.lookup;
   54.46 +
   54.47 +import java.util.*;
   54.48 +import org.openide.util.Lookup;
   54.49 +
   54.50 +/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
   54.51 + */
   54.52 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   54.53 +public class ExcludingLookupTest extends AbstractLookupBaseHid
   54.54 +implements AbstractLookupBaseHid.Impl {
   54.55 +    public ExcludingLookupTest(java.lang.String testName) {
   54.56 +        super(testName, null);
   54.57 +    }
   54.58 +
   54.59 +    public Lookup createLookup (final Lookup lookup) {
   54.60 +        return Lookups.exclude (lookup, new Class[0]);
   54.61 +    }
   54.62 +    
   54.63 +    public Lookup createInstancesLookup (InstanceContent ic) {
   54.64 +        return new AbstractLookup (ic);
   54.65 +    }
   54.66 +
   54.67 +    public void clearCaches () {
   54.68 +    }    
   54.69 +    
   54.70 +    public void testWeCanRemoveInteger () throws Exception {
   54.71 +        doBasicFilteringTest (Integer.class, Integer.class, 0);
   54.72 +    }
   54.73 +    
   54.74 +    public void testWeCanRemoveIntegersEvenByAskingForRemoveOfAllNumbers () throws Exception {
   54.75 +        doBasicFilteringTest (Number.class, Integer.class, 0);
   54.76 +    }
   54.77 +    public void testFunWithInterfaces () throws Exception {
   54.78 +        doBasicFilteringTest (java.io.Serializable.class, Integer.class, 0);
   54.79 +    }
   54.80 +    
   54.81 +    public void testWeCanGetInstanceOfSerializableEvenItIsExcludedIfWeAskForClassNotExtendingIt () throws Exception {
   54.82 +        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { java.io.Serializable.class });
   54.83 +        Lookup.Template t = new Lookup.Template (Object.class);
   54.84 +        Lookup.Result res = lookup.lookup (t);
   54.85 +        
   54.86 +        LL ll = new LL ();
   54.87 +        res.addLookupListener (ll);
   54.88 +        assertEquals ("Nothing is there", 0, res.allItems ().size ());
   54.89 +        
   54.90 +        Object inst = new Integer (3);
   54.91 +        ic.add (inst);
   54.92 +        
   54.93 +        assertEquals ("Not Filtered out", inst, lookup.lookup (Object.class));
   54.94 +        assertEquals ("Not Filtered out2", inst, lookup.lookupItem (t).getInstance ());
   54.95 +        assertEquals ("One is there - 2", 1, res.allItems ().size ());
   54.96 +        assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
   54.97 +        assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
   54.98 +        assertEquals ("Right # of events", 1, ll.getCount ());
   54.99 +        
  54.100 +        ic.remove (inst);
  54.101 +        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
  54.102 +        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
  54.103 +        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
  54.104 +        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
  54.105 +        assertEquals ("Of course it is not there", null, lookup.lookup (Object.class));
  54.106 +        assertEquals ("Right # of events", 1, ll.getCount ());
  54.107 +    }
  54.108 +    
  54.109 +    public void testIntegersQueriedThruObject () throws Exception {
  54.110 +        doBasicFilteringTest (Number.class, Object.class, 1);
  54.111 +    }
  54.112 +    
  54.113 +    private void doBasicFilteringTest (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
  54.114 +        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
  54.115 +        Lookup.Template t = new Lookup.Template (theQuery);
  54.116 +        Lookup.Result res = lookup.lookup (t);
  54.117 +        
  54.118 +        LL ll = new LL ();
  54.119 +        res.addLookupListener (ll);
  54.120 +        assertEquals ("Nothing is there", 0, res.allItems ().size ());
  54.121 +        
  54.122 +        Object inst = new Integer (3);
  54.123 +        ic.add (inst);
  54.124 +        
  54.125 +        assertEquals ("Filtered out", null, lookup.lookup (theQuery));
  54.126 +        assertEquals ("Filtered out2", null, lookup.lookupItem (t));
  54.127 +        assertEquals ("Nothing is there - 2", 0, res.allItems ().size ());
  54.128 +        assertEquals ("Nothing is there - 2a", 0, res.allInstances ().size ());
  54.129 +        assertEquals ("Nothing is there - 2b", 0, res.allClasses ().size ());
  54.130 +        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
  54.131 +        
  54.132 +        ic.remove (inst);
  54.133 +        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
  54.134 +        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
  54.135 +        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
  54.136 +        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
  54.137 +        assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
  54.138 +        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
  54.139 +        
  54.140 +    }
  54.141 +    
  54.142 +    public void testSizeOfTheLookup () throws Exception {
  54.143 +        Class exclude = String.class;
  54.144 +        
  54.145 +        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { exclude });
  54.146 +
  54.147 +        assertSize ("Should be pretty lightweight", Collections.singleton (lookup), 16, 
  54.148 +                new Object[] { this.instanceLookup, exclude });
  54.149 +    }
  54.150 +    public void testSizeOfTheLookupForMultipleFiltersIsHigher () throws Exception {
  54.151 +        Class exclude = String.class;
  54.152 +        Class exclude2 = Integer.class;
  54.153 +        Class[] arr = new Class[] { exclude, exclude2 };
  54.154 +        
  54.155 +        Lookup lookup = Lookups.exclude (this.instanceLookup, arr);
  54.156 +
  54.157 +        assertSize ("Is fatter", Collections.singleton (lookup), 40, 
  54.158 +                new Object[] { this.instanceLookup, exclude, exclude2 });
  54.159 +        assertSize ("But only due to the array", Collections.singleton (lookup), 16, 
  54.160 +                new Object[] { this.instanceLookup, exclude, exclude2, arr });
  54.161 +    }
  54.162 +    
  54.163 +    public void testFilteringOfSomething () throws Exception {
  54.164 +        doFilteringOfSomething (Runnable.class, java.io.Serializable.class, 1);
  54.165 +    }
  54.166 +    
  54.167 +    private void doFilteringOfSomething (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
  54.168 +        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
  54.169 +        Lookup.Template t = new Lookup.Template (theQuery);
  54.170 +        Lookup.Result res = lookup.lookup (t);
  54.171 +        
  54.172 +        LL ll = new LL ();
  54.173 +        res.addLookupListener (ll);
  54.174 +        assertEquals ("Nothing is there", 0, res.allItems ().size ());
  54.175 +        
  54.176 +        Object inst = new Integer (3);
  54.177 +        ic.add (inst);
  54.178 +        
  54.179 +        assertEquals ("Accepted", inst, lookup.lookup (theQuery));
  54.180 +        assertNotNull ("Accepted too", lookup.lookupItem (t));
  54.181 +        assertEquals ("One is there - 2", 1, res.allItems ().size ());
  54.182 +        assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
  54.183 +        assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
  54.184 +        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
  54.185 +
  54.186 +        Object inst2 = new Thread (); // implements Runnable
  54.187 +        ic.add (inst2);
  54.188 +        assertEquals ("Accepted - 2", inst, lookup.lookup (theQuery));
  54.189 +        assertNotNull ("Accepted too -2", lookup.lookupItem (t));
  54.190 +        assertEquals ("One is there - 3", 1, res.allItems ().size ());
  54.191 +        assertEquals ("One is there - 3a", 1, res.allInstances ().size ());
  54.192 +        assertEquals ("One is there - 3b", 1, res.allClasses ().size ());
  54.193 +        assertEquals ("Right # of events", 0, ll.getCount ());
  54.194 +        
  54.195 +        
  54.196 +        ic.remove (inst);
  54.197 +        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
  54.198 +        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
  54.199 +        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
  54.200 +        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
  54.201 +        assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
  54.202 +        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
  54.203 +    }
  54.204 +
  54.205 +    public void testTheBehaviourAsRequestedByDavidAndDescribedByJesse () throws Exception {
  54.206 +        class C implements Runnable, java.io.Serializable {
  54.207 +            public void run () {}
  54.208 +        }
  54.209 +        Object c = new C();
  54.210 +        Lookup l1 = Lookups.singleton(c);
  54.211 +        Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
  54.212 +        assertNull(l2.lookup(Runnable.class));
  54.213 +        assertEquals(c, l2.lookup(java.io.Serializable.class));
  54.214 +    }
  54.215 +    
  54.216 +    public void testTheBehaviourAsRequestedByDavidAndDescribedByJesseWithUsageOfResult () throws Exception {
  54.217 +        class C implements Runnable, java.io.Serializable {
  54.218 +            public void run () {}
  54.219 +        }
  54.220 +        Object c = new C();
  54.221 +        Lookup l1 = Lookups.singleton(c);
  54.222 +        Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
  54.223 +        
  54.224 +        Lookup.Result run = l2.lookup (new Lookup.Template (Runnable.class));
  54.225 +        Lookup.Result ser = l2.lookup (new Lookup.Template (java.io.Serializable.class));
  54.226 +        
  54.227 +        assertEquals ("Runnables filtered out", 0, run.allItems ().size ());
  54.228 +        assertEquals ("One serialiazble", 1, ser.allItems ().size ());
  54.229 +        assertEquals ("And it is c", c, ser.allInstances ().iterator ().next ());
  54.230 +    }
  54.231 +}
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/InheritanceTreeTest.java	Mon Dec 14 20:58:39 2009 +0100
    55.3 @@ -0,0 +1,77 @@
    55.4 +/*
    55.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    55.6 + *
    55.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    55.8 + *
    55.9 + * The contents of this file are subject to the terms of either the GNU
   55.10 + * General Public License Version 2 only ("GPL") or the Common
   55.11 + * Development and Distribution License("CDDL") (collectively, the
   55.12 + * "License"). You may not use this file except in compliance with the
   55.13 + * License. You can obtain a copy of the License at
   55.14 + * http://www.netbeans.org/cddl-gplv2.html
   55.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   55.16 + * specific language governing permissions and limitations under the
   55.17 + * License.  When distributing the software, include this License Header
   55.18 + * Notice in each file and include the License file at
   55.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   55.20 + * particular file as subject to the "Classpath" exception as provided
   55.21 + * by Sun in the GPL Version 2 section of the License file that
   55.22 + * accompanied this code. If applicable, add the following below the
   55.23 + * License Header, with the fields enclosed by brackets [] replaced by
   55.24 + * your own identifying information:
   55.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   55.26 + *
   55.27 + * Contributor(s):
   55.28 + *
   55.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   55.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   55.31 + * Microsystems, Inc. All Rights Reserved.
   55.32 + *
   55.33 + * If you wish your version of this file to be governed by only the CDDL
   55.34 + * or only the GPL Version 2, indicate your decision by adding
   55.35 + * "[Contributor] elects to include this software in this distribution
   55.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   55.37 + * single choice of license, a recipient has the option to distribute
   55.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   55.39 + * to extend the choice of license to its licensees as provided above.
   55.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   55.41 + * Version 2 license, then the option applies only if the new code is
   55.42 + * made subject to such option by the copyright holder.
   55.43 + */
   55.44 +package org.openide.util.lookup;
   55.45 +
   55.46 +import junit.framework.TestCase;
   55.47 +import junit.framework.*;
   55.48 +import org.openide.util.Lookup;
   55.49 +import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
   55.50 +import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
   55.51 +import java.io.*;
   55.52 +import java.lang.ref.WeakReference;
   55.53 +import java.util.*;
   55.54 +
   55.55 +/**
   55.56 + *
   55.57 + * @author Jaroslav Tulach
   55.58 + */
   55.59 +public class InheritanceTreeTest extends TestCase {
   55.60 +
   55.61 +    public InheritanceTreeTest(String testName) {
   55.62 +        super(testName);
   55.63 +    }
   55.64 +
   55.65 +    protected void setUp() throws Exception {
   55.66 +    }
   55.67 +
   55.68 +    protected void tearDown() throws Exception {
   55.69 +    }
   55.70 +
   55.71 +    public void testDeserOfNode() {
   55.72 +        InheritanceTree inh = new InheritanceTree();
   55.73 +        InheritanceTree.Node n = new InheritanceTree.Node(String.class);
   55.74 +        n.markDeserialized();
   55.75 +        n.markDeserialized();
   55.76 +
   55.77 +        n.assignItem(inh, new InstanceContent.SimpleItem("Ahoj"));
   55.78 +    }
   55.79 +    
   55.80 +}
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/InitializationBug44134Test.java	Mon Dec 14 20:58:39 2009 +0100
    56.3 @@ -0,0 +1,126 @@
    56.4 +/*
    56.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    56.6 + *
    56.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    56.8 + *
    56.9 + * The contents of this file are subject to the terms of either the GNU
   56.10 + * General Public License Version 2 only ("GPL") or the Common
   56.11 + * Development and Distribution License("CDDL") (collectively, the
   56.12 + * "License"). You may not use this file except in compliance with the
   56.13 + * License. You can obtain a copy of the License at
   56.14 + * http://www.netbeans.org/cddl-gplv2.html
   56.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   56.16 + * specific language governing permissions and limitations under the
   56.17 + * License.  When distributing the software, include this License Header
   56.18 + * Notice in each file and include the License file at
   56.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   56.20 + * particular file as subject to the "Classpath" exception as provided
   56.21 + * by Sun in the GPL Version 2 section of the License file that
   56.22 + * accompanied this code. If applicable, add the following below the
   56.23 + * License Header, with the fields enclosed by brackets [] replaced by
   56.24 + * your own identifying information:
   56.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   56.26 + *
   56.27 + * Contributor(s):
   56.28 + *
   56.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   56.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   56.31 + * Microsystems, Inc. All Rights Reserved.
   56.32 + *
   56.33 + * If you wish your version of this file to be governed by only the CDDL
   56.34 + * or only the GPL Version 2, indicate your decision by adding
   56.35 + * "[Contributor] elects to include this software in this distribution
   56.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   56.37 + * single choice of license, a recipient has the option to distribute
   56.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   56.39 + * to extend the choice of license to its licensees as provided above.
   56.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   56.41 + * Version 2 license, then the option applies only if the new code is
   56.42 + * made subject to such option by the copyright holder.
   56.43 + */
   56.44 +
   56.45 +package org.openide.util.lookup;
   56.46 +
   56.47 +import java.util.*;
   56.48 +import org.netbeans.junit.*;
   56.49 +import org.openide.util.Lookup;
   56.50 +
   56.51 +public class InitializationBug44134Test extends NbTestCase {
   56.52 +    public InitializationBug44134Test (java.lang.String testName) {
   56.53 +        super(testName);
   56.54 +    }
   56.55 +
   56.56 +    public static void main(java.lang.String[] args) {
   56.57 +        junit.textui.TestRunner.run(new NbTestSuite(InitializationBug44134Test.class));
   56.58 +    }
   56.59 +
   56.60 +    public void testThereShouldBe18Integers () throws Exception {
   56.61 +        FooManifestLookup foo = new FooManifestLookup ();
   56.62 +        
   56.63 +        Collection items = foo.lookup (new Lookup.Template (Integer.class)).allItems ();
   56.64 +        
   56.65 +        assertEquals ("18 of them", 18, items.size ());
   56.66 +        
   56.67 +        Iterator it = items.iterator ();
   56.68 +        while (it.hasNext()) {
   56.69 +            Lookup.Item t = (Lookup.Item)it.next ();
   56.70 +            assertEquals ("Is Integer", Integer.class, t.getInstance ().getClass ());
   56.71 +        }
   56.72 +    }
   56.73 +
   56.74 +    
   56.75 +    public class FooManifestLookup extends AbstractLookup {
   56.76 +        public FooManifestLookup() {
   56.77 +            super();
   56.78 +        }
   56.79 +        
   56.80 +        @Override
   56.81 +        protected void initialize() {
   56.82 +            for (int i=0; i<18; i++) {
   56.83 +                try {
   56.84 +                    String id= "__" + i;
   56.85 +                    
   56.86 +                    addPair(new FooLookupItem(new Integer(i),id));
   56.87 +                }
   56.88 +                catch (Exception e) {
   56.89 +                }
   56.90 +            }
   56.91 +        }
   56.92 +        
   56.93 +        public class FooLookupItem extends AbstractLookup.Pair {
   56.94 +            public FooLookupItem(Integer data, String id) {
   56.95 +                super();
   56.96 +                this.data=data;
   56.97 +                this.id=id;
   56.98 +            }
   56.99 +            
  56.100 +            protected boolean creatorOf(Object obj) {
  56.101 +                return obj == data;
  56.102 +            }
  56.103 +            
  56.104 +            public String getDisplayName() {
  56.105 +                return data.toString();
  56.106 +            }
  56.107 +            
  56.108 +            public Class getType () {
  56.109 +                return Integer.class;
  56.110 +            }
  56.111 +            
  56.112 +            protected boolean instanceOf (Class c) {
  56.113 +                return c.isInstance(data);
  56.114 +            }
  56.115 +            
  56.116 +            public Object getInstance() {
  56.117 +                return data;
  56.118 +            }
  56.119 +            
  56.120 +            public String getId() {
  56.121 +                return id;
  56.122 +            }
  56.123 +            
  56.124 +            private Integer data;
  56.125 +            private String id;
  56.126 +        }
  56.127 +    }
  56.128 +    
  56.129 +}
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/KomrskaLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    57.3 @@ -0,0 +1,177 @@
    57.4 +/*
    57.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    57.6 + *
    57.7 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    57.8 + *
    57.9 + * The contents of this file are subject to the terms of either the GNU
   57.10 + * General Public License Version 2 only ("GPL") or the Common
   57.11 + * Development and Distribution License("CDDL") (collectively, the
   57.12 + * "License"). You may not use this file except in compliance with the
   57.13 + * License. You can obtain a copy of the License at
   57.14 + * http://www.netbeans.org/cddl-gplv2.html
   57.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   57.16 + * specific language governing permissions and limitations under the
   57.17 + * License.  When distributing the software, include this License Header
   57.18 + * Notice in each file and include the License file at
   57.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   57.20 + * particular file as subject to the "Classpath" exception as provided
   57.21 + * by Sun in the GPL Version 2 section of the License file that
   57.22 + * accompanied this code. If applicable, add the following below the
   57.23 + * License Header, with the fields enclosed by brackets [] replaced by
   57.24 + * your own identifying information:
   57.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   57.26 + *
   57.27 + * If you wish your version of this file to be governed by only the CDDL
   57.28 + * or only the GPL Version 2, indicate your decision by adding
   57.29 + * "[Contributor] elects to include this software in this distribution
   57.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   57.31 + * single choice of license, a recipient has the option to distribute
   57.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   57.33 + * to extend the choice of license to its licensees as provided above.
   57.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   57.35 + * Version 2 license, then the option applies only if the new code is
   57.36 + * made subject to such option by the copyright holder.
   57.37 + *
   57.38 + * Contributor(s):
   57.39 + *
   57.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   57.41 + */
   57.42 +package org.openide.util.lookup;
   57.43 +
   57.44 +import org.junit.After;
   57.45 +import org.junit.Before;
   57.46 +import org.junit.Test;
   57.47 +import org.openide.util.Lookup;
   57.48 +import org.openide.util.LookupEvent;
   57.49 +import org.openide.util.LookupListener;
   57.50 +import static org.junit.Assert.*;
   57.51 +
   57.52 +/**
   57.53 + * Test donated by Mr. Komrska. Seems to pass with 6.5.
   57.54 + * @author komrska
   57.55 + */
   57.56 +public final class KomrskaLookupTest {
   57.57 +    private TestLookupManager lookupManager=null;
   57.58 +    private StringBuffer result=null;
   57.59 +    
   57.60 +    //
   57.61 +    
   57.62 +    private void addToLookup(final TestLookupItemA object) {
   57.63 +        result.append('A');
   57.64 +        lookupManager.add(object);
   57.65 +    }
   57.66 +    private void removeFromLookup(final TestLookupItemA object) {
   57.67 +        result.append('A');
   57.68 +        lookupManager.remove(object);
   57.69 +    }
   57.70 +
   57.71 +    private void addToLookup(final TestLookupItemB object) {
   57.72 +        result.append('B');
   57.73 +        lookupManager.add(object);
   57.74 +    }
   57.75 +    private void removeFromLookup(final TestLookupItemB object) {
   57.76 +        result.append('B');
   57.77 +        lookupManager.remove(object);
   57.78 +    }
   57.79 +    
   57.80 +    public String getResult() {
   57.81 +        return result.toString();
   57.82 +    }
   57.83 +    
   57.84 +    //
   57.85 +
   57.86 +    @Before
   57.87 +    public void setUp() {
   57.88 +        lookupManager=new TestLookupManager();
   57.89 +        result=new StringBuffer();
   57.90 +    }
   57.91 +    
   57.92 +    @After
   57.93 +    public void tearDown() {
   57.94 +        lookupManager=null;
   57.95 +        result=null;
   57.96 +    }
   57.97 +    
   57.98 +    @Test
   57.99 +    public void testLookupBug() {
  57.100 +        TestLookupItemA itemA1=new TestLookupItemA();
  57.101 +        TestLookupItemB itemB1=new TestLookupItemB();
  57.102 +        //
  57.103 +        addToLookup(itemA1);
  57.104 +        addToLookup(itemB1);
  57.105 +        removeFromLookup(itemA1);
  57.106 +        removeFromLookup(itemB1);
  57.107 +        addToLookup(itemB1);
  57.108 +        removeFromLookup(itemB1);
  57.109 +        //
  57.110 +        addToLookup(itemA1);
  57.111 +        addToLookup(itemB1);
  57.112 +        removeFromLookup(itemA1);
  57.113 +        removeFromLookup(itemB1);
  57.114 +        addToLookup(itemB1);
  57.115 +        removeFromLookup(itemB1);
  57.116 +        //
  57.117 +        addToLookup(itemA1);
  57.118 +        addToLookup(itemB1);
  57.119 +        removeFromLookup(itemA1);
  57.120 +        removeFromLookup(itemB1);
  57.121 +        addToLookup(itemB1);
  57.122 +        removeFromLookup(itemB1);
  57.123 +        //
  57.124 +        assertEquals(getResult(),lookupManager.getResult());
  57.125 +    }
  57.126 +
  57.127 +    public static final class TestLookupItemA {}
  57.128 +    public static final class TestLookupItemB {}
  57.129 +    public static final class TestLookupManager {
  57.130 +        private InstanceContent instanceContent=new InstanceContent();
  57.131 +        private AbstractLookup abstractLookup=new AbstractLookup(instanceContent);
  57.132 +
  57.133 +        private Lookup.Result<TestLookupItemA> resultA=null;
  57.134 +        private Lookup.Result<TestLookupItemB> resultB=null;
  57.135 +
  57.136 +        private LookupListener listenerA=new LookupListener() {
  57.137 +            public void resultChanged(LookupEvent event) {
  57.138 +                result.append('A');
  57.139 +            }
  57.140 +        };
  57.141 +        private LookupListener listenerB=new LookupListener() {
  57.142 +            public void resultChanged(LookupEvent event) {
  57.143 +                result.append('B');
  57.144 +            }
  57.145 +        };
  57.146 +
  57.147 +        private StringBuffer result=new StringBuffer();
  57.148 +
  57.149 +        //
  57.150 +
  57.151 +        public TestLookupManager() {
  57.152 +            Lookup.Template<TestLookupItemA> templateA=
  57.153 +                new Lookup.Template<TestLookupItemA>(TestLookupItemA.class);
  57.154 +            resultA=abstractLookup.lookup(templateA);
  57.155 +            resultA.addLookupListener(listenerA);
  57.156 +            resultA.allInstances().size();
  57.157 +            //
  57.158 +            Lookup.Template<TestLookupItemB> templateB=
  57.159 +                new Lookup.Template<TestLookupItemB>(TestLookupItemB.class);
  57.160 +            resultB=abstractLookup.lookup(templateB);
  57.161 +            resultB.addLookupListener(listenerB);
  57.162 +            resultB.allInstances().size();
  57.163 +            // WORKAROUND
  57.164 +            // instanceContent.add(Boolean.TRUE);
  57.165 +        }
  57.166 +
  57.167 +        //
  57.168 +
  57.169 +        public void add(Object item) {
  57.170 +            instanceContent.add(item);
  57.171 +        }
  57.172 +        public void remove(Object item) {
  57.173 +            instanceContent.remove(item);
  57.174 +        }
  57.175 +        public String getResult() {
  57.176 +            return result.toString();
  57.177 +        }
  57.178 +    }
  57.179 +
  57.180 +}
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/LookupBugTest.java	Mon Dec 14 20:58:39 2009 +0100
    58.3 @@ -0,0 +1,79 @@
    58.4 +package org.openide.util.lookup;
    58.5 +
    58.6 +import java.util.logging.Logger;
    58.7 +import org.junit.Before;
    58.8 +import org.junit.Test;
    58.9 +import org.openide.util.Lookup;
   58.10 +import org.openide.util.LookupEvent;
   58.11 +import org.openide.util.LookupListener;
   58.12 +import static org.junit.Assert.*;
   58.13 +
   58.14 +/**
   58.15 + * Test of a Lookup bug seen in NetBeans platforms 6.0-6.5M1.
   58.16 + * @author rlee
   58.17 + */
   58.18 +public class LookupBugTest implements LookupListener
   58.19 +{
   58.20 +    private static final int MAX_LOOPS = 1000;
   58.21 +    
   58.22 +    private AbstractLookup lookup;
   58.23 +    private InstanceContent content;
   58.24 +    private Lookup.Result<String> wordResult;
   58.25 +    private Lookup.Result<Integer> numberResult;
   58.26 +    private String word;
   58.27 +    private Integer number;
   58.28 +    private Logger LOG;
   58.29 +    
   58.30 +    private boolean fired;
   58.31 +    private int i;
   58.32 +
   58.33 +    @Before
   58.34 +    public void setUp()
   58.35 +    {
   58.36 +        LOG = Logger.getLogger("test.LookupBugTest");
   58.37 +        content = new InstanceContent();
   58.38 +        lookup = new AbstractLookup(content);
   58.39 +        wordResult = lookup.lookupResult(java.lang.String.class);
   58.40 +        wordResult.addLookupListener(this);
   58.41 +        numberResult = lookup.lookupResult(java.lang.Integer.class);
   58.42 +        numberResult.addLookupListener(this);
   58.43 +        
   58.44 +        fired = false;
   58.45 +    }
   58.46 +    
   58.47 +    @Test
   58.48 +    public void lookupTest()
   58.49 +    {
   58.50 +        for(i = 0; i < MAX_LOOPS; i++ )
   58.51 +        {
   58.52 +            word = String.valueOf(i);
   58.53 +            number = new Integer(i);
   58.54 +            content.add(word);
   58.55 +            assertTrue( "word on loop " + i, checkLookupEventFired() );
   58.56 +            content.add(number);
   58.57 +            assertTrue( "number on loop " + i, checkLookupEventFired() );
   58.58 +            content.remove(word);
   58.59 +            assertTrue( "remove word on loop " + i, checkLookupEventFired() );
   58.60 +            content.remove(number);
   58.61 +            assertTrue( "remove number on loop " + i, checkLookupEventFired() );
   58.62 +
   58.63 +            assertTrue("The lookup still needs to stay simple", AbstractLookup.isSimple(lookup));
   58.64 +        }
   58.65 +    }
   58.66 +
   58.67 +    public void resultChanged(LookupEvent ev)
   58.68 +    {
   58.69 +        fired = true;
   58.70 +    }
   58.71 +    
   58.72 +    public boolean checkLookupEventFired()
   58.73 +    {
   58.74 +        LOG.fine("  round: " + i + " word = " + word + " number = " + number);
   58.75 +        if( fired )
   58.76 +        {
   58.77 +            fired = false;
   58.78 +            return true;
   58.79 +        }
   58.80 +        else return false;
   58.81 +    }
   58.82 +}
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/LookupsProxyTest.java	Mon Dec 14 20:58:39 2009 +0100
    59.3 @@ -0,0 +1,282 @@
    59.4 +/*
    59.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    59.6 + *
    59.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    59.8 + *
    59.9 + * The contents of this file are subject to the terms of either the GNU
   59.10 + * General Public License Version 2 only ("GPL") or the Common
   59.11 + * Development and Distribution License("CDDL") (collectively, the
   59.12 + * "License"). You may not use this file except in compliance with the
   59.13 + * License. You can obtain a copy of the License at
   59.14 + * http://www.netbeans.org/cddl-gplv2.html
   59.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   59.16 + * specific language governing permissions and limitations under the
   59.17 + * License.  When distributing the software, include this License Header
   59.18 + * Notice in each file and include the License file at
   59.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   59.20 + * particular file as subject to the "Classpath" exception as provided
   59.21 + * by Sun in the GPL Version 2 section of the License file that
   59.22 + * accompanied this code. If applicable, add the following below the
   59.23 + * License Header, with the fields enclosed by brackets [] replaced by
   59.24 + * your own identifying information:
   59.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   59.26 + *
   59.27 + * Contributor(s):
   59.28 + *
   59.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   59.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   59.31 + * Microsystems, Inc. All Rights Reserved.
   59.32 + *
   59.33 + * If you wish your version of this file to be governed by only the CDDL
   59.34 + * or only the GPL Version 2, indicate your decision by adding
   59.35 + * "[Contributor] elects to include this software in this distribution
   59.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   59.37 + * single choice of license, a recipient has the option to distribute
   59.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   59.39 + * to extend the choice of license to its licensees as provided above.
   59.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   59.41 + * Version 2 license, then the option applies only if the new code is
   59.42 + * made subject to such option by the copyright holder.
   59.43 + */
   59.44 +
   59.45 +package org.openide.util.lookup;
   59.46 +
   59.47 +import java.io.Serializable;
   59.48 +
   59.49 +import java.util.*;
   59.50 +import org.netbeans.junit.*;
   59.51 +import org.openide.util.Lookup;
   59.52 +import org.openide.util.LookupEvent;
   59.53 +import org.openide.util.LookupListener;
   59.54 +
   59.55 +/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
   59.56 + */
   59.57 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   59.58 +public class LookupsProxyTest extends AbstractLookupBaseHid
   59.59 +implements AbstractLookupBaseHid.Impl {
   59.60 +    public LookupsProxyTest(java.lang.String testName) {
   59.61 +        super(testName, null);
   59.62 +    }
   59.63 +
   59.64 +    public static void main(java.lang.String[] args) {
   59.65 +        junit.textui.TestRunner.run(new NbTestSuite (LookupsProxyTest.class));
   59.66 +    }
   59.67 +    
   59.68 +    /** Creates an lookup for given lookup. This class just returns 
   59.69 +     * the object passed in, but subclasses can be different.
   59.70 +     * @param lookup in lookup
   59.71 +     * @return a lookup to use
   59.72 +     */
   59.73 +    public Lookup createLookup (final Lookup lookup) {
   59.74 +        return org.openide.util.lookup.Lookups.proxy (
   59.75 +            new Lookup.Provider () {
   59.76 +                public Lookup getLookup () {
   59.77 +                    return lookup;
   59.78 +                }
   59.79 +            }
   59.80 +        );
   59.81 +    }
   59.82 +    
   59.83 +    public Lookup createInstancesLookup (InstanceContent ic) {
   59.84 +        return new AbstractLookup (ic);
   59.85 +    }
   59.86 +
   59.87 +    public void clearCaches () {
   59.88 +    }    
   59.89 +    
   59.90 +    
   59.91 +   
   59.92 +    /** Check whether setLookups method does not fire when there is no
   59.93 +     * change in the lookups.
   59.94 +     */
   59.95 +    public void testProxyListener () {
   59.96 +        Changer ch = new Changer (Lookup.EMPTY);
   59.97 +        
   59.98 +        Lookup lookup = Lookups.proxy(ch);
   59.99 +        Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
  59.100 +        
  59.101 +        LL ll = new LL ();
  59.102 +        res.addLookupListener (ll);
  59.103 +        Collection allRes = res.allInstances ();
  59.104 +
  59.105 +        ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
  59.106 +        lookup.lookup (Object.class); // does the refresh
  59.107 +        
  59.108 +        assertEquals("Replacing an empty by empty does not generate an event", 0, ll.getCount());
  59.109 +        
  59.110 +        InstanceContent content = new InstanceContent ();
  59.111 +        AbstractLookup del = new AbstractLookup (content);
  59.112 +        content.add (this);
  59.113 +        ch.setLookup (del);
  59.114 +        lookup.lookup (Object.class);
  59.115 +        
  59.116 +        if (ll.getCount () != 1) {
  59.117 +            fail ("Changing lookups with different content generates an event");
  59.118 +        }
  59.119 +        
  59.120 +        ch.setLookup (del);
  59.121 +        lookup.lookup (Object.class);
  59.122 +        
  59.123 +        if (ll.getCount () != 0) {
  59.124 +           fail ("Not changing the lookups does not generate any event");
  59.125 +        }
  59.126 +    }
  59.127 +
  59.128 +    
  59.129 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
  59.130 +        doListeningAndQueryingByTwoListenersSetLookups(0, 1, false);
  59.131 +    }
  59.132 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
  59.133 +        doListeningAndQueryingByTwoListenersSetLookups(1, 1, false);        
  59.134 +    }
  59.135 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
  59.136 +        doListeningAndQueryingByTwoListenersSetLookups(2, 1, false);
  59.137 +    }
  59.138 +    
  59.139 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
  59.140 +        doListeningAndQueryingByTwoListenersSetLookups(0, 2, false);
  59.141 +    }
  59.142 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
  59.143 +        doListeningAndQueryingByTwoListenersSetLookups(1, 2, false);        
  59.144 +    }
  59.145 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
  59.146 +        doListeningAndQueryingByTwoListenersSetLookups(2, 2, false);
  59.147 +    }
  59.148 +
  59.149 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookupsWithProxy() {
  59.150 +        doListeningAndQueryingByTwoListenersSetLookups(0, 1, true);
  59.151 +    }
  59.152 +    public void testListeningAndQueryingByTwoListenersClassesSetLookupsWithProxy() {
  59.153 +        doListeningAndQueryingByTwoListenersSetLookups(1, 1, true);        
  59.154 +    }
  59.155 +    public void testListeningAndQueryingByTwoListenersItemsSetLookupsWithProxy() {
  59.156 +        doListeningAndQueryingByTwoListenersSetLookups(2, 1, true);
  59.157 +    }
  59.158 +    
  59.159 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2WithProxy() {
  59.160 +        doListeningAndQueryingByTwoListenersSetLookups(0, 2, true);
  59.161 +    }
  59.162 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups2WithProxy() {
  59.163 +        doListeningAndQueryingByTwoListenersSetLookups(1, 2, true);        
  59.164 +    }
  59.165 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups2WithProxy() {
  59.166 +        doListeningAndQueryingByTwoListenersSetLookups(2, 2, true);
  59.167 +    }
  59.168 +    
  59.169 +    /* XXX: these are pretty slow, seems there is a performance problem 2^22
  59.170 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
  59.171 +        doListeningAndQueryingByTwoListenersSetLookups(0, 22);
  59.172 +    }
  59.173 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
  59.174 +        doListeningAndQueryingByTwoListenersSetLookups(1, 22);        
  59.175 +    }
  59.176 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
  59.177 +        doListeningAndQueryingByTwoListenersSetLookups(2, 22);
  59.178 +    }
  59.179 +     */
  59.180 +    
  59.181 +    private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth, boolean cacheOnTop) {
  59.182 +        Changer orig = new Changer(Lookup.EMPTY);
  59.183 +        Lookup on = Lookups.proxy(orig);
  59.184 +        Lookup first = on;
  59.185 +        
  59.186 +        while (--depth > 0) {
  59.187 +            Changer next = new Changer(on);
  59.188 +            on = Lookups.proxy(next);
  59.189 +        }
  59.190 +        
  59.191 +        
  59.192 +        final Lookup lookup = cacheOnTop ? new ProxyLookup(new Lookup[] { on }) : on;
  59.193 +        
  59.194 +        class L implements LookupListener {
  59.195 +            Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
  59.196 +            Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
  59.197 +            Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
  59.198 +            
  59.199 +            {
  59.200 +                integer.addLookupListener(this);
  59.201 +                number.addLookupListener(this);
  59.202 +                serial.addLookupListener(this);
  59.203 +            }
  59.204 +            
  59.205 +            int round;
  59.206 +            
  59.207 +            public void resultChanged(LookupEvent ev) {
  59.208 +                Collection c1 = get(type, integer);
  59.209 +                Collection c2 = get(type, number);
  59.210 +                Collection c3 = get(type, serial);
  59.211 +                
  59.212 +                assertEquals("round " + round + " c1 vs. c2", c1, c2);
  59.213 +                assertEquals("round " + round + " c1 vs. c3", c1, c3);
  59.214 +                assertEquals("round " + round + " c2 vs. c3", c2, c3);
  59.215 +                
  59.216 +                round++;
  59.217 +            }            
  59.218 +
  59.219 +            private Collection get(int type, Lookup.Result res) {
  59.220 +                Collection c;
  59.221 +                switch(type) {
  59.222 +                    case 0: c = res.allInstances(); break;
  59.223 +                    case 1: c = res.allClasses(); break;
  59.224 +                    case 2: c = res.allItems(); break;
  59.225 +                    default: c = null; fail("Type: " + type); break;
  59.226 +                }
  59.227 +                
  59.228 +                assertNotNull(c);
  59.229 +                return new ArrayList(c);
  59.230 +            }
  59.231 +        }
  59.232 +        
  59.233 +        L listener = new L();
  59.234 +        listener.resultChanged(null);
  59.235 +        ArrayList arr = new ArrayList();
  59.236 +        for(int i = 0; i < 100; i++) {
  59.237 +            arr.add(new Integer(i));
  59.238 +            
  59.239 +            orig.lookup = Lookups.fixed(arr.toArray());
  59.240 +            // do the refresh
  59.241 +            first.lookup((Class)null);
  59.242 +        }
  59.243 +        
  59.244 +        assertEquals("3x100+1 checks", 301, listener.round);
  59.245 +    }
  59.246 +    
  59.247 +    
  59.248 +    public void testRefreshWithoutAllInstances103300 () {
  59.249 +        Changer ch = new Changer (Lookup.EMPTY);
  59.250 +        
  59.251 +        Lookup lookup = Lookups.proxy(ch);
  59.252 +
  59.253 +        ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
  59.254 +        assertNull("Nothing there", lookup.lookup (Object.class)); // does the refresh
  59.255 +        
  59.256 +        InstanceContent content = new InstanceContent ();
  59.257 +        AbstractLookup del = new AbstractLookup (content);
  59.258 +        content.add (this);
  59.259 +        ch.setLookup (del);
  59.260 +        assertEquals("Can see me", this, lookup.lookup (Object.class));
  59.261 +        
  59.262 +        ch.setLookup (del);
  59.263 +        assertEquals("Still can see me", this, lookup.lookup (Object.class));
  59.264 +
  59.265 +        assertEquals("I am visible", this, lookup.lookup(LookupsProxyTest.class));
  59.266 +    }
  59.267 +
  59.268 +
  59.269 +    private static final class Changer implements Lookup.Provider {
  59.270 +        private Lookup lookup;
  59.271 +        
  59.272 +        public Changer (Lookup lookup) {
  59.273 +            setLookup (lookup);
  59.274 +        }
  59.275 +        
  59.276 +        public void setLookup (Lookup lookup) {
  59.277 +            this.lookup = lookup;
  59.278 +        }
  59.279 +        
  59.280 +        public Lookup getLookup() {
  59.281 +            return lookup;
  59.282 +        }
  59.283 +    }
  59.284 +
  59.285 +}
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    60.3 @@ -0,0 +1,552 @@
    60.4 +/*
    60.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    60.6 + *
    60.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    60.8 + *
    60.9 + * The contents of this file are subject to the terms of either the GNU
   60.10 + * General Public License Version 2 only ("GPL") or the Common
   60.11 + * Development and Distribution License("CDDL") (collectively, the
   60.12 + * "License"). You may not use this file except in compliance with the
   60.13 + * License. You can obtain a copy of the License at
   60.14 + * http://www.netbeans.org/cddl-gplv2.html
   60.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   60.16 + * specific language governing permissions and limitations under the
   60.17 + * License.  When distributing the software, include this License Header
   60.18 + * Notice in each file and include the License file at
   60.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   60.20 + * particular file as subject to the "Classpath" exception as provided
   60.21 + * by Sun in the GPL Version 2 section of the License file that
   60.22 + * accompanied this code. If applicable, add the following below the
   60.23 + * License Header, with the fields enclosed by brackets [] replaced by
   60.24 + * your own identifying information:
   60.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   60.26 + *
   60.27 + * Contributor(s):
   60.28 + *
   60.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   60.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   60.31 + * Microsystems, Inc. All Rights Reserved.
   60.32 + *
   60.33 + * If you wish your version of this file to be governed by only the CDDL
   60.34 + * or only the GPL Version 2, indicate your decision by adding
   60.35 + * "[Contributor] elects to include this software in this distribution
   60.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   60.37 + * single choice of license, a recipient has the option to distribute
   60.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   60.39 + * to extend the choice of license to its licensees as provided above.
   60.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   60.41 + * Version 2 license, then the option applies only if the new code is
   60.42 + * made subject to such option by the copyright holder.
   60.43 + */
   60.44 +
   60.45 +package org.openide.util.lookup;
   60.46 +
   60.47 +import java.io.ByteArrayInputStream;
   60.48 +import java.io.File;
   60.49 +import java.io.FileOutputStream;
   60.50 +import java.io.IOException;
   60.51 +import java.io.InputStream;
   60.52 +import java.io.InputStreamReader;
   60.53 +import java.lang.ref.Reference;
   60.54 +import java.lang.ref.WeakReference;
   60.55 +import java.net.URL;
   60.56 +import java.net.URLClassLoader;
   60.57 +import java.net.URLConnection;
   60.58 +import java.net.URLStreamHandler;
   60.59 +import java.util.ArrayList;
   60.60 +import java.util.Collection;
   60.61 +import java.util.Collections;
   60.62 +import java.util.Comparator;
   60.63 +import java.util.Enumeration;
   60.64 +import java.util.HashSet;
   60.65 +import java.util.Iterator;
   60.66 +import java.util.List;
   60.67 +import java.util.Map;
   60.68 +import java.util.Set;
   60.69 +import java.util.TreeSet;
   60.70 +import java.util.WeakHashMap;
   60.71 +import java.util.concurrent.atomic.AtomicBoolean;
   60.72 +import java.util.jar.JarEntry;
   60.73 +import java.util.jar.JarOutputStream;
   60.74 +import java.util.logging.Level;
   60.75 +import java.util.logging.Logger;
   60.76 +import java.util.regex.Matcher;
   60.77 +import java.util.regex.Pattern;
   60.78 +import org.bar.Comparator2;
   60.79 +import org.netbeans.junit.MockServices;
   60.80 +import org.netbeans.junit.NbTestCase;
   60.81 +import org.openide.util.Lookup;
   60.82 +import org.openide.util.LookupEvent;
   60.83 +import org.openide.util.LookupListener;
   60.84 +import org.openide.util.test.MockLookup;
   60.85 +
   60.86 +/** Test finding services from manifest.
   60.87 + * @author Jesse Glick
   60.88 + */
   60.89 +public class MetaInfServicesLookupTest extends NbTestCase {
   60.90 +    private Logger LOG;
   60.91 +    private Map<ClassLoader,Lookup> lookups = new WeakHashMap<ClassLoader,Lookup>();
   60.92 +    
   60.93 +    public MetaInfServicesLookupTest(String name) {
   60.94 +        super(name);
   60.95 +        LOG = Logger.getLogger("Test." + name);
   60.96 +    }
   60.97 +
   60.98 +    protected String prefix() {
   60.99 +        return "META-INF/services/";
  60.100 +    }
  60.101 +    
  60.102 +    protected Lookup createLookup(ClassLoader c) {
  60.103 +        return Lookups.metaInfServices(c);
  60.104 +    }
  60.105 +    
  60.106 +    @Override
  60.107 +    protected Level logLevel() {
  60.108 +        return Level.INFO;
  60.109 +    }
  60.110 +
  60.111 +    private Lookup getTestedLookup(ClassLoader c) {
  60.112 +        MockServices.setServices();
  60.113 +        Lookup l = lookups.get(c);
  60.114 +        if (l == null) {
  60.115 +            l = createLookup(c);
  60.116 +            lookups.put(c, l);
  60.117 +        }
  60.118 +        return l;
  60.119 +    }
  60.120 +
  60.121 +    private URL findJar(String n) throws IOException {
  60.122 +        LOG.info("Looking for " + n);
  60.123 +        File jarDir = new File(getWorkDir(), "jars");
  60.124 +        jarDir.mkdirs();
  60.125 +        File jar = new File(jarDir, n);
  60.126 +        if (jar.exists()) {
  60.127 +            return jar.toURI().toURL();
  60.128 +        }
  60.129 +        
  60.130 +        LOG.info("generating " + jar);
  60.131 +        
  60.132 +        URL data = MetaInfServicesLookupTest.class.getResource(n.replaceAll("\\.jar", "\\.txt"));
  60.133 +        assertNotNull("Data found", data);
  60.134 +        StringBuffer sb = new StringBuffer();
  60.135 +        InputStreamReader r = new InputStreamReader(data.openStream());
  60.136 +        for(;;) {
  60.137 +            int ch = r.read();
  60.138 +            if (ch == -1) {
  60.139 +                break;
  60.140 +            }
  60.141 +            sb.append((char)ch);
  60.142 +        }
  60.143 +        
  60.144 +        JarOutputStream os = new JarOutputStream(new FileOutputStream(jar));
  60.145 +        
  60.146 +        Pattern p = Pattern.compile(":([^:]+):([^:]*)", Pattern.MULTILINE | Pattern.DOTALL);
  60.147 +        Matcher m = p.matcher(sb);
  60.148 +        Pattern foobar = Pattern.compile("^(org\\.(foo|bar)\\..*)$", Pattern.MULTILINE);
  60.149 +        Set<String> names = new TreeSet<String>();
  60.150 +        while (m.find()) {
  60.151 +            assert m.groupCount() == 2;
  60.152 +            String entryName = prefix() + m.group(1);
  60.153 +            LOG.info("putting there entry: " + entryName);
  60.154 +            os.putNextEntry(new JarEntry(entryName));
  60.155 +            os.write(m.group(2).getBytes());
  60.156 +            os.closeEntry();
  60.157 +            
  60.158 +            Matcher fb = foobar.matcher(m.group(2));
  60.159 +            while (fb.find()) {
  60.160 +                String clazz = fb.group(1).replace('.', '/') + ".class";
  60.161 +                LOG.info("will copy " + clazz);
  60.162 +                names.add(clazz);
  60.163 +            }
  60.164 +        }
  60.165 +        
  60.166 +        for (String copy : names) {
  60.167 +            os.putNextEntry(new JarEntry(copy));
  60.168 +            LOG.info("copying " + copy);
  60.169 +            InputStream from = MetaInfServicesLookupTest.class.getResourceAsStream("/" + copy);
  60.170 +            assertNotNull(copy, from);
  60.171 +            for (;;) {
  60.172 +                int ch = from.read();
  60.173 +                if (ch == -1) {
  60.174 +                    break;
  60.175 +                }
  60.176 +                os.write(ch);
  60.177 +            }
  60.178 +            from.close();
  60.179 +            os.closeEntry();
  60.180 +        }
  60.181 +        os.close();
  60.182 +        LOG.info("done " + jar);
  60.183 +        return jar.toURI().toURL();
  60.184 +    }
  60.185 +
  60.186 +    ClassLoader c1, c2, c2a, c3, c4;
  60.187 +
  60.188 +    @Override
  60.189 +    protected void setUp() throws Exception {
  60.190 +        clearWorkDir();
  60.191 +        ClassLoader app = getClass().getClassLoader().getParent();
  60.192 +        ClassLoader c0 = app;
  60.193 +        
  60.194 +        c1 = new URLClassLoader(new URL[] {
  60.195 +            findJar("services-jar-1.jar"),
  60.196 +        }, c0);
  60.197 +        c2 = new URLClassLoader(new URL[] {
  60.198 +            findJar("services-jar-2.jar"),
  60.199 +        }, c1);
  60.200 +        c2a = new URLClassLoader(new URL[] {
  60.201 +            findJar("services-jar-2.jar"),
  60.202 +        }, c1);
  60.203 +        c3 = new URLClassLoader(new URL[] { findJar("services-jar-2.jar") },
  60.204 +            c0
  60.205 +        );
  60.206 +        c4 = new URLClassLoader(new URL[] {
  60.207 +            findJar("services-jar-1.jar"),
  60.208 +            findJar("services-jar-2.jar"),
  60.209 +        }, c0);
  60.210 +    }
  60.211 +
  60.212 +    @Override
  60.213 +    protected void tearDown() throws Exception {
  60.214 +        Set<Reference<Lookup>> weak = new HashSet<Reference<Lookup>>();
  60.215 +        for (Lookup l : lookups.values()) {
  60.216 +            weak.add(new WeakReference<Lookup>(l));
  60.217 +        }
  60.218 +        
  60.219 +        lookups = null;
  60.220 +        
  60.221 +        for(Reference<Lookup> ref : weak) {
  60.222 +            assertGC("Lookup can disappear", ref);
  60.223 +        }
  60.224 +    }
  60.225 +
  60.226 +    public void testBasicUsage() throws Exception {
  60.227 +        Lookup l = getTestedLookup(c2);
  60.228 +        Class<?> xface = c1.loadClass("org.foo.Interface");
  60.229 +        List<?> results = new ArrayList<Object>(l.lookupAll(xface));
  60.230 +        assertEquals("Two items in result: " + results, 2, results.size());
  60.231 +        // Note that they have to be in order:
  60.232 +        assertEquals("org.foo.impl.Implementation1", results.get(0).getClass().getName());
  60.233 +        assertEquals("org.bar.Implementation2", results.get(1).getClass().getName());
  60.234 +        // Make sure it does not gratuitously replace items:
  60.235 +        List<?> results2 = new ArrayList<Object>(l.lookupAll(xface));
  60.236 +        assertEquals(results, results2);
  60.237 +    }
  60.238 +
  60.239 +    public void testLoaderSkew() throws Exception {
  60.240 +        Class<?> xface1 = c1.loadClass("org.foo.Interface");
  60.241 +        Lookup l3 = getTestedLookup(c3);
  60.242 +        // If we cannot load Interface, there should be no impls of course... quietly!
  60.243 +        assertEquals(Collections.emptyList(),
  60.244 +                new ArrayList<Object>(l3.lookupAll(xface1)));
  60.245 +        Lookup l4 = getTestedLookup(c4);
  60.246 +        // If we can load Interface but it is the wrong one, ignore it.
  60.247 +        assertEquals(Collections.emptyList(),
  60.248 +                new ArrayList<Object>(l4.lookupAll(xface1)));
  60.249 +        // Make sure l4 is really OK - it can load from its own JARs.
  60.250 +        Class<?> xface4 = c4.loadClass("org.foo.Interface");
  60.251 +        assertEquals(2, l4.lookupAll(xface4).size());
  60.252 +    }
  60.253 +
  60.254 +    public void testStability() throws Exception {
  60.255 +        Lookup l = getTestedLookup(c2);
  60.256 +        Class<?> xface = c1.loadClass("org.foo.Interface");
  60.257 +        Object first = l.lookup(xface);
  60.258 +        assertEquals(first, l.lookupAll(xface).iterator().next());
  60.259 +        l = getTestedLookup(c2a);
  60.260 +        Object second = l.lookup(xface);
  60.261 +        assertEquals(first, second);
  60.262 +    }
  60.263 +
  60.264 +    public void testMaskingOfResources() throws Exception {
  60.265 +        Lookup l1 = getTestedLookup(c1);
  60.266 +        Lookup l2 = getTestedLookup(c2);
  60.267 +        Lookup l4 = getTestedLookup(c4);
  60.268 +
  60.269 +        assertNotNull("services1.jar defines a class that implements runnable", l1.lookup(Runnable.class));
  60.270 +        assertNull("services2.jar does not defines a class that implements runnable", l2.lookup(Runnable.class));
  60.271 +        assertNull("services1.jar defines Runnable, but services2.jar masks it out", l4.lookup(Runnable.class));
  60.272 +    }
  60.273 +
  60.274 +    public void testOrdering() throws Exception {
  60.275 +        Lookup l = getTestedLookup(c1);
  60.276 +        Class<?> xface = c1.loadClass("java.util.Comparator");
  60.277 +        List<?> results = new ArrayList<Object>(l.lookupAll(xface));
  60.278 +        assertEquals(1, results.size());
  60.279 +
  60.280 +        l = getTestedLookup(c2);
  60.281 +        xface = c2.loadClass("java.util.Comparator");
  60.282 +        results = new ArrayList<Object>(l.lookupAll(xface));
  60.283 +        assertEquals(2, results.size());
  60.284 +        // Test order:
  60.285 +        assertEquals("org.bar.Comparator2", results.get(0).getClass().getName());
  60.286 +        assertEquals("org.foo.impl.Comparator1", results.get(1).getClass().getName());
  60.287 +
  60.288 +        // test that items without position are always at the end
  60.289 +        l = getTestedLookup(c2);
  60.290 +        xface = c2.loadClass("java.util.Iterator");
  60.291 +        results = new ArrayList<Object>(l.lookupAll(xface));
  60.292 +        assertEquals(2, results.size());
  60.293 +        // Test order:
  60.294 +        assertEquals("org.bar.Iterator2", results.get(0).getClass().getName());
  60.295 +        assertEquals("org.foo.impl.Iterator1", results.get(1).getClass().getName());
  60.296 +    }
  60.297 +
  60.298 +    public void testNoCallToGetResourceForObjectIssue65124() throws Exception {
  60.299 +        class Loader extends ClassLoader {
  60.300 +            private int counter;
  60.301 +
  60.302 +            @Override
  60.303 +            protected URL findResource(String name) {
  60.304 +                if (name.equals(prefix() + "java.lang.Object")) {
  60.305 +                    counter++;
  60.306 +                }
  60.307 +
  60.308 +                URL retValue;
  60.309 +
  60.310 +                retValue = super.findResource(name);
  60.311 +                return retValue;
  60.312 +            }
  60.313 +
  60.314 +            @Override
  60.315 +            protected Enumeration<URL> findResources(String name) throws IOException {
  60.316 +                if (name.equals(prefix() + "java.lang.Object")) {
  60.317 +                    counter++;
  60.318 +                }
  60.319 +                return super.findResources(name);
  60.320 +            }
  60.321 +        }
  60.322 +        Loader loader = new Loader();
  60.323 +        Lookup l = getTestedLookup(loader);
  60.324 +
  60.325 +        Object no = l.lookup(String.class);
  60.326 +        assertNull("Not found of course", no);
  60.327 +        assertEquals("No lookup of Object", 0, loader.counter);
  60.328 +    }
  60.329 +
  60.330 +    public void testCanGarbageCollectClasses() throws Exception {
  60.331 +        class Loader extends ClassLoader {
  60.332 +            public Loader() {
  60.333 +                super(Loader.class.getClassLoader().getParent());
  60.334 +            }
  60.335 +
  60.336 +            @Override
  60.337 +            protected URL findResource(String name) {
  60.338 +                if (name.equals(prefix() + "java.lang.Runnable")) {
  60.339 +                    return Loader.class.getResource("MetaInfServicesLookupTestRunnable.txt");
  60.340 +                }
  60.341 +
  60.342 +                URL retValue;
  60.343 +
  60.344 +                retValue = super.findResource(name);
  60.345 +                return retValue;
  60.346 +            }
  60.347 +
  60.348 +            @Override
  60.349 +            protected Class<?> findClass(String name) throws ClassNotFoundException {
  60.350 +                if (name.equals("org.openide.util.lookup.MetaInfServicesLookupTestRunnable")) {
  60.351 +                    try {
  60.352 +                        InputStream is = getClass().getResourceAsStream("MetaInfServicesLookupTestRunnable.class");
  60.353 +                        byte[] arr = new byte[is.available()];
  60.354 +                        int read = is.read(arr);
  60.355 +                        assertEquals("Fully read", arr.length, read);
  60.356 +                        return defineClass(name, arr, 0, arr.length);
  60.357 +                    } catch (IOException ex) {
  60.358 +                        throw new ClassNotFoundException("Cannot load", ex);
  60.359 +                    }
  60.360 +                }
  60.361 +                throw new ClassNotFoundException();
  60.362 +            }
  60.363 +
  60.364 +
  60.365 +
  60.366 +            @Override
  60.367 +            protected Enumeration<URL> findResources(String name) throws IOException {
  60.368 +                if (name.equals(prefix() + "java.lang.Runnable")) {
  60.369 +                    return Collections.enumeration(Collections.singleton(findResource(name)));
  60.370 +                }
  60.371 +                return super.findResources(name);
  60.372 +            }
  60.373 +        }
  60.374 +        Loader loader = new Loader();
  60.375 +        Lookup l = getTestedLookup(loader);
  60.376 +
  60.377 +
  60.378 +        Object no = l.lookup(Runnable.class);
  60.379 +        assertNotNull("Found of course", no);
  60.380 +        assertEquals("The right name", "MetaInfServicesLookupTestRunnable", no.getClass().getSimpleName());
  60.381 +        if (no.getClass().getClassLoader() != loader) {
  60.382 +            fail("Wrong classloader: " + no.getClass().getClassLoader());
  60.383 +        }
  60.384 +
  60.385 +        WeakReference<Object> ref = new WeakReference<Object>(no.getClass());
  60.386 +        loader = null;
  60.387 +        no = null;
  60.388 +        l = null;
  60.389 +        lookups.clear();
  60.390 +        MockLookup.setInstances();
  60.391 +        Thread.currentThread().setContextClassLoader(null);
  60.392 +        assertGC("Class can be garbage collected", ref);
  60.393 +    }
  60.394 +
  60.395 +    public void testSuperTypes() throws Exception {
  60.396 +        doTestSuperTypes(createLookup(c2));
  60.397 +        doTestSuperTypes(new ProxyLookup(createLookup(c2)));
  60.398 +    }
  60.399 +    private void doTestSuperTypes(Lookup l) throws Exception {
  60.400 +        final Class<?> xface = c1.loadClass("org.foo.Interface");
  60.401 +        final Lookup.Result<Object> res = l.lookupResult(Object.class);
  60.402 +        assertEquals("Nothing yet", 0, res.allInstances().size());
  60.403 +        final AtomicBoolean event = new AtomicBoolean();
  60.404 +        final Thread here = Thread.currentThread();
  60.405 +        res.addLookupListener(new LookupListener() {
  60.406 +            public void resultChanged(LookupEvent ev) {
  60.407 +                if (Thread.currentThread() == here) {
  60.408 +                    event.set(true);
  60.409 +                }
  60.410 +            }
  60.411 +        });
  60.412 +        assertNotNull("Interface found", l.lookup(xface));
  60.413 +        assertFalse(event.get());
  60.414 +        class W implements Runnable {
  60.415 +            boolean ok;
  60.416 +            public synchronized void run() {
  60.417 +                ok = true;
  60.418 +                notifyAll();
  60.419 +            }
  60.420 +
  60.421 +            public synchronized void await() throws Exception {
  60.422 +                while (!ok) {
  60.423 +                    wait();
  60.424 +                }
  60.425 +            }
  60.426 +        }
  60.427 +        W w = new W();
  60.428 +        MetaInfServicesLookup.RP.execute(w);
  60.429 +        w.await();
  60.430 +        assertEquals("Now two", 2, res.allInstances().size());
  60.431 +    }
  60.432 +    
  60.433 +    public void testWrongOrderAsInIssue100320() throws Exception {
  60.434 +        ClassLoader app = getClass().getClassLoader().getParent();
  60.435 +        ClassLoader c0 = app;
  60.436 +        ClassLoader ctmp = new URLClassLoader(new URL[] {
  60.437 +            findJar("problem100320.jar"),
  60.438 +        }, c0);
  60.439 +        Lookup lookup = Lookups.metaInfServices(ctmp, prefix());
  60.440 +
  60.441 +        Collection<?> colAWT = lookup.lookupAll(IOException.class);
  60.442 +        assertEquals("There is enough objects to switch to InheritanceTree", 12, colAWT.size());
  60.443 +        
  60.444 +        
  60.445 +        List<?> col1 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
  60.446 +        assertEquals("Two", 2, col1.size());
  60.447 +        Collection<?> col2 = lookup.lookupAll(ctmp.loadClass(Comparator2.class.getName()));
  60.448 +        assertEquals("One", 1, col2.size());
  60.449 +        List<?> col3 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
  60.450 +        assertEquals("Two2", 2, col3.size());
  60.451 +        
  60.452 +        Iterator<?> it1 = col1.iterator();
  60.453 +        Iterator<?> it3 = col3.iterator();
  60.454 +        if (
  60.455 +            it1.next() != it3.next() || 
  60.456 +            it1.next() != it3.next() 
  60.457 +        ) {
  60.458 +            fail("Collections are different:\nFirst: " + col1 + "\nLast:  " + col3);
  60.459 +        }
  60.460 +    }
  60.461 +
  60.462 +    public void testContentionWhenLoadingMetainfServices() throws Exception {
  60.463 +        class My extends ClassLoader implements Runnable {
  60.464 +            Lookup query;
  60.465 +            Integer value;
  60.466 +
  60.467 +            public void run() {
  60.468 +                value = query.lookup(Integer.class);
  60.469 +            }
  60.470 +
  60.471 +
  60.472 +            @Override
  60.473 +            protected URL findResource(String name) {
  60.474 +                waitForTask(name);
  60.475 +                return super.findResource(name);
  60.476 +            }
  60.477 +
  60.478 +            @Override
  60.479 +            protected Enumeration<URL> findResources(String name) throws IOException {
  60.480 +                waitForTask(name);
  60.481 +                return super.findResources(name);
  60.482 +            }
  60.483 +
  60.484 +            private synchronized void waitForTask(String name) {
  60.485 +                if (name.startsWith(prefix()) && Thread.currentThread().getName().contains("block")) {
  60.486 +                    try {
  60.487 +                        wait();
  60.488 +                    } catch (InterruptedException ex) {
  60.489 +                        Logger.getLogger("global").log(Level.WARNING, "", ex);
  60.490 +                    }
  60.491 +                }
  60.492 +            }
  60.493 +        }
  60.494 +
  60.495 +        My loader = new My();
  60.496 +        loader.query = createLookup(loader);
  60.497 +        Thread t = new Thread(loader, "block when querying");
  60.498 +        t.start();
  60.499 +        t.join(1000);
  60.500 +
  60.501 +        // this blocks waiting for the waitForTask to finish
  60.502 +        // right now
  60.503 +        Float f = loader.query.lookup(Float.class);
  60.504 +        assertNull("Nothing found", f);
  60.505 +
  60.506 +        synchronized (loader) {
  60.507 +            loader.notifyAll();
  60.508 +        }
  60.509 +        t.join();
  60.510 +
  60.511 +        assertNull("Nothing found", loader.value);
  60.512 +    }
  60.513 +
  60.514 +    public void testInitializerRobustness() throws Exception { // #174055
  60.515 +        check(Broken1.class.getName());
  60.516 +        check(Broken2.class.getName());
  60.517 +    }
  60.518 +    private void check(final String n) {
  60.519 +        assertNull(Lookups.metaInfServices(new ClassLoader() {
  60.520 +            protected @Override Enumeration<URL> findResources(String name) throws IOException {
  60.521 +                if (name.equals("META-INF/services/java.lang.Object")) {
  60.522 +                    return singleton(new URL(null, "dummy:stuff", new URLStreamHandler() {
  60.523 +                        protected URLConnection openConnection(URL u) throws IOException {
  60.524 +                            return new URLConnection(u) {
  60.525 +                                public void connect() throws IOException {}
  60.526 +                                public @Override InputStream getInputStream() throws IOException {
  60.527 +                                    return new ByteArrayInputStream(n.getBytes("UTF-8"));
  60.528 +                                }
  60.529 +                            };
  60.530 +                        }
  60.531 +                    }));
  60.532 +                } else {
  60.533 +                    return Collections.enumeration(Collections.<URL>emptyList());
  60.534 +                }
  60.535 +            }
  60.536 +
  60.537 +        }).lookup(Object.class));
  60.538 +    }
  60.539 +    public static class Broken1 {
  60.540 +        public Broken1() {
  60.541 +            throw new NullPointerException("broken1");
  60.542 +        }
  60.543 +    }
  60.544 +    public static class Broken2 {
  60.545 +        static {
  60.546 +            if (true) { // otherwise javac complains
  60.547 +                throw new NullPointerException("broken2");
  60.548 +            }
  60.549 +        }
  60.550 +    }
  60.551 +
  60.552 +    static <T> Enumeration<T> singleton(T t) {
  60.553 +        return Collections.enumeration(Collections.singleton(t));
  60.554 +    }
  60.555 +}
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.java	Mon Dec 14 20:58:39 2009 +0100
    61.3 @@ -0,0 +1,50 @@
    61.4 +/*
    61.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    61.6 + *
    61.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    61.8 + *
    61.9 + * The contents of this file are subject to the terms of either the GNU
   61.10 + * General Public License Version 2 only ("GPL") or the Common
   61.11 + * Development and Distribution License("CDDL") (collectively, the
   61.12 + * "License"). You may not use this file except in compliance with the
   61.13 + * License. You can obtain a copy of the License at
   61.14 + * http://www.netbeans.org/cddl-gplv2.html
   61.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   61.16 + * specific language governing permissions and limitations under the
   61.17 + * License.  When distributing the software, include this License Header
   61.18 + * Notice in each file and include the License file at
   61.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   61.20 + * particular file as subject to the "Classpath" exception as provided
   61.21 + * by Sun in the GPL Version 2 section of the License file that
   61.22 + * accompanied this code. If applicable, add the following below the
   61.23 + * License Header, with the fields enclosed by brackets [] replaced by
   61.24 + * your own identifying information:
   61.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   61.26 + *
   61.27 + * Contributor(s):
   61.28 + *
   61.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   61.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   61.31 + * Microsystems, Inc. All Rights Reserved.
   61.32 + *
   61.33 + * If you wish your version of this file to be governed by only the CDDL
   61.34 + * or only the GPL Version 2, indicate your decision by adding
   61.35 + * "[Contributor] elects to include this software in this distribution
   61.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   61.37 + * single choice of license, a recipient has the option to distribute
   61.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   61.39 + * to extend the choice of license to its licensees as provided above.
   61.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   61.41 + * Version 2 license, then the option applies only if the new code is
   61.42 + * made subject to such option by the copyright holder.
   61.43 + */
   61.44 +
   61.45 +package org.openide.util.lookup;
   61.46 +
   61.47 +
   61.48 +/**
   61.49 + */
   61.50 +public final class MetaInfServicesLookupTestRunnable implements Runnable {
   61.51 +    public void run() {
   61.52 +    }
   61.53 +}
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.txt	Mon Dec 14 20:58:39 2009 +0100
    62.3 @@ -0,0 +1,1 @@
    62.4 +org.openide.util.lookup.MetaInfServicesLookupTestRunnable
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/NamedServicesLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    63.3 @@ -0,0 +1,85 @@
    63.4 +/*
    63.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    63.6 + *
    63.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    63.8 + *
    63.9 + * The contents of this file are subject to the terms of either the GNU
   63.10 + * General Public License Version 2 only ("GPL") or the Common
   63.11 + * Development and Distribution License("CDDL") (collectively, the
   63.12 + * "License"). You may not use this file except in compliance with the
   63.13 + * License. You can obtain a copy of the License at
   63.14 + * http://www.netbeans.org/cddl-gplv2.html
   63.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   63.16 + * specific language governing permissions and limitations under the
   63.17 + * License.  When distributing the software, include this License Header
   63.18 + * Notice in each file and include the License file at
   63.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   63.20 + * particular file as subject to the "Classpath" exception as provided
   63.21 + * by Sun in the GPL Version 2 section of the License file that
   63.22 + * accompanied this code. If applicable, add the following below the
   63.23 + * License Header, with the fields enclosed by brackets [] replaced by
   63.24 + * your own identifying information:
   63.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   63.26 + *
   63.27 + * Contributor(s):
   63.28 + *
   63.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   63.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   63.31 + * Microsystems, Inc. All Rights Reserved.
   63.32 + *
   63.33 + * If you wish your version of this file to be governed by only the CDDL
   63.34 + * or only the GPL Version 2, indicate your decision by adding
   63.35 + * "[Contributor] elects to include this software in this distribution
   63.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   63.37 + * single choice of license, a recipient has the option to distribute
   63.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   63.39 + * to extend the choice of license to its licensees as provided above.
   63.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   63.41 + * Version 2 license, then the option applies only if the new code is
   63.42 + * made subject to such option by the copyright holder.
   63.43 + */
   63.44 +
   63.45 +package org.openide.util.lookup;
   63.46 +
   63.47 +import org.openide.util.Lookup;
   63.48 +import org.openide.util.test.MockLookup;
   63.49 +
   63.50 +
   63.51 +/** Test finding services from manifest.
   63.52 + * @author Jaroslav Tulach
   63.53 + */
   63.54 +public class NamedServicesLookupTest extends MetaInfServicesLookupTest {
   63.55 +    static {
   63.56 +        MockLookup.init();
   63.57 +    }
   63.58 +    public NamedServicesLookupTest(String name) {
   63.59 +        super(name);
   63.60 +    }
   63.61 +
   63.62 +    @Override
   63.63 +    protected String prefix() {
   63.64 +        return "META-INF/namedservices/sub/path/";
   63.65 +    }
   63.66 +    
   63.67 +    @Override
   63.68 +    protected Lookup createLookup(ClassLoader c) {
   63.69 +        MockLookup.setInstances(c);
   63.70 +        Thread.currentThread().setContextClassLoader(c);
   63.71 +        Lookup l = Lookups.forPath("sub/path");
   63.72 +        return l;
   63.73 +    }
   63.74 +    
   63.75 +    //
   63.76 +    // this is not much inheriting test, as we mask most of the tested methods
   63.77 +    // anyway, but the infrastructure to generate the JAR files is useful
   63.78 +    //
   63.79 +    
   63.80 +    public @Override void testLoaderSkew() {}
   63.81 +    public @Override void testStability() throws Exception {}
   63.82 +    public @Override void testMaskingOfResources() throws Exception {}
   63.83 +    public @Override void testOrdering() throws Exception {}
   63.84 +    public @Override void testNoCallToGetResourceForObjectIssue65124() throws Exception {}
   63.85 +    public @Override void testSuperTypes() throws Exception {}
   63.86 +    public @Override void testWrongOrderAsInIssue100320() throws Exception {}
   63.87 +    
   63.88 +}
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/PathInLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    64.3 @@ -0,0 +1,112 @@
    64.4 +/*
    64.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    64.6 + *
    64.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    64.8 + *
    64.9 + * The contents of this file are subject to the terms of either the GNU
   64.10 + * General Public License Version 2 only ("GPL") or the Common
   64.11 + * Development and Distribution License("CDDL") (collectively, the
   64.12 + * "License"). You may not use this file except in compliance with the
   64.13 + * License. You can obtain a copy of the License at
   64.14 + * http://www.netbeans.org/cddl-gplv2.html
   64.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   64.16 + * specific language governing permissions and limitations under the
   64.17 + * License.  When distributing the software, include this License Header
   64.18 + * Notice in each file and include the License file at
   64.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   64.20 + * particular file as subject to the "Classpath" exception as provided
   64.21 + * by Sun in the GPL Version 2 section of the License file that
   64.22 + * accompanied this code. If applicable, add the following below the
   64.23 + * License Header, with the fields enclosed by brackets [] replaced by
   64.24 + * your own identifying information:
   64.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   64.26 + *
   64.27 + * Contributor(s):
   64.28 + *
   64.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   64.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   64.31 + * Microsystems, Inc. All Rights Reserved.
   64.32 + *
   64.33 + * If you wish your version of this file to be governed by only the CDDL
   64.34 + * or only the GPL Version 2, indicate your decision by adding
   64.35 + * "[Contributor] elects to include this software in this distribution
   64.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   64.37 + * single choice of license, a recipient has the option to distribute
   64.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   64.39 + * to extend the choice of license to its licensees as provided above.
   64.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   64.41 + * Version 2 license, then the option applies only if the new code is
   64.42 + * made subject to such option by the copyright holder.
   64.43 + */
   64.44 +
   64.45 +package org.openide.util.lookup;
   64.46 +
   64.47 +import java.util.logging.Level;
   64.48 +import org.netbeans.junit.MockServices;
   64.49 +import org.netbeans.junit.NbTestCase;
   64.50 +import org.netbeans.modules.openide.util.NamedServicesProvider;
   64.51 +import org.openide.util.Lookup;
   64.52 +
   64.53 +/** 
   64.54 + * @author Jaroslav Tulach
   64.55 + */
   64.56 +public class PathInLookupTest extends NbTestCase {
   64.57 +    static {
   64.58 +        System.setProperty("org.openide.util.Lookup.paths", "MyServices:YourServices");
   64.59 +        MockServices.setServices(P.class);
   64.60 +        Lookup.getDefault();
   64.61 +    }
   64.62 +
   64.63 +    public PathInLookupTest(String name) {
   64.64 +        super(name);
   64.65 +    }
   64.66 +
   64.67 +    @Override
   64.68 +    protected Level logLevel() {
   64.69 +        return Level.FINE;
   64.70 +    }
   64.71 +    
   64.72 +    public void testInterfaceFoundInMyServices() throws Exception {
   64.73 +        assertNull("not found", Lookup.getDefault().lookup(Shared.class));
   64.74 +        Shared v = new Shared();
   64.75 +        P.ic1.add(v);
   64.76 +        assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
   64.77 +        P.ic1.remove(v);
   64.78 +        assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
   64.79 +    }
   64.80 +    public void testInterfaceFoundInMyServices2() throws Exception {
   64.81 +        assertNull("not found", Lookup.getDefault().lookup(Shared.class));
   64.82 +        Shared v = new Shared();
   64.83 +        P.ic2.add(v);
   64.84 +        assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
   64.85 +        P.ic2.remove(v);
   64.86 +        assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
   64.87 +    }
   64.88 +
   64.89 +    static final class Shared extends Object {}
   64.90 +
   64.91 +    public static final class P extends NamedServicesProvider {
   64.92 +        static InstanceContent ic1 = new InstanceContent();
   64.93 +        static InstanceContent ic2 = new InstanceContent();
   64.94 +        static AbstractLookup[] arr = {
   64.95 +            new AbstractLookup(ic1), new AbstractLookup(ic2)
   64.96 +        };
   64.97 +
   64.98 +
   64.99 +        @Override
  64.100 +        public Lookup create(String path) {
  64.101 +            int indx = -1;
  64.102 +            if (path.equals("MyServices/")) {
  64.103 +                indx = 0;
  64.104 +            }
  64.105 +            if (path.equals("YourServices/")) {
  64.106 +                indx = 1;
  64.107 +            }
  64.108 +            if (indx == -1) {
  64.109 +                fail("Unexpected lookup query: " + path);
  64.110 +            }
  64.111 +            return arr[indx];
  64.112 +        }
  64.113 +    }
  64.114 +
  64.115 +}
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/PrefixServicesLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    65.3 @@ -0,0 +1,63 @@
    65.4 +/*
    65.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    65.6 + *
    65.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    65.8 + *
    65.9 + * The contents of this file are subject to the terms of either the GNU
   65.10 + * General Public License Version 2 only ("GPL") or the Common
   65.11 + * Development and Distribution License("CDDL") (collectively, the
   65.12 + * "License"). You may not use this file except in compliance with the
   65.13 + * License. You can obtain a copy of the License at
   65.14 + * http://www.netbeans.org/cddl-gplv2.html
   65.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   65.16 + * specific language governing permissions and limitations under the
   65.17 + * License.  When distributing the software, include this License Header
   65.18 + * Notice in each file and include the License file at
   65.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   65.20 + * particular file as subject to the "Classpath" exception as provided
   65.21 + * by Sun in the GPL Version 2 section of the License file that
   65.22 + * accompanied this code. If applicable, add the following below the
   65.23 + * License Header, with the fields enclosed by brackets [] replaced by
   65.24 + * your own identifying information:
   65.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   65.26 + *
   65.27 + * Contributor(s):
   65.28 + *
   65.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   65.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   65.31 + * Microsystems, Inc. All Rights Reserved.
   65.32 + *
   65.33 + * If you wish your version of this file to be governed by only the CDDL
   65.34 + * or only the GPL Version 2, indicate your decision by adding
   65.35 + * "[Contributor] elects to include this software in this distribution
   65.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   65.37 + * single choice of license, a recipient has the option to distribute
   65.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   65.39 + * to extend the choice of license to its licensees as provided above.
   65.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   65.41 + * Version 2 license, then the option applies only if the new code is
   65.42 + * made subject to such option by the copyright holder.
   65.43 + */
   65.44 +
   65.45 +package org.openide.util.lookup;
   65.46 +
   65.47 +import org.openide.util.Lookup;
   65.48 +
   65.49 +
   65.50 +/** Test finding services from manifest.
   65.51 + * @author Jaroslav Tulach
   65.52 + */
   65.53 +public class PrefixServicesLookupTest extends MetaInfServicesLookupTest {
   65.54 +    public PrefixServicesLookupTest(String name) {
   65.55 +        super(name);
   65.56 +    }
   65.57 +    
   65.58 +    protected String prefix() {
   65.59 +        return "META-INF/netbeans/prefix/services/test/";
   65.60 +    }
   65.61 +    
   65.62 +    protected Lookup createLookup(ClassLoader c) {
   65.63 +        return Lookups.metaInfServices(c, prefix());
   65.64 +    }
   65.65 +    
   65.66 +}
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/ProxyLookup173975Test.java	Mon Dec 14 20:58:39 2009 +0100
    66.3 @@ -0,0 +1,108 @@
    66.4 +/*
    66.5 + * To change this template, choose Tools | Templates
    66.6 + * and open the template in the editor.
    66.7 + */
    66.8 +package org.openide.util.lookup;
    66.9 +
   66.10 +import java.util.Collection;
   66.11 +import java.util.Collections;
   66.12 +import org.junit.Assert;
   66.13 +import org.junit.Test;
   66.14 +import org.openide.util.Lookup;
   66.15 +import org.openide.util.LookupEvent;
   66.16 +import org.openide.util.LookupListener;
   66.17 +import org.openide.util.lookup.AbstractLookup.Storage;
   66.18 +
   66.19 +public class ProxyLookup173975Test {
   66.20 +
   66.21 +    public ProxyLookup173975Test() {
   66.22 +    }
   66.23 +
   66.24 +    boolean called = false;
   66.25 +
   66.26 +    @Test
   66.27 +    public void testAbstractLookupWithoutAllInstances() {
   66.28 +        registerLookupListenerAndAddSomething(false, false, false);
   66.29 +    }
   66.30 +
   66.31 +    @Test
   66.32 +    public void testAbstractLookupWithAllInstances() {
   66.33 +        registerLookupListenerAndAddSomething(false, true, false);
   66.34 +    }
   66.35 +
   66.36 +    @Test
   66.37 +    public void testAbstractLookupInheritanceTreeWithoutAllInstances() {
   66.38 +        registerLookupListenerAndAddSomething(false, false, true);
   66.39 +    }
   66.40 +
   66.41 +    @Test
   66.42 +    public void testAbstractLookupInheritanceTreeWithAllInstances() {
   66.43 +        registerLookupListenerAndAddSomething(false, true, true);
   66.44 +    }
   66.45 +
   66.46 +    @Test
   66.47 +    public void testProxyLookupWithoutAllInstances() {
   66.48 +        registerLookupListenerAndAddSomething(true, false, false);
   66.49 +    }
   66.50 +
   66.51 +    @Test
   66.52 +    public void testProxyLookupWithAllInstances() {
   66.53 +        registerLookupListenerAndAddSomething(true, true, false);
   66.54 +    }
   66.55 +
   66.56 +    @Test
   66.57 +    public void testProxyLookupInheritanceTreeWithoutAllInstances() {
   66.58 +        registerLookupListenerAndAddSomething(true, false, true);
   66.59 +    }
   66.60 +
   66.61 +    @Test
   66.62 +    public void testProxyLookupInheritanceTreeWithAllInstances() {
   66.63 +        registerLookupListenerAndAddSomething(true, true, true);
   66.64 +    }
   66.65 +
   66.66 +    private void registerLookupListenerAndAddSomething(boolean useProxy, boolean callAllInstances, boolean inheritanceTree) {
   66.67 +        called = false;
   66.68 +        InstanceContent aInstanceContent = new InstanceContent();
   66.69 +        Storage<?> s = inheritanceTree ? new InheritanceTree() : new ArrayStorage();
   66.70 +        Lookup aLookup = new AbstractLookup(aInstanceContent, s);
   66.71 +        if (useProxy) {
   66.72 +            aLookup = new ProxyLookup(aLookup);
   66.73 +        }
   66.74 +        Lookup.Result<ObjectInLookup> result = aLookup.lookupResult(ObjectInLookup.class);
   66.75 +        if (callAllInstances) {
   66.76 +            result.allInstances(); // TO GET SUCCESS
   66.77 +        }
   66.78 +        result.addLookupListener(new LookupListener() {
   66.79 +
   66.80 +            public void resultChanged(LookupEvent ev) {
   66.81 +                Lookup.Result aResult = (Lookup.Result) ev.getSource();
   66.82 +                Collection c = aResult.allInstances();
   66.83 +                if (!c.isEmpty()) {
   66.84 +                    called = true;
   66.85 +                }
   66.86 +            }
   66.87 +        });
   66.88 +
   66.89 +        aInstanceContent.set(Collections.singleton(
   66.90 +                new ObjectInLookup("Set Object in Lookup)")), null);
   66.91 +        Assert.assertTrue("Listener was notified", called);
   66.92 +    }
   66.93 +
   66.94 +    public class ObjectInLookup {
   66.95 +
   66.96 +        private final String name;
   66.97 +
   66.98 +        public ObjectInLookup(String name) {
   66.99 +            this.name = name;
  66.100 +        }
  66.101 +
  66.102 +        public String getName() {
  66.103 +            return this.name;
  66.104 +        }
  66.105 +
  66.106 +        @Override
  66.107 +        public String toString() {
  66.108 +            return "objectinlookup:" + getName();
  66.109 +        }
  66.110 +    }
  66.111 +}
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/ProxyLookupEventIssue136866Test.java	Mon Dec 14 20:58:39 2009 +0100
    67.3 @@ -0,0 +1,56 @@
    67.4 +package org.openide.util.lookup;
    67.5 +
    67.6 +import junit.framework.TestCase;
    67.7 +import org.openide.util.Lookup;
    67.8 +import org.openide.util.LookupEvent;
    67.9 +import org.openide.util.LookupListener;
   67.10 +
   67.11 +/**
   67.12 + * Test case which demonstrates that ProxyLookup does not fire
   67.13 + * an event when it should.
   67.14 + */
   67.15 +public class ProxyLookupEventIssue136866Test extends TestCase {
   67.16 +
   67.17 +    public ProxyLookupEventIssue136866Test(String testName) {
   67.18 +        super(testName);
   67.19 +    }
   67.20 +
   67.21 +    public void testAbstractLookupFiresEventWhenContentChanged() {
   67.22 +        InstanceContent ic = new InstanceContent();
   67.23 +        AbstractLookup al = new AbstractLookup(ic);
   67.24 +
   67.25 +        final int[] counts = {0}; // Number of items observed upon a LookupEvent
   67.26 +        final Lookup.Result<String> result = al.lookupResult(String.class);
   67.27 +
   67.28 +        result.addLookupListener(new LookupListener() {
   67.29 +            public void resultChanged(LookupEvent ev) {
   67.30 +                // this gets called as expected
   67.31 +                assertSame(result, ev.getSource());
   67.32 +                counts[0] = result.allInstances().size();
   67.33 +            }
   67.34 +        });
   67.35 +        
   67.36 +        ic.add("hello1");
   67.37 +        assertEquals(1, counts[0]);
   67.38 +    }
   67.39 +    
   67.40 +    public void testProxyLookupFailsToFireEventWhenProxiedLookupChanged() {
   67.41 +        InstanceContent ic = new InstanceContent();
   67.42 +//        AbstractLookup al = new AbstractLookup(ic);
   67.43 +        Lookup proxy = new AbstractLookup(ic);
   67.44 +
   67.45 +        final int[] counts = {0}; // Number of items observed upon a LookupEvent
   67.46 +        final Lookup.Result<String> result = proxy.lookupResult(String.class);
   67.47 +
   67.48 +        result.addLookupListener(new LookupListener() {
   67.49 +            public void resultChanged(LookupEvent ev) {
   67.50 +                // this should be called but never is
   67.51 +                assertSame(result, ev.getSource());
   67.52 +                counts[0] = result.allInstances().size();
   67.53 +            }
   67.54 +        });
   67.55 +        
   67.56 +        ic.add("hello1");
   67.57 +        assertEquals(1, counts[0]);
   67.58 +    }
   67.59 +}
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    68.3 @@ -0,0 +1,655 @@
    68.4 +/*
    68.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    68.6 + *
    68.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    68.8 + *
    68.9 + * The contents of this file are subject to the terms of either the GNU
   68.10 + * General Public License Version 2 only ("GPL") or the Common
   68.11 + * Development and Distribution License("CDDL") (collectively, the
   68.12 + * "License"). You may not use this file except in compliance with the
   68.13 + * License. You can obtain a copy of the License at
   68.14 + * http://www.netbeans.org/cddl-gplv2.html
   68.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   68.16 + * specific language governing permissions and limitations under the
   68.17 + * License.  When distributing the software, include this License Header
   68.18 + * Notice in each file and include the License file at
   68.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   68.20 + * particular file as subject to the "Classpath" exception as provided
   68.21 + * by Sun in the GPL Version 2 section of the License file that
   68.22 + * accompanied this code. If applicable, add the following below the
   68.23 + * License Header, with the fields enclosed by brackets [] replaced by
   68.24 + * your own identifying information:
   68.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   68.26 + *
   68.27 + * Contributor(s):
   68.28 + *
   68.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   68.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   68.31 + * Microsystems, Inc. All Rights Reserved.
   68.32 + *
   68.33 + * If you wish your version of this file to be governed by only the CDDL
   68.34 + * or only the GPL Version 2, indicate your decision by adding
   68.35 + * "[Contributor] elects to include this software in this distribution
   68.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   68.37 + * single choice of license, a recipient has the option to distribute
   68.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   68.39 + * to extend the choice of license to its licensees as provided above.
   68.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   68.41 + * Version 2 license, then the option applies only if the new code is
   68.42 + * made subject to such option by the copyright holder.
   68.43 + */
   68.44 +
   68.45 +package org.openide.util.lookup;
   68.46 +
   68.47 +import java.io.Serializable;
   68.48 +
   68.49 +import java.lang.ref.Reference;
   68.50 +import java.lang.ref.WeakReference;
   68.51 +import java.util.*;
   68.52 +import java.util.concurrent.Executor;
   68.53 +import junit.framework.*;
   68.54 +import org.netbeans.junit.*;
   68.55 +import org.netbeans.modules.openide.util.ActiveQueue;
   68.56 +import org.openide.util.Lookup;
   68.57 +import org.openide.util.Lookup.Result;
   68.58 +import org.openide.util.LookupEvent;
   68.59 +import org.openide.util.LookupListener;
   68.60 +
   68.61 +/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
   68.62 + */
   68.63 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   68.64 +public class ProxyLookupTest extends AbstractLookupBaseHid
   68.65 +implements AbstractLookupBaseHid.Impl {
   68.66 +    public ProxyLookupTest(java.lang.String testName) {
   68.67 +        super(testName, null);
   68.68 +    }
   68.69 +
   68.70 +    public static Test suite() {
   68.71 +        return new NbTestSuite (ProxyLookupTest.class);
   68.72 +//        return new ProxyLookupTest("testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679");
   68.73 +    }
   68.74 +    
   68.75 +    /** Creates an lookup for given lookup. This class just returns 
   68.76 +     * the object passed in, but subclasses can be different.
   68.77 +     * @param lookup in lookup
   68.78 +     * @return a lookup to use
   68.79 +     */
   68.80 +    public Lookup createLookup (Lookup lookup) {
   68.81 +        return new ProxyLookup (new Lookup[] { lookup });
   68.82 +    }
   68.83 +    
   68.84 +    public Lookup createInstancesLookup (InstanceContent ic) {
   68.85 +        return new AbstractLookup (ic);
   68.86 +    }
   68.87 +    
   68.88 +
   68.89 +    public void clearCaches () {
   68.90 +    }    
   68.91 +    
   68.92 +    
   68.93 +    /** Check whether setLookups method does not fire when there is no
   68.94 +     * change in the lookups.
   68.95 +     */
   68.96 +    public void testProxyListener () {
   68.97 +        ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
   68.98 +
   68.99 +        final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
  68.100 +        final Object[] IGNORE = {
  68.101 +            ProxyLookup.ImmutableInternalData.EMPTY,
  68.102 +            ProxyLookup.ImmutableInternalData.EMPTY_ARR,
  68.103 +            ActiveQueue.queue(),
  68.104 +            Collections.emptyMap(),
  68.105 +            Collections.emptyList(),
  68.106 +            Collections.emptySet()
  68.107 +        };
  68.108 +        
  68.109 +        assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
  68.110 +        
  68.111 +        Lookup.Result<Object> res = lookup.lookup (template);
  68.112 +
  68.113 +        assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
  68.114 +        
  68.115 +        LL ll = new LL ();
  68.116 +        res.addLookupListener (ll);
  68.117 +        Collection allRes = res.allInstances ();
  68.118 +        
  68.119 +        lookup.setLookups (new Lookup[0]);
  68.120 +        
  68.121 +        if (ll.getCount () != 0) {
  68.122 +           fail ("Calling setLookups (emptyarray) fired a change");
  68.123 +        }
  68.124 +        
  68.125 +        InstanceContent t = new InstanceContent();
  68.126 +        Lookup del = new AbstractLookup (t);
  68.127 +        t.add("Ahoj");
  68.128 +        lookup.setLookups (new Lookup[] { del });
  68.129 +        
  68.130 +        if (ll.getCount () != 1) {
  68.131 +            fail ("Changing lookups did not generate an event");
  68.132 +        }
  68.133 +        
  68.134 +        lookup.setLookups (new Lookup[] { del });
  68.135 +        
  68.136 +        if (ll.getCount () != 0) {
  68.137 +           fail ("Calling setLookups (thesamearray) fired a change");
  68.138 +        }
  68.139 +    }
  68.140 +    
  68.141 +    public void testNoListenersProxyListener () {
  68.142 +        ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
  68.143 +        class E implements Executor {
  68.144 +            Runnable r;
  68.145 +            public void execute(Runnable command) {
  68.146 +                assertNull("NO previous", r);
  68.147 +                r = command;
  68.148 +            }
  68.149 +            public void perform() {
  68.150 +                assertNotNull("We shall have a runnable", r);
  68.151 +                r.run();
  68.152 +                r = null;
  68.153 +            }
  68.154 +        }
  68.155 +        E executor = new E();
  68.156 +                
  68.157 +
  68.158 +        final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
  68.159 +        final Object[] IGNORE = {
  68.160 +            ProxyLookup.ImmutableInternalData.EMPTY,
  68.161 +            ProxyLookup.ImmutableInternalData.EMPTY_ARR,
  68.162 +            ActiveQueue.queue(),
  68.163 +            Collections.emptyMap(),
  68.164 +            Collections.emptyList(),
  68.165 +            Collections.emptySet()
  68.166 +        };
  68.167 +        
  68.168 +        assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
  68.169 +        
  68.170 +        Lookup.Result<Object> res = lookup.lookup (template);
  68.171 +
  68.172 +        assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
  68.173 +        
  68.174 +        LL ll = new LL ();
  68.175 +        res.addLookupListener (ll);
  68.176 +        Collection allRes = res.allInstances ();
  68.177 +        
  68.178 +        lookup.setLookups (executor, new Lookup[0]);
  68.179 +        if (ll.getCount () != 0) {
  68.180 +           fail ("Calling setLookups (emptyarray) fired a change");
  68.181 +        }
  68.182 +        
  68.183 +        InstanceContent t = new InstanceContent();
  68.184 +        Lookup del = new AbstractLookup (t);
  68.185 +        t.add("Ahoj");
  68.186 +        lookup.setLookups (executor, new Lookup[] { del });
  68.187 +        assertEquals("No change yet", 0, ll.getCount());
  68.188 +        executor.perform();
  68.189 +        if (ll.getCount () != 1) {
  68.190 +            fail ("Changing lookups did not generate an event");
  68.191 +        }
  68.192 +        
  68.193 +        lookup.setLookups (executor, new Lookup[] { del });
  68.194 +        if (ll.getCount () != 0) {
  68.195 +           fail ("Calling setLookups (thesamearray) fired a change");
  68.196 +        }
  68.197 +    }
  68.198 +
  68.199 +    public void testSetLookups () throws Exception {
  68.200 +        AbstractLookup a1 = new AbstractLookup (new InstanceContent ());
  68.201 +        AbstractLookup a2 = new AbstractLookup (new InstanceContent ());
  68.202 +        
  68.203 +        InstanceContent i3 = new InstanceContent ();
  68.204 +        i3.add (i3);
  68.205 +        AbstractLookup a3 = new AbstractLookup (i3);
  68.206 +
  68.207 +        final ProxyLookup p = new ProxyLookup (new Lookup[] { a1, a2 });
  68.208 +        final Lookup.Result res1 = p.lookup (new Lookup.Template (Object.class));
  68.209 +        Collection c1 = res1.allInstances();
  68.210 +        
  68.211 +        Lookup.Result res2 = p.lookup (new Lookup.Template (String.class));
  68.212 +        Collection c2 = res2.allInstances ();
  68.213 +        
  68.214 +        
  68.215 +        assertTrue ("We need two results", res1 != res2);
  68.216 +
  68.217 +        final Object blocked = new Object ();
  68.218 +
  68.219 +        class L extends Object implements LookupListener {
  68.220 +            public void resultChanged (LookupEvent ev) {
  68.221 +                try {
  68.222 +                    res1.removeLookupListener(this);
  68.223 +                    
  68.224 +                    // waiting for second thread to start #111#
  68.225 +                    blocked.wait ();
  68.226 +
  68.227 +                } catch (Exception ex) {
  68.228 +                    ex.printStackTrace();
  68.229 +                    fail ("An exception occured ");
  68.230 +                }
  68.231 +            }
  68.232 +        }
  68.233 +        
  68.234 +        final L listener1 = new L ();
  68.235 +        res1.addLookupListener (listener1);
  68.236 +        
  68.237 +
  68.238 +        Runnable newLookupSetter = new Runnable() {
  68.239 +            public void run () {
  68.240 +                synchronized (blocked) {
  68.241 +                    try {
  68.242 +                        p.setLookups (new Lookup[0]);
  68.243 +                    } catch (Exception ex) {
  68.244 +                        ex.printStackTrace();
  68.245 +                        fail ("setLookups failed.");
  68.246 +                    } finally {
  68.247 +                        // starts the main thread #111#
  68.248 +                        blocked.notify ();
  68.249 +                    }
  68.250 +                }
  68.251 +            }
  68.252 +        };
  68.253 +        
  68.254 +        synchronized (blocked) {
  68.255 +            new Thread (newLookupSetter).start ();
  68.256 +            
  68.257 +            p.setLookups (new Lookup[] { a1, a2, a3 });
  68.258 +        }
  68.259 +    }
  68.260 +    
  68.261 +    public void testProxyLookupTemplateCaching(){
  68.262 +        Lookup lookups[] = new Lookup[1];
  68.263 +        doProxyLookupTemplateCaching(lookups, false);
  68.264 +    }
  68.265 +    
  68.266 +    public void testProxyLookupTemplateCachingOnSizeTwoArray() {
  68.267 +        Lookup lookups[] = new Lookup[2];
  68.268 +        lookups[1] = Lookup.EMPTY;
  68.269 +        doProxyLookupTemplateCaching(lookups, false);
  68.270 +    }
  68.271 +    public void testProxyLookupShallNotAllowModificationOfGetLookups(){
  68.272 +        Lookup lookups[] = new Lookup[1];
  68.273 +        doProxyLookupTemplateCaching(lookups, true);
  68.274 +    }
  68.275 +    
  68.276 +    public void testProxyLookupShallNotAllowModificationOfGetLookupsOnSizeTwoArray() {
  68.277 +        Lookup lookups[] = new Lookup[2];
  68.278 +        lookups[1] = Lookup.EMPTY;
  68.279 +        doProxyLookupTemplateCaching(lookups, true);
  68.280 +    }
  68.281 +    
  68.282 +    /** Index 0 of lookups will be modified, the rest is up to the 
  68.283 +     * setup code.
  68.284 +     */
  68.285 +    private void doProxyLookupTemplateCaching(Lookup[] lookups, boolean reget) {
  68.286 +        // Create MyProxyLookup with one lookup containing the String object
  68.287 +        InstanceContent inst = new InstanceContent();
  68.288 +        inst.add(new String("Hello World")); //NOI18N
  68.289 +        lookups[0] = new AbstractLookup(inst);
  68.290 +        ProxyLookup proxy = new ProxyLookup(lookups);
  68.291 +        if (reget) {
  68.292 +            lookups = proxy.getLookups();
  68.293 +        }
  68.294 +        
  68.295 +        // Performing template lookup for String object
  68.296 +        Lookup.Result result = proxy.lookup(new Lookup.Template(String.class, null, null));
  68.297 +        int stringTemplateResultSize = result.allInstances().size();
  68.298 +        assertEquals ("Ensure, there is only one instance of String.class in proxyLookup:", //NOI18N
  68.299 +                1, stringTemplateResultSize);
  68.300 +        
  68.301 +        // Changing lookup in proxy lookup, now it will contain 
  68.302 +        // StringBuffer Object instead of String
  68.303 +        InstanceContent ic2 = new InstanceContent();
  68.304 +        ic2.add(new Integer(1234567890));
  68.305 +        lookups[0] = new AbstractLookup(ic2);
  68.306 +        proxy.setLookups(lookups);
  68.307 +        
  68.308 +        assertEquals ("the old result is updated", 0, result.allInstances().size());
  68.309 +
  68.310 +        // Instance of String.class should not appear in proxyLookup
  68.311 +        Lookup.Result r2 = proxy.lookup(new Lookup.Template(String.class, null, null));
  68.312 +        assertEquals ("Instance of String.class should not appear in proxyLookup:", //NOI18N
  68.313 +                0, r2.allInstances().size());
  68.314 +
  68.315 +        Lookup.Result r3 = proxy.lookup(new Lookup.Template(Integer.class, null, null));
  68.316 +        assertEquals ("There is only one instance of Integer.class in proxyLookup:", //NOI18N
  68.317 +                1, r3.allInstances().size());
  68.318 +    }
  68.319 +    
  68.320 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
  68.321 +        doListeningAndQueryingByTwoListenersSetLookups(0, 1);
  68.322 +    }
  68.323 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
  68.324 +        doListeningAndQueryingByTwoListenersSetLookups(1, 1);        
  68.325 +    }
  68.326 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
  68.327 +        doListeningAndQueryingByTwoListenersSetLookups(2, 1);
  68.328 +    }
  68.329 +    
  68.330 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
  68.331 +        doListeningAndQueryingByTwoListenersSetLookups(0, 2);
  68.332 +    }
  68.333 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
  68.334 +        doListeningAndQueryingByTwoListenersSetLookups(1, 2);        
  68.335 +    }
  68.336 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
  68.337 +        doListeningAndQueryingByTwoListenersSetLookups(2, 2);
  68.338 +    }
  68.339 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
  68.340 +        doListeningAndQueryingByTwoListenersSetLookups(0, 22);
  68.341 +    }
  68.342 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
  68.343 +        doListeningAndQueryingByTwoListenersSetLookups(1, 22);        
  68.344 +    }
  68.345 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
  68.346 +        doListeningAndQueryingByTwoListenersSetLookups(2, 22);
  68.347 +    }
  68.348 +    
  68.349 +    private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth) {
  68.350 +        ProxyLookup orig = new ProxyLookup();
  68.351 +        ProxyLookup on = orig;
  68.352 +        
  68.353 +        while (--depth > 0) {
  68.354 +            on = new ProxyLookup(new Lookup[] { on });
  68.355 +        }
  68.356 +        
  68.357 +        
  68.358 +        final ProxyLookup lookup = on;
  68.359 +        
  68.360 +        class L implements LookupListener {
  68.361 +            Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
  68.362 +            Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
  68.363 +            Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
  68.364 +            
  68.365 +            {
  68.366 +                integer.addLookupListener(this);
  68.367 +                number.addLookupListener(this);
  68.368 +                serial.addLookupListener(this);
  68.369 +            }
  68.370 +            
  68.371 +            int round;
  68.372 +            
  68.373 +            public void resultChanged(LookupEvent ev) {
  68.374 +                Collection c1 = get(type, integer);
  68.375 +                Collection c2 = get(type, number);
  68.376 +                Collection c3 = get(type, serial);
  68.377 +                
  68.378 +                assertEquals("round " + round + " c1 vs. c2", c1, c2);
  68.379 +                assertEquals("round " + round + " c1 vs. c3", c1, c3);
  68.380 +                assertEquals("round " + round + " c2 vs. c3", c2, c3);
  68.381 +                
  68.382 +                round++;
  68.383 +            }            
  68.384 +
  68.385 +            private Collection get(int type, Lookup.Result res) {
  68.386 +                Collection c;
  68.387 +                switch(type) {
  68.388 +                    case 0: c = res.allInstances(); break;
  68.389 +                    case 1: c = res.allClasses(); break;
  68.390 +                    case 2: c = res.allItems(); break;
  68.391 +                    default: c = null; fail("Type: " + type); break;
  68.392 +                }
  68.393 +                
  68.394 +                assertNotNull(c);
  68.395 +                return new ArrayList(c);
  68.396 +            }
  68.397 +        }
  68.398 +        
  68.399 +        L listener = new L();
  68.400 +        listener.resultChanged(null);
  68.401 +        ArrayList arr = new ArrayList();
  68.402 +        for(int i = 0; i < 100; i++) {
  68.403 +            arr.add(new Integer(i));
  68.404 +            
  68.405 +            orig.setLookups(new Lookup[] { Lookups.fixed(arr.toArray()) });
  68.406 +        }
  68.407 +        
  68.408 +        assertEquals("3x100+1 checks", 301, listener.round);
  68.409 +    }
  68.410 +
  68.411 +    static Object holder;
  68.412 +    
  68.413 +    public void testProxyWithLiveResultCanBeCollected() {
  68.414 +        Lookup layer0 = Lookups.singleton("Hello");
  68.415 +        Lookup layer1 = new ProxyLookup(new Lookup[] { layer0 });
  68.416 +        Lookup layer2 = new ProxyLookup(new Lookup[] { layer1 });
  68.417 +        Lookup.Result result1 = layer1.lookup(new Lookup.Template(String.class));
  68.418 +
  68.419 +        assertEquals("One instance", 1, result1.allInstances().size());
  68.420 +
  68.421 +        // this will create ProxyLookup$R which listens on origResult
  68.422 +        Lookup.Result result2 = layer2.lookup(new Lookup.Template(String.class));
  68.423 +        
  68.424 +        // this line is necessary. W/o actually querying the result,
  68.425 +        // it will nether compute it nor attach the listener.
  68.426 +        assertEquals("One instance", 1, result2.allInstances().size());
  68.427 +        
  68.428 +        result2.addLookupListener(new LookupListener() {
  68.429 +            public void resultChanged(LookupEvent ev) {}
  68.430 +        });
  68.431 +        
  68.432 +        Reference ref = new WeakReference(layer2);
  68.433 +        layer2 = null;
  68.434 +        result2 = null;
  68.435 +        try {
  68.436 +            holder = result1;
  68.437 +            assertGC ("The proxy lookup not been garbage collected!", ref);
  68.438 +        } finally {
  68.439 +            holder = null;
  68.440 +        }
  68.441 +    }
  68.442 +    
  68.443 +    public void testArrayIndexAsInIssue119292() throws Exception {
  68.444 +        final ProxyLookup pl = new ProxyLookup();
  68.445 +        final int[] cnt = { 0 };
  68.446 +        
  68.447 +        class L extends Lookup {
  68.448 +            L[] set;
  68.449 +            Lookup l;
  68.450 +            
  68.451 +            public L(String s) {
  68.452 +                l = Lookups.singleton(s);
  68.453 +            }
  68.454 +            
  68.455 +            @Override
  68.456 +            public <T> T lookup(Class<T> clazz) {
  68.457 +                return l.lookup(clazz);
  68.458 +            }
  68.459 +
  68.460 +            @Override
  68.461 +            public <T> Result<T> lookup(Template<T> template) {
  68.462 +                return l.lookup(template);
  68.463 +            }
  68.464 +
  68.465 +            @Override
  68.466 +            @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
  68.467 +            public boolean equals(Object obj) {
  68.468 +                if (set != null) {
  68.469 +                    cnt[0]++;
  68.470 +                    pl.setLookups(set);
  68.471 +                }
  68.472 +                return super.equals(obj);
  68.473 +            }
  68.474 +
  68.475 +            @Override
  68.476 +            public int hashCode() {
  68.477 +                int hash = 3;
  68.478 +                return hash;
  68.479 +            }
  68.480 +        }
  68.481 +
  68.482 +        Result<String> res = pl.lookupResult(String.class);
  68.483 +        assertEquals(Collections.EMPTY_LIST, res.allItems());
  68.484 +        
  68.485 +        L[] old = { new L("A"), new L("B") };
  68.486 +        L[] now = { new L("C") };
  68.487 +        
  68.488 +        pl.setLookups(old);
  68.489 +        cnt[0] = 0;
  68.490 +        
  68.491 +        old[0].set = new L[0];
  68.492 +        pl.setLookups(now);
  68.493 +
  68.494 +        assertEquals("No call to equals", 0, cnt[0]);
  68.495 +        
  68.496 +        assertEquals("Still assigned to C", Collections.singletonList("C"), res.allInstances());
  68.497 +    }
  68.498 +    
  68.499 +    public void testArrayIndexWithAddRemoveListenerAsInIssue119292() throws Exception {
  68.500 +        final ProxyLookup pl = new ProxyLookup();
  68.501 +        final int[] cnt = { 0 };
  68.502 +        
  68.503 +        class L extends Lookup {
  68.504 +            L[] set;
  68.505 +            Lookup l;
  68.506 +            
  68.507 +            public L(String s) {
  68.508 +                l = Lookups.singleton(s);
  68.509 +            }
  68.510 +            
  68.511 +            @Override
  68.512 +            public <T> T lookup(Class<T> clazz) {
  68.513 +                return l.lookup(clazz);
  68.514 +            }
  68.515 +
  68.516 +            @Override
  68.517 +            public <T> Result<T> lookup(Template<T> template) {
  68.518 +                Result<T> r = l.lookup(template);
  68.519 +                return new R<T>(r);
  68.520 +            }
  68.521 +
  68.522 +            final class R<T> extends Result<T> {
  68.523 +                private Result<T> delegate;
  68.524 +
  68.525 +                public R(Result<T> delegate) {
  68.526 +                    this.delegate = delegate;
  68.527 +                }
  68.528 +                
  68.529 +                @Override
  68.530 +                public void addLookupListener(LookupListener l) {
  68.531 +                    cnt[0]++;
  68.532 +                    if (set != null) {
  68.533 +                        pl.setLookups(set);
  68.534 +                    }
  68.535 +                    delegate.addLookupListener(l);
  68.536 +                }
  68.537 +
  68.538 +                @Override
  68.539 +                public void removeLookupListener(LookupListener l) {
  68.540 +                    cnt[0]++;
  68.541 +                    if (set != null) {
  68.542 +                        pl.setLookups(set);
  68.543 +                    }
  68.544 +                    delegate.removeLookupListener(l);
  68.545 +                }
  68.546 +
  68.547 +                @Override
  68.548 +                public Collection<? extends T> allInstances() {
  68.549 +                    return delegate.allInstances();
  68.550 +                }
  68.551 +            }
  68.552 +        }
  68.553 +
  68.554 +        Result<String> res = pl.lookupResult(String.class);
  68.555 +        assertEquals(Collections.EMPTY_LIST, res.allItems());
  68.556 +        
  68.557 +        L[] old = { new L("A"), new L("B") };
  68.558 +        L[] now = { new L("C") };
  68.559 +        
  68.560 +        pl.setLookups(old);
  68.561 +        cnt[0] = 0;
  68.562 +        
  68.563 +        old[0].set = new L[0];
  68.564 +        pl.setLookups(now);
  68.565 +
  68.566 +        if (cnt[0] == 0) {
  68.567 +            fail("There should be calls to listeners");
  68.568 +        }
  68.569 +        
  68.570 +        assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances());
  68.571 +    }
  68.572 +    
  68.573 +    
  68.574 +    public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception {
  68.575 +        final ProxyLookup pl = new ProxyLookup();
  68.576 +        final int[] cnt = { 0 };
  68.577 +        
  68.578 +        class L extends Lookup {
  68.579 +            L[] set;
  68.580 +            Lookup l;
  68.581 +            Collection<? extends Serializable> res;
  68.582 +            
  68.583 +            public L(String s) {
  68.584 +                l = Lookups.singleton(s);
  68.585 +            }
  68.586 +            
  68.587 +            @Override
  68.588 +            public <T> T lookup(Class<T> clazz) {
  68.589 +                return l.lookup(clazz);
  68.590 +            }
  68.591 +
  68.592 +            @Override
  68.593 +            public <T> Result<T> lookup(Template<T> template) {
  68.594 +                cnt[0]++;
  68.595 +                if (set != null) {
  68.596 +                    pl.setLookups(set);
  68.597 +                    res = pl.lookupAll(Serializable.class);
  68.598 +                }
  68.599 +                Result<T> r = l.lookup(template);
  68.600 +                return r;
  68.601 +            }
  68.602 +        }
  68.603 +
  68.604 +        L[] now = { new L("A"), new L("B") };
  68.605 +        L[] old = { new L("C") };
  68.606 +        pl.setLookups(old);
  68.607 +        old[0].set = now;
  68.608 +        
  68.609 +        Result<String> res = pl.lookupResult(String.class);
  68.610 +        assertEquals("New items visible", 2, res.allItems().size());
  68.611 +        
  68.612 +        
  68.613 +        pl.setLookups(new L("X"), new L("Y"), new L("Z"));
  68.614 +    }
  68.615 +    
  68.616 +    public void testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679() throws Exception {
  68.617 +        final ProxyLookup pl = new ProxyLookup();
  68.618 +        final int[] cnt = { 0 };
  68.619 +        
  68.620 +        class L extends Lookup {
  68.621 +            L[] set;
  68.622 +            Lookup l;
  68.623 +            Collection<? extends Serializable> res;
  68.624 +            
  68.625 +            public L(String s) {
  68.626 +                l = Lookups.singleton(s);
  68.627 +            }
  68.628 +            
  68.629 +            @Override
  68.630 +            public <T> T lookup(Class<T> clazz) {
  68.631 +                return l.lookup(clazz);
  68.632 +            }
  68.633 +
  68.634 +            @Override
  68.635 +            public <T> Result<T> lookup(Template<T> template) {
  68.636 +                cnt[0]++;
  68.637 +                if (set != null) {
  68.638 +                    pl.setLookups(set);
  68.639 +                    res = pl.lookupAll(Serializable.class);
  68.640 +                }
  68.641 +                Result<T> r = l.lookup(template);
  68.642 +                return r;
  68.643 +            }
  68.644 +        }
  68.645 +
  68.646 +        L dupl = new L("A");
  68.647 +        L[] now = { dupl };
  68.648 +        L[] old = { new L("C") };
  68.649 +        pl.setLookups(old);
  68.650 +        old[0].set = now;
  68.651 +        
  68.652 +        Result<String> res = pl.lookupResult(String.class);
  68.653 +        assertEquals("New items visible", 1, res.allItems().size());
  68.654 +        
  68.655 +        
  68.656 +        pl.setLookups(old);
  68.657 +    }
  68.658 +}
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/SimpleLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    69.3 @@ -0,0 +1,351 @@
    69.4 +/*
    69.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    69.6 + *
    69.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    69.8 + *
    69.9 + * The contents of this file are subject to the terms of either the GNU
   69.10 + * General Public License Version 2 only ("GPL") or the Common
   69.11 + * Development and Distribution License("CDDL") (collectively, the
   69.12 + * "License"). You may not use this file except in compliance with the
   69.13 + * License. You can obtain a copy of the License at
   69.14 + * http://www.netbeans.org/cddl-gplv2.html
   69.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   69.16 + * specific language governing permissions and limitations under the
   69.17 + * License.  When distributing the software, include this License Header
   69.18 + * Notice in each file and include the License file at
   69.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   69.20 + * particular file as subject to the "Classpath" exception as provided
   69.21 + * by Sun in the GPL Version 2 section of the License file that
   69.22 + * accompanied this code. If applicable, add the following below the
   69.23 + * License Header, with the fields enclosed by brackets [] replaced by
   69.24 + * your own identifying information:
   69.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   69.26 + *
   69.27 + * Contributor(s):
   69.28 + *
   69.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   69.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
   69.31 + * Microsystems, Inc. All Rights Reserved.
   69.32 + *
   69.33 + * If you wish your version of this file to be governed by only the CDDL
   69.34 + * or only the GPL Version 2, indicate your decision by adding
   69.35 + * "[Contributor] elects to include this software in this distribution
   69.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   69.37 + * single choice of license, a recipient has the option to distribute
   69.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   69.39 + * to extend the choice of license to its licensees as provided above.
   69.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   69.41 + * Version 2 license, then the option applies only if the new code is
   69.42 + * made subject to such option by the copyright holder.
   69.43 + */
   69.44 +
   69.45 +package org.openide.util.lookup;
   69.46 +
   69.47 +import java.util.ArrayList;
   69.48 +import java.util.Arrays;
   69.49 +import java.util.Collection;
   69.50 +import java.util.List;
   69.51 +import java.util.Set;
   69.52 +import org.netbeans.junit.NbTestCase;
   69.53 +import org.openide.util.Lookup;
   69.54 +
   69.55 +/**
   69.56 + * Tests for class SimpleLookup.
   69.57 + * @author David Strupl
   69.58 + */
   69.59 +public class SimpleLookupTest extends NbTestCase {
   69.60 +
   69.61 +    public SimpleLookupTest(String testName) {
   69.62 +        super(testName);
   69.63 +    }
   69.64 +
   69.65 +    public void testEmptyLookup() {
   69.66 +        assertSize("Lookup.EMPTY should be small", 8, Lookup.EMPTY);
   69.67 +    }
   69.68 +
   69.69 +    /**
   69.70 +     * Simple tests testing singleton lookup.
   69.71 +     */
   69.72 +    public void testSingleton() {
   69.73 +        //
   69.74 +        Object orig = new Object();
   69.75 +        Lookup p1 = Lookups.singleton(orig);
   69.76 +        Object obj = p1.lookup(Object.class);
   69.77 +        assertTrue(obj == orig);
   69.78 +        assertNull(p1.lookup(String.class)); 
   69.79 +        assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
   69.80 +        //
   69.81 +        Lookup p2 = Lookups.singleton("test");
   69.82 +        assertNotNull(p2.lookup(Object.class));
   69.83 +        assertNotNull(p2.lookup(String.class));
   69.84 +        assertNotNull(p2.lookup(java.io.Serializable.class));
   69.85 +    }
   69.86 +    
   69.87 +    public void testEmptyFixed() {
   69.88 +        Lookup l = Lookups.fixed();
   69.89 +        assertSize("Lookups.fixed() for empty list of items should be small", 8, l);
   69.90 +        assertSame(Lookup.EMPTY, l);
   69.91 +    }
   69.92 +
   69.93 +    public void testSingleItemFixed() {
   69.94 +        Object o = new Object();
   69.95 +        Lookup l = Lookups.fixed(o);
   69.96 +        assertSize("Lookups.fixed(o) for a single item should be small", 24, l);
   69.97 +    }
   69.98 +
   69.99 +    /**
  69.100 +     * Simple tests testing fixed lookup.
  69.101 +     */
  69.102 +    public void testFixed() {
  69.103 +        //
  69.104 +        Object[] orig = new Object[] { new Object(), new Object() };
  69.105 +        Lookup p1 = Lookups.fixed(orig);
  69.106 +        Object obj = p1.lookup(Object.class);
  69.107 +        assertTrue(obj == orig[0] || obj == orig[1]);
  69.108 +        assertNull(p1.lookup(String.class)); 
  69.109 +        //
  69.110 +        String[] s = new String[] { "test1", "test2" };
  69.111 +        Lookup p2 = Lookups.fixed((Object[]) s);
  69.112 +        Object obj2 = p2.lookup(Object.class);
  69.113 +        assertNotNull(obj2);
  69.114 +        if (obj2 != s[0] && obj2 != s[1]) {
  69.115 +            fail("Returned objects are not the originals");
  69.116 +        }
  69.117 +        assertNotNull(p2.lookup(String.class));
  69.118 +        assertNotNull(p2.lookup(java.io.Serializable.class));
  69.119 +        Lookup.Template<String> t = new Lookup.Template<String>(String.class);
  69.120 +        Lookup.Result<String> r = p2.lookup(t);
  69.121 +        Collection<? extends String> all = r.allInstances();
  69.122 +        assertTrue(all.size() == 2);
  69.123 +        for (String o : all) {
  69.124 +            assertTrue("allInstances contains wrong objects", o.equals(s[0]) || o.equals(s[1]));
  69.125 +        }
  69.126 +        
  69.127 +        try {
  69.128 +            Lookups.fixed(new Object[] {null});
  69.129 +            fail("No nulls are allowed");
  69.130 +        } catch (NullPointerException ex) {
  69.131 +            // ok, NPE is what we want
  69.132 +        }        
  69.133 +    }
  69.134 +
  69.135 +    public void testFixedSubtypes() {
  69.136 +        class A {}
  69.137 +        class B extends A {}
  69.138 +        Lookup l = Lookups.fixed(new A(), new B());
  69.139 +        assertEquals(1, l.lookupAll(B.class).size());
  69.140 +        assertEquals(2, l.lookupAll(A.class).size());
  69.141 +    }
  69.142 +
  69.143 +    /**
  69.144 +     * Simple tests testing converting lookup.
  69.145 +     */
  69.146 +    public void testConverting() {
  69.147 +        //
  69.148 +        String[] orig = new String[] { TestConvertor.TEST1, TestConvertor.TEST2 };
  69.149 +        TestConvertor convertor = new TestConvertor();
  69.150 +        Lookup p1 = Lookups.fixed(orig, convertor);
  69.151 +        assertNull("Converting from String to Integer - it should not find String in result", p1.lookup(String.class));
  69.152 +        assertNotNull(p1.lookup(Integer.class));
  69.153 +        assertNotNull(p1.lookup(Integer.class));
  69.154 +        assertTrue("Convertor should be called only once.", convertor.getNumberOfConvertCalls() == 1); 
  69.155 +        Lookup.Template<Integer> t = new Lookup.Template<Integer>(Integer.class);
  69.156 +        Lookup.Result<Integer> r = p1.lookup(t);
  69.157 +        Collection<? extends Integer> all = r.allInstances();
  69.158 +        assertTrue(all.size() == 2);
  69.159 +        for (int i : all) {
  69.160 +            assertTrue("allInstances contains wrong objects", i == TestConvertor.t1 || i == TestConvertor.t2);
  69.161 +        }
  69.162 +    }
  69.163 +    
  69.164 +    private static class TestConvertor implements InstanceContent.Convertor<String,Integer> {
  69.165 +        static final String TEST1 = "test1";
  69.166 +        static final int t1 = 1;
  69.167 +        static final String TEST2 = "test2";
  69.168 +        static final int t2 = 2;
  69.169 +        
  69.170 +        private int numberOfConvertCalls = 0;
  69.171 +        
  69.172 +        public Integer convert(String obj) {
  69.173 +            numberOfConvertCalls++;
  69.174 +            if (obj.equals(TEST1)) {
  69.175 +                return t1;
  69.176 +            }
  69.177 +            if (obj.equals(TEST2)) {
  69.178 +                return t2;
  69.179 +            }
  69.180 +            throw new IllegalArgumentException();
  69.181 +        }
  69.182 +        
  69.183 +        public String displayName(String obj) {
  69.184 +            return obj;
  69.185 +        }
  69.186 +        
  69.187 +        public String id(String obj) {
  69.188 +            if (obj.equals(TEST1)) {
  69.189 +                return TEST1;
  69.190 +            }
  69.191 +            if (obj.equals(TEST2)) {
  69.192 +                return TEST2;
  69.193 +            }
  69.194 +            return null;
  69.195 +        }
  69.196 +        
  69.197 +        public Class<? extends Integer> type(String obj) {
  69.198 +            return Integer.class;
  69.199 +        }
  69.200 +        
  69.201 +        int getNumberOfConvertCalls() { 
  69.202 +            return numberOfConvertCalls;
  69.203 +        }
  69.204 +    }
  69.205 +    
  69.206 +    public void testLookupItem() {
  69.207 +        SomeInst inst = new SomeInst();
  69.208 +        Lookup.Item item = Lookups.lookupItem(inst, "XYZ");
  69.209 +        
  69.210 +        assertTrue("Wrong instance", item.getInstance() == inst);
  69.211 +        assertTrue("Wrong instance class", item.getType() == inst.getClass());
  69.212 +        assertEquals("Wrong id", "XYZ", item.getId());
  69.213 +
  69.214 +        item = Lookups.lookupItem(inst, null);
  69.215 +        assertNotNull("Id must never be null", item.getId());
  69.216 +    }
  69.217 +
  69.218 +    public void testLookupItemEquals() {
  69.219 +        SomeInst instA = new SomeInst();
  69.220 +        SomeInst instB = new SomeInst();
  69.221 +        Lookup.Item itemA = Lookups.lookupItem(instA, null);
  69.222 +        Lookup.Item itemB = Lookups.lookupItem(instB, null);
  69.223 +        
  69.224 +        assertTrue("Lookup items shouldn't be equal", !itemA.equals(itemB) && !itemB.equals(itemA));
  69.225 +
  69.226 +        itemA = Lookups.lookupItem(instA, null);
  69.227 +        itemB = Lookups.lookupItem(instA, null); // same instance
  69.228 +
  69.229 +        assertTrue("Lookup items should be equal", itemA.equals(itemB) && itemB.equals(itemA));
  69.230 +        assertTrue("Lookup items hashcode should be same", itemA.hashCode() == itemB.hashCode());
  69.231 +
  69.232 +        itemA = Lookups.lookupItem(new String("VOKURKA"), null);
  69.233 +        itemB = Lookups.lookupItem(new String("VOKURKA"), null);
  69.234 +
  69.235 +        assertTrue("Lookup items shouldn't be equal (2)", !itemA.equals(itemB) && !itemB.equals(itemA));
  69.236 +    }
  69.237 +    
  69.238 +    public void testAllClassesIssue42399 () throws Exception {
  69.239 +        Object[] arr = { "Ahoj", new Object () };
  69.240 +        
  69.241 +        Lookup l = Lookups.fixed (arr);
  69.242 +        
  69.243 +        Set<Class<? extends Object>> s = l.lookup(new Lookup.Template<Object>(Object.class)).allClasses();
  69.244 +        
  69.245 +        assertEquals ("Two there", 2, s.size ());
  69.246 +        assertTrue ("Contains Object.class", s.contains (Object.class));
  69.247 +        assertTrue ("Contains string", s.contains (String.class));
  69.248 +        
  69.249 +    }
  69.250 +
  69.251 +    public void testLookupItemEarlyInitializationProblem() {
  69.252 +        InstanceContent ic = new InstanceContent();
  69.253 +        AbstractLookup al = new AbstractLookup(ic);
  69.254 +        LI item = new LI();
  69.255 +        List<AbstractLookup.Pair> pairs1 = new ArrayList<AbstractLookup.Pair>();
  69.256 +        List<AbstractLookup.Pair> pairs2 = new ArrayList<AbstractLookup.Pair>();
  69.257 +        
  69.258 +        assertEquals("Item's instance shouldn't be requested", 0, item.cnt);
  69.259 +
  69.260 +        pairs1.add(new ItemPair<Object>(Lookups.<Object>lookupItem(new SomeInst(), null)));
  69.261 +        pairs1.add(new ItemPair<Object>(item));
  69.262 +        pairs1.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
  69.263 +
  69.264 +        pairs2.add(new ItemPair<Object>(item));
  69.265 +        pairs2.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
  69.266 +
  69.267 +        ic.setPairs(pairs1);
  69.268 +        ic.setPairs(pairs2);
  69.269 +
  69.270 +        assertEquals("Item's instance shouldn't be requested when added to lookup", 0, item.cnt);
  69.271 +        
  69.272 +        LI item2 = al.lookup(LI.class);
  69.273 +        assertEquals("Item's instance should be requested", 1, item.cnt);
  69.274 +    }
  69.275 +
  69.276 +    public void testConvenienceMethods() throws Exception {
  69.277 +        // Just check signatures and basic behavior of #73848.
  69.278 +        Lookup l = Lookups.fixed(new Object[] {1, "hello", 2, "goodbye"});
  69.279 +        Collection<? extends Integer> ints = l.lookupAll(Integer.class);
  69.280 +        assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
  69.281 +        Lookup.Result<Integer> r = l.lookupResult(Integer.class);
  69.282 +        ints = r.allInstances();
  69.283 +        assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
  69.284 +    }
  69.285 +    
  69.286 +    private static class SomeInst { }
  69.287 +    
  69.288 +    private static class LI extends Lookup.Item<Object> {
  69.289 +
  69.290 +        public long cnt = 0;
  69.291 +        
  69.292 +        public String getDisplayName() {
  69.293 +            return getId();
  69.294 +        }
  69.295 +
  69.296 +        public String getId() {
  69.297 +            return getClass() + "@" + hashCode();
  69.298 +        }
  69.299 +
  69.300 +        public Object getInstance() {
  69.301 +            cnt++;
  69.302 +            return this;
  69.303 +        }
  69.304 +
  69.305 +        public Class<? extends Object> getType() {
  69.306 +            return getClass();
  69.307 +        }
  69.308 +    } // End of LI class
  69.309 +
  69.310 +    private static class ItemPair<T> extends AbstractLookup.Pair<T> {
  69.311 +        
  69.312 +        private AbstractLookup.Item<T> item;
  69.313 +        
  69.314 +        public ItemPair(Lookup.Item<T> i) {
  69.315 +            this.item = i;
  69.316 +        }
  69.317 +
  69.318 +        protected boolean creatorOf(Object obj) {
  69.319 +            return item.getInstance() == obj;
  69.320 +        }
  69.321 +
  69.322 +        public String getDisplayName() {
  69.323 +            return item.getDisplayName ();
  69.324 +        }
  69.325 +
  69.326 +        public String getId() {
  69.327 +            return item.getId ();
  69.328 +        }
  69.329 +
  69.330 +        public T getInstance() {
  69.331 +            return item.getInstance ();
  69.332 +        }
  69.333 +
  69.334 +        public Class<? extends T> getType() {
  69.335 +            return item.getType ();
  69.336 +        }
  69.337 +
  69.338 +        protected boolean instanceOf(Class<?> c) {
  69.339 +            return c.isAssignableFrom(getType());
  69.340 +        }
  69.341 +
  69.342 +        public @Override boolean equals(Object o) {
  69.343 +            if (o instanceof ItemPair) {
  69.344 +                ItemPair p = (ItemPair)o;
  69.345 +                return item.equals (p.item);
  69.346 +            }
  69.347 +            return false;
  69.348 +        }
  69.349 +
  69.350 +        public @Override int hashCode() {
  69.351 +            return item.hashCode ();
  69.352 +        }
  69.353 +    } // end of ItemPair
  69.354 +}
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/SimpleProxyLookupIssue42244Test.java	Mon Dec 14 20:58:39 2009 +0100
    70.3 @@ -0,0 +1,120 @@
    70.4 +/*
    70.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    70.6 + *
    70.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    70.8 + *
    70.9 + * The contents of this file are subject to the terms of either the GNU
   70.10 + * General Public License Version 2 only ("GPL") or the Common
   70.11 + * Development and Distribution License("CDDL") (collectively, the
   70.12 + * "License"). You may not use this file except in compliance with the
   70.13 + * License. You can obtain a copy of the License at
   70.14 + * http://www.netbeans.org/cddl-gplv2.html
   70.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   70.16 + * specific language governing permissions and limitations under the
   70.17 + * License.  When distributing the software, include this License Header
   70.18 + * Notice in each file and include the License file at
   70.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   70.20 + * particular file as subject to the "Classpath" exception as provided
   70.21 + * by Sun in the GPL Version 2 section of the License file that
   70.22 + * accompanied this code. If applicable, add the following below the
   70.23 + * License Header, with the fields enclosed by brackets [] replaced by
   70.24 + * your own identifying information:
   70.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   70.26 + *
   70.27 + * Contributor(s):
   70.28 + *
   70.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   70.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   70.31 + * Microsystems, Inc. All Rights Reserved.
   70.32 + *
   70.33 + * If you wish your version of this file to be governed by only the CDDL
   70.34 + * or only the GPL Version 2, indicate your decision by adding
   70.35 + * "[Contributor] elects to include this software in this distribution
   70.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   70.37 + * single choice of license, a recipient has the option to distribute
   70.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   70.39 + * to extend the choice of license to its licensees as provided above.
   70.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   70.41 + * Version 2 license, then the option applies only if the new code is
   70.42 + * made subject to such option by the copyright holder.
   70.43 + */
   70.44 +
   70.45 +package org.openide.util.lookup;
   70.46 +
   70.47 +import java.lang.ref.WeakReference;
   70.48 +import java.util.*;
   70.49 +import junit.framework.*;
   70.50 +import org.netbeans.junit.*;
   70.51 +import org.openide.util.Lookup;
   70.52 +
   70.53 +/** To simulate issue 42244.
   70.54 + */
   70.55 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   70.56 +public class SimpleProxyLookupIssue42244Test extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
   70.57 +    public SimpleProxyLookupIssue42244Test (java.lang.String testName) {
   70.58 +        super(testName, null);
   70.59 +    }
   70.60 +
   70.61 +    public static Test suite() {
   70.62 +        // return new SimpleProxyLookupIssue42244Test("testGarbageCollect");
   70.63 +        return new NbTestSuite(SimpleProxyLookupIssue42244Test.class);
   70.64 +    }
   70.65 +    
   70.66 +    /** Creates an lookup for given lookup. This class just returns 
   70.67 +     * the object passed in, but subclasses can be different.
   70.68 +     * @param lookup in lookup
   70.69 +     * @return a lookup to use
   70.70 +     */
   70.71 +    public Lookup createLookup (final Lookup lookup) {
   70.72 +        class C implements Lookup.Provider {
   70.73 +            public Lookup getLookup () {
   70.74 +                return lookup;
   70.75 +            }
   70.76 +        }
   70.77 +        return Lookups.proxy (new C ());
   70.78 +    }
   70.79 +    
   70.80 +    public Lookup createInstancesLookup (InstanceContent ic) {
   70.81 +        return new KeepResultsProxyLookup (new AbstractLookup (ic));
   70.82 +    }
   70.83 +    
   70.84 +    public void clearCaches () {
   70.85 +        KeepResultsProxyLookup k = (KeepResultsProxyLookup)this.instanceLookup;
   70.86 +        
   70.87 +        ArrayList toGC = new ArrayList ();
   70.88 +        Iterator it = k.allQueries.iterator ();
   70.89 +        while (it.hasNext ()) {
   70.90 +            Lookup.Result r = (Lookup.Result)it.next ();
   70.91 +            toGC.add (new WeakReference (r));
   70.92 +        }
   70.93 +        
   70.94 +        k.allQueries = null;
   70.95 +        
   70.96 +        it = toGC.iterator ();
   70.97 +        while (it.hasNext ()) {
   70.98 +            WeakReference r = (WeakReference)it.next ();
   70.99 +            assertGC ("Trying to release all results from memory", r);
  70.100 +        }
  70.101 +    }
  70.102 +    
  70.103 +    class KeepResultsProxyLookup extends ProxyLookup {
  70.104 +        private ArrayList allQueries = new ArrayList ();
  70.105 +        private ThreadLocal in = new ThreadLocal ();
  70.106 +        
  70.107 +        public KeepResultsProxyLookup (Lookup delegate) {
  70.108 +            super (new Lookup[] { delegate });
  70.109 +        }
  70.110 +        
  70.111 +        @Override
  70.112 +        protected void beforeLookup (org.openide.util.Lookup.Template template) {
  70.113 +            super.beforeLookup (template);
  70.114 +            if (allQueries != null && in.get () == null) {
  70.115 +                in.set (this);
  70.116 +                Lookup.Result res = lookup (template);
  70.117 +                allQueries.add (res);
  70.118 +                in.set (null);
  70.119 +            }
  70.120 +        }
  70.121 +        
  70.122 +    }
  70.123 +}
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/SimpleProxyLookupSpeedIssue42244Test.java	Mon Dec 14 20:58:39 2009 +0100
    71.3 @@ -0,0 +1,118 @@
    71.4 +/*
    71.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    71.6 + *
    71.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    71.8 + *
    71.9 + * The contents of this file are subject to the terms of either the GNU
   71.10 + * General Public License Version 2 only ("GPL") or the Common
   71.11 + * Development and Distribution License("CDDL") (collectively, the
   71.12 + * "License"). You may not use this file except in compliance with the
   71.13 + * License. You can obtain a copy of the License at
   71.14 + * http://www.netbeans.org/cddl-gplv2.html
   71.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   71.16 + * specific language governing permissions and limitations under the
   71.17 + * License.  When distributing the software, include this License Header
   71.18 + * Notice in each file and include the License file at
   71.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   71.20 + * particular file as subject to the "Classpath" exception as provided
   71.21 + * by Sun in the GPL Version 2 section of the License file that
   71.22 + * accompanied this code. If applicable, add the following below the
   71.23 + * License Header, with the fields enclosed by brackets [] replaced by
   71.24 + * your own identifying information:
   71.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   71.26 + *
   71.27 + * Contributor(s):
   71.28 + *
   71.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   71.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   71.31 + * Microsystems, Inc. All Rights Reserved.
   71.32 + *
   71.33 + * If you wish your version of this file to be governed by only the CDDL
   71.34 + * or only the GPL Version 2, indicate your decision by adding
   71.35 + * "[Contributor] elects to include this software in this distribution
   71.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   71.37 + * single choice of license, a recipient has the option to distribute
   71.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   71.39 + * to extend the choice of license to its licensees as provided above.
   71.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   71.41 + * Version 2 license, then the option applies only if the new code is
   71.42 + * made subject to such option by the copyright holder.
   71.43 + */
   71.44 +
   71.45 +package org.openide.util.lookup;
   71.46 +
   71.47 +import java.util.HashSet;
   71.48 +import java.util.Set;
   71.49 +import org.netbeans.junit.NbTestCase;
   71.50 +
   71.51 +import org.netbeans.junit.RandomlyFails;
   71.52 +import org.openide.util.Lookup;
   71.53 +
   71.54 +/**
   71.55 + * @author  Petr Nejedly, adapted to test by Jaroslav Tulach
   71.56 + */
   71.57 +@RandomlyFails // NB-Core-Build #1847
   71.58 +public class SimpleProxyLookupSpeedIssue42244Test extends NbTestCase {
   71.59 +
   71.60 +    public SimpleProxyLookupSpeedIssue42244Test (String name) {
   71.61 +        super (name);
   71.62 +    }
   71.63 +
   71.64 +    public void testCompareTheSpeed () {
   71.65 +        String content1 = "String1";
   71.66 +        String content2 = "String2";
   71.67 +        
   71.68 +        Lookup fixed1 = Lookups.singleton(content1);
   71.69 +        Lookup fixed2 = Lookups.singleton(content2);
   71.70 +        
   71.71 +        MyProvider provider = new MyProvider();
   71.72 +        provider.setLookup(fixed1);
   71.73 +        
   71.74 +        Lookup top = Lookups.proxy(provider);
   71.75 +
   71.76 +        Lookup.Result<String> r0 = top.lookupResult(String.class);
   71.77 +        r0.allInstances();
   71.78 +
   71.79 +        long time = System.currentTimeMillis();
   71.80 +        top.lookupAll(String.class);
   71.81 +        long withOneResult = System.currentTimeMillis() - time;
   71.82 +
   71.83 +     
   71.84 +        Set<Object> results = new HashSet<Object>();
   71.85 +        for (int i=0; i<10000; i++) {
   71.86 +            Lookup.Result<String> res = top.lookupResult(String.class);
   71.87 +            results.add (res);
   71.88 +            res.allInstances();
   71.89 +        }
   71.90 +        
   71.91 +        provider.setLookup(fixed2);
   71.92 +
   71.93 +        time = System.currentTimeMillis();
   71.94 +        top.lookupAll(String.class);
   71.95 +        long withManyResults = System.currentTimeMillis() - time;
   71.96 +        
   71.97 +        // if the measurement takes less then 10ms, pretend 10ms
   71.98 +        if (withManyResults < 10) {
   71.99 +            withManyResults = 10;
  71.100 +        }
  71.101 +        if (withOneResult < 10) {
  71.102 +            withOneResult = 10;
  71.103 +        }
  71.104 +
  71.105 +        if (withManyResults >= 10 * withOneResult) {
  71.106 +            fail ("With many results the test runs too long.\n With many: " + withManyResults + "\n With one : " + withOneResult);
  71.107 +        }
  71.108 +    }
  71.109 +    
  71.110 +    private static class MyProvider implements Lookup.Provider {
  71.111 +        private Lookup lookup;
  71.112 +        public Lookup getLookup() {
  71.113 +            return lookup;
  71.114 +        }
  71.115 +        
  71.116 +        void setLookup(Lookup lookup) {
  71.117 +            this.lookup = lookup;
  71.118 +        }
  71.119 +    }
  71.120 +    
  71.121 +}
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/SimpleProxyLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    72.3 @@ -0,0 +1,73 @@
    72.4 +/*
    72.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    72.6 + *
    72.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    72.8 + *
    72.9 + * The contents of this file are subject to the terms of either the GNU
   72.10 + * General Public License Version 2 only ("GPL") or the Common
   72.11 + * Development and Distribution License("CDDL") (collectively, the
   72.12 + * "License"). You may not use this file except in compliance with the
   72.13 + * License. You can obtain a copy of the License at
   72.14 + * http://www.netbeans.org/cddl-gplv2.html
   72.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   72.16 + * specific language governing permissions and limitations under the
   72.17 + * License.  When distributing the software, include this License Header
   72.18 + * Notice in each file and include the License file at
   72.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   72.20 + * particular file as subject to the "Classpath" exception as provided
   72.21 + * by Sun in the GPL Version 2 section of the License file that
   72.22 + * accompanied this code. If applicable, add the following below the
   72.23 + * License Header, with the fields enclosed by brackets [] replaced by
   72.24 + * your own identifying information:
   72.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   72.26 + *
   72.27 + * Contributor(s):
   72.28 + *
   72.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   72.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   72.31 + * Microsystems, Inc. All Rights Reserved.
   72.32 + *
   72.33 + * If you wish your version of this file to be governed by only the CDDL
   72.34 + * or only the GPL Version 2, indicate your decision by adding
   72.35 + * "[Contributor] elects to include this software in this distribution
   72.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   72.37 + * single choice of license, a recipient has the option to distribute
   72.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   72.39 + * to extend the choice of license to its licensees as provided above.
   72.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   72.41 + * Version 2 license, then the option applies only if the new code is
   72.42 + * made subject to such option by the copyright holder.
   72.43 + */
   72.44 +
   72.45 +package org.openide.util.lookup;
   72.46 +
   72.47 +import java.lang.ref.WeakReference;
   72.48 +import org.netbeans.junit.NbTestCase;
   72.49 +import org.openide.util.Lookup;
   72.50 +import org.openide.util.Lookup.Provider;
   72.51 +
   72.52 +/**
   72.53 + *
   72.54 + * @author Jan Lahoda
   72.55 + */
   72.56 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   72.57 +public class SimpleProxyLookupTest extends NbTestCase {
   72.58 +
   72.59 +    public SimpleProxyLookupTest(String testName) {
   72.60 +        super(testName);
   72.61 +    }
   72.62 +
   72.63 +    public void test69810() throws Exception {
   72.64 +        Lookup.Template t = new Lookup.Template(String.class);
   72.65 +        SimpleProxyLookup spl = new SimpleProxyLookup(new Provider() {
   72.66 +            public Lookup getLookup() {
   72.67 +                return Lookups.fixed(new Object[] {"test1", "test2"});
   72.68 +            }
   72.69 +        });
   72.70 +        
   72.71 +        assertGC("", new WeakReference(spl.lookup(t)));
   72.72 +        
   72.73 +        spl.lookup(new Lookup.Template(Object.class)).allInstances();
   72.74 +    }
   72.75 +    
   72.76 +}
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/SingletonLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    73.3 @@ -0,0 +1,113 @@
    73.4 +/*
    73.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    73.6 + * 
    73.7 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    73.8 + * 
    73.9 + * The contents of this file are subject to the terms of either the GNU
   73.10 + * General Public License Version 2 only ("GPL") or the Common
   73.11 + * Development and Distribution License("CDDL") (collectively, the
   73.12 + * "License"). You may not use this file except in compliance with the
   73.13 + * License. You can obtain a copy of the License at
   73.14 + * http://www.netbeans.org/cddl-gplv2.html
   73.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   73.16 + * specific language governing permissions and limitations under the
   73.17 + * License.  When distributing the software, include this License Header
   73.18 + * Notice in each file and include the License file at
   73.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   73.20 + * particular file as subject to the "Classpath" exception as provided
   73.21 + * by Sun in the GPL Version 2 section of the License file that
   73.22 + * accompanied this code. If applicable, add the following below the
   73.23 + * License Header, with the fields enclosed by brackets [] replaced by
   73.24 + * your own identifying information:
   73.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   73.26 + * 
   73.27 + * If you wish your version of this file to be governed by only the CDDL
   73.28 + * or only the GPL Version 2, indicate your decision by adding
   73.29 + * "[Contributor] elects to include this software in this distribution
   73.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   73.31 + * single choice of license, a recipient has the option to distribute
   73.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   73.33 + * to extend the choice of license to its licensees as provided above.
   73.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   73.35 + * Version 2 license, then the option applies only if the new code is
   73.36 + * made subject to such option by the copyright holder.
   73.37 + * 
   73.38 + * Contributor(s):
   73.39 + * 
   73.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   73.41 + */
   73.42 +
   73.43 +package org.openide.util.lookup;
   73.44 +
   73.45 +import java.util.Collection;
   73.46 +import org.netbeans.junit.NbTestCase;
   73.47 +import org.openide.util.Lookup;
   73.48 +
   73.49 +/**
   73.50 + * Contains tests of class {@code SingletonLookup}.
   73.51 + *
   73.52 + * @author  Marian Petras
   73.53 + */
   73.54 +public class SingletonLookupTest extends NbTestCase {
   73.55 +    
   73.56 +    public SingletonLookupTest(String testName) {
   73.57 +        super(testName);
   73.58 +    }
   73.59 +
   73.60 +    public void testBasics() {
   73.61 +        Object orig = new Object();
   73.62 +        Lookup p1 = new SingletonLookup(orig);
   73.63 +        Object obj = p1.lookup(Object.class);
   73.64 +        assertTrue(obj == orig);
   73.65 +        assertNull(p1.lookup(String.class)); 
   73.66 +        assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
   73.67 +        //
   73.68 +        Lookup p2 = new SingletonLookup("test");
   73.69 +        assertNotNull(p2.lookup(Object.class));
   73.70 +        assertNotNull(p2.lookup(String.class));
   73.71 +        assertNotNull(p2.lookup(java.io.Serializable.class));
   73.72 +    }
   73.73 +
   73.74 +    public void testId() {
   73.75 +        Object orig = new Object();
   73.76 +        Collection allInstances;
   73.77 +
   73.78 +        Lookup l = new SingletonLookup(orig, "id");
   73.79 +
   73.80 +        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, null, null)).allInstances();
   73.81 +        assertNotNull(allInstances);
   73.82 +        assertFalse(allInstances.isEmpty());
   73.83 +        assertEquals(1, allInstances.size());
   73.84 +        assertTrue(allInstances.iterator().next() == orig);
   73.85 +
   73.86 +        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "id", null)).allInstances();
   73.87 +        assertNotNull(allInstances);
   73.88 +        assertFalse(allInstances.isEmpty());
   73.89 +        assertEquals(1, allInstances.size());
   73.90 +        assertTrue(allInstances.iterator().next() == orig);
   73.91 +
   73.92 +        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "not", null)).allInstances();
   73.93 +        assertNotNull(allInstances);
   73.94 +        assertTrue(allInstances.isEmpty());
   73.95 +
   73.96 +        allInstances = l.lookup(new Lookup.Template<String>(String.class, null, null)).allInstances();
   73.97 +        assertNotNull(allInstances);
   73.98 +        assertTrue(allInstances.isEmpty());
   73.99 +
  73.100 +        allInstances = l.lookup(new Lookup.Template<String>(String.class, "id", null)).allInstances();
  73.101 +        assertNotNull(allInstances);
  73.102 +        assertTrue(allInstances.isEmpty());
  73.103 +
  73.104 +        allInstances = l.lookup(new Lookup.Template<String>(String.class, "not", null)).allInstances();
  73.105 +        assertNotNull(allInstances);
  73.106 +        assertTrue(allInstances.isEmpty());
  73.107 +    }
  73.108 +
  73.109 +    public void testSize() {
  73.110 +        final Object obj = new Object();
  73.111 +        assertSize("The singleton lookup instance should be small",
  73.112 +                   24,
  73.113 +                   new SingletonLookup(obj));
  73.114 +    }
  73.115 +
  73.116 +}
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/problem100320.txt	Mon Dec 14 20:58:39 2009 +0100
    74.3 @@ -0,0 +1,17 @@
    74.4 +:java.io.IOException:
    74.5 +java.nio.charset.CharacterCodingException
    74.6 +java.io.EOFException
    74.7 +java.io.FileNotFoundException
    74.8 +java.io.InterruptedIOException
    74.9 +java.net.MalformedURLException
   74.10 +java.io.IOException
   74.11 +java.io.UnsupportedEncodingException
   74.12 +java.io.NotActiveException
   74.13 +java.io.StreamCorruptedException
   74.14 +java.io.UTFDataFormatException
   74.15 +java.util.zip.ZipException
   74.16 +java.util.jar.JarException
   74.17 +:java.util.Comparator:
   74.18 +org.bar.Comparator3
   74.19 +org.bar.Comparator2
   74.20 +#position=5
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/services-jar-1.txt	Mon Dec 14 20:58:39 2009 +0100
    75.3 @@ -0,0 +1,17 @@
    75.4 +:somedummyfile:
    75.5 +org.foo.Interface
    75.6 +:java.lang.Runnable:
    75.7 +org.foo.impl.Runnable1
    75.8 +:java.util.Comparator:
    75.9 +#some comment
   75.10 +org.foo.impl.Comparator1
   75.11 +#position=10
   75.12 +#som comment2
   75.13 +:java.util.Iterator:
   75.14 +org.foo.impl.Iterator1
   75.15 +:org.foo.Interface:
   75.16 +# Some header info, maybe.
   75.17 +
   75.18 +# Our first impl here
   75.19 +org.foo.impl.Implementation1
   75.20 +
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/services-jar-2.txt	Mon Dec 14 20:58:39 2009 +0100
    76.3 @@ -0,0 +1,10 @@
    76.4 +:java.lang.Runnable:
    76.5 +#-org.foo.impl.Runnable1
    76.6 +:java.util.Comparator:
    76.7 +org.bar.Comparator2
    76.8 +#position=5
    76.9 +:java.util.Iterator:
   76.10 +org.bar.Iterator2
   76.11 +#position=100
   76.12 +:org.foo.Interface:
   76.13 +org.bar.Implementation2
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/test/AnnotationProcessorTestUtils.java	Mon Dec 14 20:58:39 2009 +0100
    77.3 @@ -0,0 +1,139 @@
    77.4 +/*
    77.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    77.6 + *
    77.7 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    77.8 + *
    77.9 + * The contents of this file are subject to the terms of either the GNU
   77.10 + * General Public License Version 2 only ("GPL") or the Common
   77.11 + * Development and Distribution License("CDDL") (collectively, the
   77.12 + * "License"). You may not use this file except in compliance with the
   77.13 + * License. You can obtain a copy of the License at
   77.14 + * http://www.netbeans.org/cddl-gplv2.html
   77.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   77.16 + * specific language governing permissions and limitations under the
   77.17 + * License.  When distributing the software, include this License Header
   77.18 + * Notice in each file and include the License file at
   77.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   77.20 + * particular file as subject to the "Classpath" exception as provided
   77.21 + * by Sun in the GPL Version 2 section of the License file that
   77.22 + * accompanied this code. If applicable, add the following below the
   77.23 + * License Header, with the fields enclosed by brackets [] replaced by
   77.24 + * your own identifying information:
   77.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   77.26 + *
   77.27 + * If you wish your version of this file to be governed by only the CDDL
   77.28 + * or only the GPL Version 2, indicate your decision by adding
   77.29 + * "[Contributor] elects to include this software in this distribution
   77.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   77.31 + * single choice of license, a recipient has the option to distribute
   77.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   77.33 + * to extend the choice of license to its licensees as provided above.
   77.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   77.35 + * Version 2 license, then the option applies only if the new code is
   77.36 + * made subject to such option by the copyright holder.
   77.37 + *
   77.38 + * Contributor(s):
   77.39 + *
   77.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   77.41 + */
   77.42 +
   77.43 +package org.openide.util.test;
   77.44 +
   77.45 +import java.io.File;
   77.46 +import java.io.FileWriter;
   77.47 +import java.io.IOException;
   77.48 +import java.io.OutputStream;
   77.49 +import java.io.PrintWriter;
   77.50 +import java.io.Writer;
   77.51 +import java.util.ArrayList;
   77.52 +import java.util.List;
   77.53 +import java.util.regex.Pattern;
   77.54 +import javax.tools.JavaCompiler;
   77.55 +import javax.tools.ToolProvider;
   77.56 +import junit.framework.Assert;
   77.57 +
   77.58 +/**
   77.59 + * Utilities useful to those testing JSR 269 annotation processors.
   77.60 + * <p>If you just want to test that the output of the processor is correct,
   77.61 + * you do not need to do anything special:
   77.62 + * just use the annotation on some sample classes nested inside your unit test.
   77.63 + * They will be processed, and you check that your SPI loads them correctly.
   77.64 + * These utilities are useful mainly in case you want to check that the processor
   77.65 + * rejects erroneous sources, and that any messages it prints are reasonable;
   77.66 + * that it behaves correctly on incremental compilations; etc.
   77.67 + */
   77.68 +public class AnnotationProcessorTestUtils {
   77.69 +
   77.70 +    private AnnotationProcessorTestUtils() {}
   77.71 +
   77.72 +    /**
   77.73 +     * Create a source file.
   77.74 +     * @param dir source root
   77.75 +     * @param clazz a fully-qualified class name
   77.76 +     * @param content lines of text (skip package decl)
   77.77 +     */
   77.78 +    public static void makeSource(File dir, String clazz, String... content) throws IOException {
   77.79 +        File f = new File(dir, clazz.replace('.', File.separatorChar) + ".java");
   77.80 +        f.getParentFile().mkdirs();
   77.81 +        Writer w = new FileWriter(f);
   77.82 +        try {
   77.83 +            PrintWriter pw = new PrintWriter(w);
   77.84 +            String pkg = clazz.replaceFirst("\\.[^.]+$", "");
   77.85 +            if (!pkg.equals(clazz)) {
   77.86 +                pw.println("package " + pkg + ";");
   77.87 +            }
   77.88 +            for (String line : content) {
   77.89 +                pw.println(line);
   77.90 +            }
   77.91 +            pw.flush();
   77.92 +        } finally {
   77.93 +            w.close();
   77.94 +        }
   77.95 +    }
   77.96 +
   77.97 +    /**
   77.98 +     * Run the Java compiler.
   77.99 +     * (A JSR 199 implementation must be available.)
  77.100 +     * @param src a source root (runs javac on all *.java it finds matching {@code srcIncludes})
  77.101 +     * @param srcIncludes a pattern of source files names without path to compile (useful for testing incremental compiles), or null for all
  77.102 +     * @param dest a dest dir to compile classes to
  77.103 +     * @param cp classpath entries; if null, use Java classpath of test
  77.104 +     * @param stderr output stream to print messages to, or null for test console (i.e. do not capture)
  77.105 +     * @return true if compilation succeeded, false if it failed
  77.106 +     */
  77.107 +    public static boolean runJavac(File src, String srcIncludes, File dest, File[] cp, OutputStream stderr) {
  77.108 +        List<String> args = new ArrayList<String>();
  77.109 +        args.add("-classpath");
  77.110 +        if (cp != null) {
  77.111 +            StringBuffer b = new StringBuffer();
  77.112 +            for (File entry : cp) {
  77.113 +                b.append(File.pathSeparatorChar);
  77.114 +                b.append(entry.getAbsolutePath());
  77.115 +            }
  77.116 +            args.add(b.toString());
  77.117 +        } else {
  77.118 +            args.add(System.getProperty("java.class.path"));
  77.119 +        }
  77.120 +        args.add("-d");
  77.121 +        args.add(dest.getAbsolutePath());
  77.122 +        args.add("-sourcepath");
  77.123 +        args.add(src.getAbsolutePath());
  77.124 +        dest.mkdirs();
  77.125 +        scan(args, src, srcIncludes);
  77.126 +        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  77.127 +        Assert.assertNotNull("no JSR 199 compiler impl found; try e.g.: " +
  77.128 +                "test.unit.run.cp.extra=${nb_all}/apisupport.harness/external/openjdk-javac-6-b12.jar", compiler);
  77.129 +        //System.err.println("running javac with args: " + args);
  77.130 +        return compiler.run(null, null, stderr, args.toArray(new String[args.size()])) == 0;
  77.131 +    }
  77.132 +    private static void scan(List<String> names, File f, String includes) {
  77.133 +        if (f.isDirectory()) {
  77.134 +            for (File kid : f.listFiles()) {
  77.135 +                scan(names, kid, includes);
  77.136 +            }
  77.137 +        } else if (f.getName().endsWith(".java") && (includes == null || Pattern.compile(includes).matcher(f.getName()).find())) {
  77.138 +            names.add(f.getAbsolutePath());
  77.139 +        }
  77.140 +    }
  77.141 +
  77.142 +}
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/test/MockLookup.java	Mon Dec 14 20:58:39 2009 +0100
    78.3 @@ -0,0 +1,135 @@
    78.4 +/*
    78.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    78.6 + *
    78.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    78.8 + *
    78.9 + * The contents of this file are subject to the terms of either the GNU
   78.10 + * General Public License Version 2 only ("GPL") or the Common
   78.11 + * Development and Distribution License("CDDL") (collectively, the
   78.12 + * "License"). You may not use this file except in compliance with the
   78.13 + * License. You can obtain a copy of the License at
   78.14 + * http://www.netbeans.org/cddl-gplv2.html
   78.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   78.16 + * specific language governing permissions and limitations under the
   78.17 + * License.  When distributing the software, include this License Header
   78.18 + * Notice in each file and include the License file at
   78.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   78.20 + * particular file as subject to the "Classpath" exception as provided
   78.21 + * by Sun in the GPL Version 2 section of the License file that
   78.22 + * accompanied this code. If applicable, add the following below the
   78.23 + * License Header, with the fields enclosed by brackets [] replaced by
   78.24 + * your own identifying information:
   78.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   78.26 + *
   78.27 + * Contributor(s):
   78.28 + *
   78.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   78.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
   78.31 + * Microsystems, Inc. All Rights Reserved.
   78.32 + *
   78.33 + * If you wish your version of this file to be governed by only the CDDL
   78.34 + * or only the GPL Version 2, indicate your decision by adding
   78.35 + * "[Contributor] elects to include this software in this distribution
   78.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   78.37 + * single choice of license, a recipient has the option to distribute
   78.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   78.39 + * to extend the choice of license to its licensees as provided above.
   78.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   78.41 + * Version 2 license, then the option applies only if the new code is
   78.42 + * made subject to such option by the copyright holder.
   78.43 + */
   78.44 +
   78.45 +package org.openide.util.test;
   78.46 +
   78.47 +import java.lang.reflect.Field;
   78.48 +import java.util.Collection;
   78.49 +import static junit.framework.Assert.*;
   78.50 +import org.openide.util.Lookup;
   78.51 +import org.openide.util.lookup.Lookups;
   78.52 +import org.openide.util.lookup.ProxyLookup;
   78.53 +
   78.54 +/**
   78.55 + * Mock implementation of system default lookup suitable for use in unit tests.
   78.56 + * The initial value just contains classpath services.
   78.57 + */
   78.58 +public class MockLookup extends ProxyLookup {
   78.59 +
   78.60 +    private static MockLookup DEFAULT;
   78.61 +    private static boolean making = false;
   78.62 +    private static volatile boolean ready;
   78.63 +
   78.64 +    static {
   78.65 +        making = true;
   78.66 +        try {
   78.67 +            System.setProperty("org.openide.util.Lookup", MockLookup.class.getName());
   78.68 +            if (Lookup.getDefault().getClass() != MockLookup.class) {
   78.69 +                // Someone else initialized lookup first. Try to force our way.
   78.70 +                Field defaultLookup = Lookup.class.getDeclaredField("defaultLookup");
   78.71 +                defaultLookup.setAccessible(true);
   78.72 +                defaultLookup.set(null, null);
   78.73 +            }
   78.74 +            assertEquals(MockLookup.class, Lookup.getDefault().getClass());
   78.75 +        } catch (Exception x) {
   78.76 +            throw new ExceptionInInitializerError(x);
   78.77 +        } finally {
   78.78 +            making = false;
   78.79 +        }
   78.80 +    }
   78.81 +
   78.82 +    /** Do not call this directly! */
   78.83 +    public MockLookup() {
   78.84 +        assertTrue(making);
   78.85 +        assertNull(DEFAULT);
   78.86 +        DEFAULT = this;
   78.87 +    }
   78.88 +
   78.89 +    /**
   78.90 +     * Just ensures that this lookup is default lookup, but does not actually change its content.
   78.91 +     * Useful mainly if you have some test utility method which calls foreign code which might use default lookup,
   78.92 +     * and you want to ensure that any users of mock lookup will see the correct default lookup right away,
   78.93 +     * even if they have not yet called {@link #setLookup} or {@link #setInstances}.
   78.94 +     */
   78.95 +    public static void init() {
   78.96 +        if (!ready) {
   78.97 +            setInstances();
   78.98 +        }
   78.99 +    }
  78.100 +
  78.101 +    /**
  78.102 +     * Sets the global default lookup with zero or more delegate lookups.
  78.103 +     * Caution: if you don't include Lookups.metaInfServices, you may have trouble,
  78.104 +     * e.g. {@link #makeScratchDir} will not work.
  78.105 +     * Most of the time you should use {@link #setInstances} instead.
  78.106 +     */
  78.107 +    public static void setLookup(Lookup... lookups) {
  78.108 +        ready = true;
  78.109 +        DEFAULT.setLookups(lookups);
  78.110 +    }
  78.111 +
  78.112 +    /**
  78.113 +     * Sets the global default lookup with some fixed instances.
  78.114 +     * Will also include (at a lower priority) a {@link ClassLoader},
  78.115 +     * and services found from <code>META-INF/services/*</code> in the classpath.
  78.116 +     */
  78.117 +    public static void setInstances(Object... instances) {
  78.118 +        ClassLoader l = MockLookup.class.getClassLoader();
  78.119 +        setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
  78.120 +    }
  78.121 +    /**
  78.122 +     * Sets the global default lookup with some fixed instances and
  78.123 +     * content read from Services folder from system file system.
  78.124 +     * Will also include (at a lower priority) a {@link ClassLoader},
  78.125 +     * and services found from <code>META-INF/services/*</code> in the classpath.
  78.126 +     */
  78.127 +    public static void setLayersAndInstances(Object... instances) {
  78.128 +        ClassLoader l = MockLookup.class.getClassLoader();
  78.129 +        if (l != Lookup.getDefault().lookup(ClassLoader.class)) {
  78.130 +            setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
  78.131 +        }
  78.132 +        Lookup projects = Lookups.forPath("Services");
  78.133 +        Collection<?> initialize = projects.lookupAll(Object.class);
  78.134 +        //System.err.println("all: " + initialize);
  78.135 +        setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l), projects);
  78.136 +    }
  78.137 +
  78.138 +}
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/test/MockLookupTest.java	Mon Dec 14 20:58:39 2009 +0100
    79.3 @@ -0,0 +1,66 @@
    79.4 +/*
    79.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    79.6 + *
    79.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    79.8 + *
    79.9 + * The contents of this file are subject to the terms of either the GNU
   79.10 + * General Public License Version 2 only ("GPL") or the Common
   79.11 + * Development and Distribution License("CDDL") (collectively, the
   79.12 + * "License"). You may not use this file except in compliance with the
   79.13 + * License. You can obtain a copy of the License at
   79.14 + * http://www.netbeans.org/cddl-gplv2.html
   79.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   79.16 + * specific language governing permissions and limitations under the
   79.17 + * License.  When distributing the software, include this License Header
   79.18 + * Notice in each file and include the License file at
   79.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   79.20 + * particular file as subject to the "Classpath" exception as provided
   79.21 + * by Sun in the GPL Version 2 section of the License file that
   79.22 + * accompanied this code. If applicable, add the following below the
   79.23 + * License Header, with the fields enclosed by brackets [] replaced by
   79.24 + * your own identifying information:
   79.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   79.26 + *
   79.27 + * Contributor(s):
   79.28 + *
   79.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   79.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
   79.31 + * Microsystems, Inc. All Rights Reserved.
   79.32 + *
   79.33 + * If you wish your version of this file to be governed by only the CDDL
   79.34 + * or only the GPL Version 2, indicate your decision by adding
   79.35 + * "[Contributor] elects to include this software in this distribution
   79.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   79.37 + * single choice of license, a recipient has the option to distribute
   79.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   79.39 + * to extend the choice of license to its licensees as provided above.
   79.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   79.41 + * Version 2 license, then the option applies only if the new code is
   79.42 + * made subject to such option by the copyright holder.
   79.43 + */
   79.44 +
   79.45 +package org.openide.util.test;
   79.46 +
   79.47 +import junit.framework.TestCase;
   79.48 +import org.openide.util.Lookup;
   79.49 +
   79.50 +public class MockLookupTest extends TestCase {
   79.51 +
   79.52 +    // XXX test:
   79.53 +    // setLookup with one or more lookup args does not use M-I/s
   79.54 +    // still works if another Lookup.getDefault was set before
   79.55 +
   79.56 +    public MockLookupTest(String n) {
   79.57 +        super(n);
   79.58 +    }
   79.59 +
   79.60 +    public void testSetLookup() throws Exception {
   79.61 +        MockLookup.setInstances("hello");
   79.62 +        assertEquals("initial lookup works", "hello", Lookup.getDefault().lookup(String.class));
   79.63 +        MockLookup.setInstances("goodbye");
   79.64 +        assertEquals("modified lookup works", "goodbye", Lookup.getDefault().lookup(String.class));
   79.65 +        MockLookup.setInstances();
   79.66 +        assertEquals("cleared lookup works", null, Lookup.getDefault().lookup(String.class));
   79.67 +    }
   79.68 +
   79.69 +}
    80.1 --- a/openide.util/apichanges.xml	Thu Dec 10 19:23:25 2009 -0500
    80.2 +++ b/openide.util/apichanges.xml	Mon Dec 14 20:58:39 2009 +0100
    80.3 @@ -43,7 +43,6 @@
    80.4  <!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
    80.5  <apichanges>
    80.6  <apidefs>
    80.7 -    <apidef name="lookup">Lookup API</apidef>
    80.8      <apidef name="util">Utilities API</apidef>
    80.9      <apidef name="xml">XML API</apidef>
   80.10      <apidef name="actions">Actions API</apidef>
   80.11 @@ -136,23 +135,6 @@
   80.12          <class package="org.openide" name="LifecycleManager"/>
   80.13          <issue number="168257"/>
   80.14      </change>
   80.15 -    <change id="org.openide.util.Lookup.paths">
   80.16 -        <api name="lookup"/>
   80.17 -        <summary>Added
   80.18 -            <code>org.openide.util.Lookup.paths</code> property
   80.19 -        </summary>
   80.20 -        <version major="7" minor="24"/>
   80.21 -        <date day="19" month="6" year="2009"/>
   80.22 -        <author login="jtulach"/>
   80.23 -        <compatibility addition="yes"/>
   80.24 -        <description>
   80.25 -            <p>
   80.26 -                 Better way to integrate Lookup.getDefault() and system filesystem.
   80.27 -            </p>
   80.28 -        </description>
   80.29 -        <class package="org.openide.util" name="Lookup"/>
   80.30 -        <issue number="166782"/>
   80.31 -    </change>
   80.32      <change id="enableStackTraces">
   80.33          <api name="util"/>
   80.34          <summary>Added constructor <code>RequestProcessor(String name, int throughput, boolean interruptThread, boolean enableStackTraces)</code></summary>
   80.35 @@ -200,28 +182,6 @@
   80.36          <class package="org.openide.util" name="Utilities"/>
   80.37          <issue number="110492"/>
   80.38      </change>
   80.39 -    <change id="ServiceProvider">
   80.40 -        <api name="lookup"/>
   80.41 -        <summary>Added <code>ServiceProvider</code> annotation</summary>
   80.42 -        <version major="7" minor="20"/>
   80.43 -        <date day="1" month="11" year="2008"/>
   80.44 -        <author login="jglick"/>
   80.45 -        <compatibility addition="yes">
   80.46 -            <p>
   80.47 -                Modules registering services using <code>META-INF/services</code>
   80.48 -                files in the source tree are encouraged to switch to the annotation.
   80.49 -            </p>
   80.50 -        </compatibility>
   80.51 -        <description>
   80.52 -            <p>
   80.53 -                Added annotations <code>ServiceProvider</code> and <code>ServiceProviders</code>
   80.54 -                to simplify registration of global singleton services.
   80.55 -            </p>
   80.56 -        </description>
   80.57 -        <class package="org.openide.util.lookup" name="ServiceProvider"/>
   80.58 -        <class package="org.openide.util.lookup" name="ServiceProviders"/>
   80.59 -        <issue number="150447"/>
   80.60 -    </change>
   80.61      <change id="Utilities.OS_OPENBSD">
   80.62          <api name="util"/>
   80.63          <summary>Added <code>OS_OPENBSD</code> and <code>OS_UNIX_OTHER</code> fields</summary>
   80.64 @@ -269,29 +229,6 @@
   80.65          <class package="org.openide.xml" name="XMLUtil"/>
   80.66          <issue number="42686"/>
   80.67      </change>
   80.68 -    <change id="Lookup.asynchronous">
   80.69 -        <api name="lookup"/>
   80.70 -        <summary>AbstractLookup and ProxyLookup fire changes asynchronously</summary>
   80.71 -        <version major="7" minor="16"/>
   80.72 -        <date day="27" month="6" year="2008"/>
   80.73 -        <author login="jtulach"/>
   80.74 -        <compatibility addition="yes" binary="compatible" semantic="compatible"/>
   80.75 -        <description>
   80.76 -            <p>
   80.77 -                All modification methods in <code>AbstractLookup</code> and <code>ProxyLookup</code>
   80.78 -                were extended to accept an 
   80.79 -                <a href="@JDK@/java/util/concurrent/Executor.html">Executor</a>.
   80.80 -                If not null, it is used to dispatch events to listeners sometime
   80.81 -                "later". Also the <code>AbstractLookup.Content</code> 
   80.82 -                and <code>InstanceContent</code> constructors
   80.83 -                have been extended to accept such <code>Executor</code>s.
   80.84 -            </p>
   80.85 -        </description> 
   80.86 -        <class package="org.openide.util.lookup" name="AbstractLookup"/>
   80.87 -        <class package="org.openide.util.lookup" name="ProxyLookup"/>
   80.88 -        <class package="org.openide.util.lookup" name="InstanceContent"/>
   80.89 -        <issue number="134297"/>
   80.90 -    </change>
   80.91      <change id="RequestProcessor.Executor">
   80.92          <api name="util"/>
   80.93          <summary>RequestProcessor implements Executor interface</summary>
   80.94 @@ -386,25 +323,6 @@
   80.95          <issue number="119069"/>
   80.96      </change>
   80.97  
   80.98 -    <change id="Lookups.forPath">
   80.99 -        <api name="util"/>
  80.100 -        <summary>Added simplified support for named lookups <code>Lookups.forPath</code></summary>
  80.101 -        <version major="7" minor="9"/>
  80.102 -        <date day="17" month="4" year="2007"/>
  80.103 -        <author login="jtulach"/>
  80.104 -        <compatibility addition="yes"/>
  80.105 -        <description>
  80.106 -            <p>
  80.107 -                New method <a href="@TOP@/org/openide/util/lookup/Lookups.html#forPath(java.lang.String)">Lookups.forPath(String)</a>
  80.108 -                has been added to replace now deprecated <a href="@org-openide-loaders@/org/openide/loaders/FolderLookup.html">FolderLookup</a>
  80.109 -                and allow modules who wants to read settings from layers
  80.110 -                to do so with a simpler code, without dependency on DataSystems API.
  80.111 -            </p>
  80.112 -        </description>
  80.113 -        <class package="org.openide.util.lookup" name="Lookups"/>
  80.114 -        <issue number="98426"/>
  80.115 -    </change>
  80.116 -
  80.117      <change id="ChangeSupport">
  80.118          <api name="util"/>
  80.119          <summary>Added <code>ChangeSupport</code></summary>
  80.120 @@ -557,30 +475,6 @@
  80.121          <issue number="73637"/>
  80.122      </change>
  80.123      
  80.124 -    <change id="lookupAll-lookupResult">
  80.125 -        <api name="lookup"/>
  80.126 -        <summary>Convenience methods added to <code>Lookup</code></summary>
  80.127 -        <version major="6" minor="10"/>
  80.128 -        <date day="3" month="4" year="2006"/>
  80.129 -        <author login="jglick"/>
  80.130 -        <compatibility addition="yes" binary="compatible" source="incompatible">
  80.131 -            <p>
  80.132 -                Could conceivably conflict with existing subclass method with same signature
  80.133 -                with different semantics or return type.
  80.134 -            </p>
  80.135 -        </compatibility>
  80.136 -        <description>
  80.137 -            <p>
  80.138 -                Two methods, <code>lookupResult</code> and <code>lookupAll</code>, were
  80.139 -                added to <code>Lookup</code> to encapsulate the most common usage patterns
  80.140 -                with less typing, and more importantly avoiding the need to explicitly
  80.141 -                make a <code>Lookup.Template</code> object.
  80.142 -            </p>
  80.143 -        </description>
  80.144 -        <class package="org.openide.util" name="Lookup"/>
  80.145 -        <issue number="73848"/>
  80.146 -    </change>
  80.147 -
  80.148      <change id="use-logging" >
  80.149        <api name="util"/>
  80.150        <summary>Do not use ErrorManager for logging</summary>
  80.151 @@ -646,32 +540,6 @@
  80.152        <class package="org.openide.util" name="RequestProcessor"/>
  80.153        <issue number="68031"/>
  80.154      </change>
  80.155 -    <change id="less-events-from-proxylookup" >
  80.156 -      <api name="lookup"/>
  80.157 -      <summary>Less change notifications from ProxyLookup</summary>
  80.158 -      <version major="6" minor="7"/>
  80.159 -      <date day="11" month="11" year="2005"/>
  80.160 -      <author login="jtulach"/>
  80.161 -      <compatibility addition="no" modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no"/>
  80.162 -      <description>
  80.163 -        <a href="@TOP@/org/openide/util/lookup/ProxyLookup.html">ProxyLookup.setLookups</a>
  80.164 -        used to fire <a href="@TOP@/org/openide/util/LookupEvent.html">LookupEvent</a> every 
  80.165 -        time it was called. Now it always checks whether there was a change to the
  80.166 -        previous state. This will reduce the number of events delivered when a small
  80.167 -        change is made. Also results from both 
  80.168 -        <a href="@TOP@/org/openide/util/lookup/ProxyLookup.html">ProxyLookup</a>
  80.169 -        and <a href="@TOP@/org/openide/util/lookup/AbstractLookup.html">AbstractLookup</a>
  80.170 -        were modified to return immutable <code>Collection</code>s. 
  80.171 -        So do not try to modify them. It was always documented that the
  80.172 -        results, are immutable and also it was never said that a change is
  80.173 -        delivered when there is no change in the result, so this is considered
  80.174 -        compatible change, even it is know that at least one piece of code 
  80.175 -        in NetBeans relied on this behaviour.
  80.176 -      </description>
  80.177 -      <class package="org.openide.util.lookup" name="ProxyLookup"/>
  80.178 -      <class package="org.openide.util.lookup" name="AbstractLookup"/>
  80.179 -      <issue number="68031"/>
  80.180 -    </change>
  80.181      
  80.182      <change>
  80.183        <api name="util"/>
  80.184 @@ -803,23 +671,6 @@
  80.185          <issue number="27868"/>
  80.186      </change>
  80.187  
  80.188 -    <change id="excluding-lookup">
  80.189 -      <api name="lookup"/>
  80.190 -      <summary>
  80.191 -<code>Lookups.exclude</code> added to simplify writing of lookups that filter content of other lookups</summary>
  80.192 -      <version major="5" minor="4"/>
  80.193 -      <date day="14" month="1" year="2005"/>
  80.194 -      <author login="jtulach"/>
  80.195 -      <compatibility binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no" modification="no"/>
  80.196 -      <description>
  80.197 -        <p>New method that takes lookup and set of classes and return new lookup 
  80.198 -        which contains everything from the original one except instances of 
  80.199 -        the specified classes has been added.
  80.200 -        </p>
  80.201 -      </description>
  80.202 -      <class package="org.openide.util.lookup" name="Lookups"/>
  80.203 -      <issue number="53058"/>
  80.204 -    </change>
  80.205  <change id="Task-waitFinished-timeout">
  80.206        <api name="util"/>
  80.207        <summary>New method <code>task.waitFinished(timeout)</code> added</summary>
  80.208 @@ -910,22 +761,6 @@
  80.209       <issue number="41166"/>
  80.210      </change>
  80.211  <change>
  80.212 -        <api name="lookup"/>
  80.213 -        <summary>Added ability to order items in META-INF/services/ lookup</summary>
  80.214 -        <version major="4" minor="34"/>
  80.215 -        <date day="9" month="5" year="2004"/>
  80.216 -        <author login="dkonecny"/>
  80.217 -        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.218 -        <description>
  80.219 -            Items in META-INF/services/ lookup can be followed by advisory
  80.220 -            "position" attribute. The resulting lookup will list first items with lower
  80.221 -            position value. Items without position attribute will be listed 
  80.222 -            last. See documentation for more details on format.
  80.223 -        </description>
  80.224 -        <class package="org.openide.util.lookup" name="Lookups"/>
  80.225 -        <issue number="41606"/>
  80.226 -    </change>
  80.227 -<change>
  80.228       <api name="util"/>
  80.229       <summary>Support for complicated listeners</summary>
  80.230       <version major="4" minor="12"/>
  80.231 @@ -983,20 +818,6 @@
  80.232       <class package="org.openide.util" name="WeakListeners"/>
  80.233       <issue number="34758"/>
  80.234      </change>
  80.235 -<change>
  80.236 -     <api name="lookup"/>
  80.237 -     <summary>New <code>lookupItem()</code> method in Lookups</summary>
  80.238 -     <version major="4" minor="8"/>
  80.239 -     <date day="9" month="7" year="2003"/>
  80.240 -     <author login="vstejskal"/>
  80.241 -     <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.242 -     <description>
  80.243 -       New method that returns Lookup.Item implementation for given instance and key identifying
  80.244 -       that instance in the lookup. This method is useful when writing Looks which need to
  80.245 -       return some cookies (Collection of Lookup.Items).
  80.246 -     </description>
  80.247 -     <class package="org.openide.util.lookup" name="Lookups"/>
  80.248 -    </change>
  80.249      <change id="HelpCtx.findHelp">
  80.250       <api name="util"/>
  80.251       <summary>New method to find HelpCtx</summary>
  80.252 @@ -1049,22 +870,6 @@
  80.253          <issue number="30604"/>
  80.254      </change>
  80.255  <change>
  80.256 -        <api name="lookup"/>
  80.257 -        <summary>New method Lookups.metaInfServices</summary>
  80.258 -        <version major="3" minor="35"/>
  80.259 -        <date day="5" month="2" year="2003"/>
  80.260 -        <author login="dstrupl"/>
  80.261 -        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.262 -        <description>
  80.263 -            A lookup that implements the JDK1.3 JAR services mechanism and delegates
  80.264 -            to META-INF/services/name.of.class files. This lookup was (is) used by core
  80.265 -            and the core had to use reflection to create an instance. Moreover can
  80.266 -            be usefull for module authors and in standalone library.
  80.267 -        </description>
  80.268 -        <class package="org.openide.util.lookup" name="Lookups"/>
  80.269 -        <issue number="29126"/>
  80.270 -    </change>
  80.271 -<change>
  80.272       <api name="util"/>
  80.273       <summary>org.openide.util.Utilities.createProgressCursor added</summary>
  80.274       <version major="3" minor="23"/>
  80.275 @@ -1118,23 +923,6 @@
  80.276          <issue number="22156"/>
  80.277      </change>
  80.278  <change>
  80.279 -        <api name="lookup"/>
  80.280 -        <summary>New method Lookups.proxy</summary>
  80.281 -        <version major="3" minor="9"/>
  80.282 -        <date day="20" month="9" year="2002"/>
  80.283 -        <author login="dstrupl"/>
  80.284 -        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.285 -        <description>
  80.286 -            Creates a lookup that delegates to another one but that one can change
  80.287 -            from time to time. The returned lookup checks every time somebody calls
  80.288 -            lookup or lookupItem method whether the provider still returns
  80.289 -            the same lookup. If not, it updates state of all Lookup.Results
  80.290 -            that it created (and that still exists).
  80.291 -        </description>
  80.292 -        <class package="org.openide.util.lookup" name="Lookups"/>
  80.293 -        <issue number="27425"/>
  80.294 -    </change>
  80.295 -<change>
  80.296          <api name="util"/>
  80.297          <summary>Utilities.activeReferenceQueue()</summary>
  80.298          <version major="3" minor="11"/>
  80.299 @@ -1151,22 +939,6 @@
  80.300      </change>
  80.301  <change>
  80.302          <api name="util"/>
  80.303 -        <summary>New interface Lookup.Provider</summary>
  80.304 -        <version major="3" minor="6"/>
  80.305 -        <date day="19" month="8" year="2002"/>
  80.306 -        <author login="dstrupl"/>
  80.307 -        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.308 -        <description>
  80.309 -            An object can have method getLookup if there is a need to provide
  80.310 -            local loookup instance. To recognize objects with such a facility
  80.311 -            we are introducing interface Lookup.Provider with only one method:
  80.312 -            getLookup.
  80.313 -        </description>
  80.314 -        <class package="org.openide.util" name="Lookup"/>
  80.315 -         <issue number="26275"/>
  80.316 -    </change>
  80.317 -<change>
  80.318 -        <api name="util"/>
  80.319          <summary>Deprecation of parts of MouseUtils.PopupMenuAdapter</summary>
  80.320          <version major="3" minor="4"/>
  80.321          <date day="6" month="8" year="2002"/>
  80.322 @@ -1179,46 +951,6 @@
  80.323            should be constructed via default constructor.
  80.324          </description>
  80.325      </change>
  80.326 -<change id="meta-inf-services">
  80.327 -        <api name="lookup"/>
  80.328 -        <summary>Modules can specify the content of Lookup.getDefault
  80.329 -        in META-INF/services</summary>
  80.330 -        <version major="3" minor="3"/>
  80.331 -        <date day="22" month="7" year="2002"/>
  80.332 -        <author login="jtulach"/>
  80.333 -        <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.334 -        <description>
  80.335 -          The content of <code>Lookup.getDefault()</code> can be specified
  80.336 -          by a standard JDK registration mechanism, using JARs'
  80.337 -          <a href="http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html#Service%20Provider" shape="rect">
  80.338 -            META-INF/services
  80.339 -          </a>
  80.340 -          directory. This is suitable for services that do not change,
  80.341 -          do not require user modification and that need to be ready
  80.342 -          soon during initialization of the system. 
  80.343 -        </description>
  80.344 -    </change>
  80.345 -    <change>
  80.346 -      <api name="lookup"/>
  80.347 -      <summary>
  80.348 -<code>ErrorManager.isNotifiable</code> added</summary>
  80.349 -      <version major="3" minor="18"/>
  80.350 -      <date day="3" month="11" year="2002"/>
  80.351 -      <author login="jglick"/>
  80.352 -      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no">
  80.353 -        Existing code which assumes (incorrectly) that <code>isLoggable</code>
  80.354 -        can be used for this purpose, or which calls <code>notify</code> at a low
  80.355 -        level such as <code>INFORMATIONAL</code> without first checking
  80.356 -        <code>isNotifiable</code> for efficiency, should be revised.
  80.357 -      </compatibility>
  80.358 -      <description>
  80.359 -        The method <code>ErrorManager.isNotifiable</code> was added to capture
  80.360 -        the fact that an error manager implementation might be more aggressive
  80.361 -        about displaying stack traces than log messages.
  80.362 -      </description>
  80.363 -      <class package="org.openide" name="ErrorManager"/>
  80.364 -      <issue number="24056"/>
  80.365 -    </change>
  80.366  <change>
  80.367        <api name="util"/>
  80.368        <summary>
  80.369 @@ -1246,26 +978,6 @@
  80.370        <issue number="29711"/>
  80.371      </change>
  80.372  <change>
  80.373 -         <api name="lookup"/>
  80.374 -         <summary>Added org.openide.util.lookup.Lookups</summary>
  80.375 -         <version major="2" minor="21"/>
  80.376 -         <date day="28" month="5" year="2002"/>
  80.377 -         <author login="dstrupl"/>
  80.378 -         <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.379 -         <description>New utility class added. The class cannot be instantiated
  80.380 -           and contains following static methods:
  80.381 -        <pre xml:space="preserve">
  80.382 -<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Lookup</span> <span class="function-name">singleton</span>(<span class="type">Object</span> <span class="variable-name">objectToLookup</span>);
  80.383 -<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Lookup</span> <span class="function-name">fixed</span>(<span class="type">Object</span>[] <span class="variable-name">objectsToLookup</span>);
  80.384 -<span class="keyword">public</span> <span class="keyword">static</span> <span class="type">Lookup</span> <span class="function-name">fixed</span>(<span class="type">Object</span>[] <span class="variable-name">keys</span>, <span class="type">InstanceContent.Convertor</span> <span class="variable-name">convertor</span>);
  80.385 -</pre>
  80.386 -           The methods return an instance of simple lookup implementation
  80.387 -           that holds the objects passed a parameter.
  80.388 -         </description>
  80.389 -         <class package="org.openide.util.lookup" name="Lookups"/>
  80.390 -         <issue number="20550"/>
  80.391 -    </change>
  80.392 -<change>
  80.393          <api name="util"/>
  80.394          <summary>Added RequestProcessor.getDefault(), deprecated static methods in RequestProcessor</summary>
  80.395          <version major="2" minor="12"/>
  80.396 @@ -1325,49 +1037,6 @@
  80.397        <class package="org.openide" name="ErrorManager"/>
  80.398        <issue number="16854"/>
  80.399    </change>
  80.400 -<change id="AbstractLookup.Content-ProxyLookup.beforeLookup">
  80.401 -      <api name="lookup"/>
  80.402 -      <summary>Enhanced usage of ProxyLookup &amp; AbstractLookup.Content</summary>
  80.403 -      <version major="1" minor="31"/>
  80.404 -      <date day="18" month="8" year="2001"/>
  80.405 -      <author login="jtulach"/>
  80.406 -      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.407 -      <description>
  80.408 -        <code>AbstractLookup.Content</code> made public to allow its usage 
  80.409 -        for objects that do not subclass AbstractLookup. <code>ProxyLookup.beforeLookup</code>
  80.410 -        added so subclasses can update themselves (call setLookups (...)) before the actual lookup is
  80.411 -        performed.
  80.412 -      </description>
  80.413 -      <class package="org.openide.util.lookup" name="AbstractLookup"/>
  80.414 -      <class package="org.openide.util.lookup" name="ProxyLookup"/>
  80.415 -    </change>
  80.416 -<change>
  80.417 -      <api name="lookup"/>
  80.418 -      <summary>Instance content simplifies creation of lookups</summary>
  80.419 -      <version major="1" minor="25"/>
  80.420 -      <!-- XXX date unknown -->
  80.421 -      <author login="jtulach"/>
  80.422 -      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.423 -      <description>
  80.424 -        Added <code>AbstractLookup.Content</code> which can be passed to an
  80.425 -        abstract lookup in its constructor and used to control the contents
  80.426 -        easily. Also <code>InstanceLookup</code> provides the common easy
  80.427 -        implementation.
  80.428 -      </description>
  80.429 -      <class package="org.openide.util.lookup" name="AbstractLookup"/>
  80.430 -      <class package="org.openide.util.lookup" name="InstanceContent"/>
  80.431 -    </change>
  80.432 -    <change id="clone-service-type" >
  80.433 -      <api name="lookup"/>
  80.434 -      <summary>
  80.435 -<code>ServiceType.createClone</code> added</summary>
  80.436 -      <date day="30" month="11" year="2000"/>
  80.437 -      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no">Subclasses are encouraged to implement <code>Cloneable</code>.</compatibility>
  80.438 -      <description>
  80.439 -        <code>public final ServiceType createClone()</code> added.
  80.440 -      </description>
  80.441 -      <class package="org.openide" name="ServiceType"/>
  80.442 -    </change>
  80.443      <change id="logging-added-to-error-manager" >
  80.444        <api name="util"/>
  80.445        <summary>
  80.446 @@ -1392,27 +1061,6 @@
  80.447        <class package="org.openide" name="ErrorManager"/>
  80.448      </change>
  80.449      <change>
  80.450 -      <api name="lookup"/>
  80.451 -      <summary>Folder lookup may be serialized</summary>
  80.452 -      <version major="3" minor="27"/>
  80.453 -      <date day="7" month="1" year="2003"/>
  80.454 -      <author login="jglick"/>
  80.455 -      <compatibility modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no">
  80.456 -        Modules which rely on a data object under <samp>Services/</samp> gaining
  80.457 -        or losing <code>InstanceCookie</code> between sessions may not work
  80.458 -        correctly with the cache. This is probably very rare.
  80.459 -      </compatibility>
  80.460 -      <description>
  80.461 -        To implement lookup caching, some lookup implementations are now
  80.462 -        serializable: <code>AbstractLookup</code> as well as
  80.463 -        <code>FolderLookup</code>'s lookup. <code>ProxyLookup</code> has a
  80.464 -        protected subclass constructor permitting subclasses to be serializable.
  80.465 -      </description>
  80.466 -      <class package="org.openide.util.lookup" name="AbstractLookup"/>
  80.467 -      <class package="org.openide.util.lookup" name="ProxyLookup"/>
  80.468 -      <issue number="20190"/>
  80.469 -    </change>
  80.470 -    <change>
  80.471        <api name="xml"/>
  80.472        <summary>Can register entity resolvers</summary>
  80.473        <date day="20" month="12" year="2000"/>
  80.474 @@ -1534,39 +1182,6 @@
  80.475        </description>
  80.476        <class package="org.openide.util" name="Mutex"/>
  80.477      </change>
  80.478 -    <change>
  80.479 -      <api name="lookup"/>
  80.480 -      <summary>Changes in access protection of proxy lookup</summary>
  80.481 -      <version major="1" minor="19"/>
  80.482 -      <date day="8" month="7" year="2001"/>
  80.483 -      <compatibility modification="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" addition="no" deletion="no">
  80.484 -        Changes to newly added feature.
  80.485 -      </compatibility>
  80.486 -      <description>
  80.487 -        <code>ProxyLookup.setLookups</code> made protected instead of public so
  80.488 -        nobody can misuse the method except the creator of the object and
  80.489 -        <code>ProxyLookup.getLookups</code> added. <code>ProxyLookup</code> made
  80.490 -        non final.
  80.491 -      </description>
  80.492 -      <class package="org.openide.util.lookup" name="ProxyLookup"/>
  80.493 -    </change>
  80.494 -<change>
  80.495 -      <api name="lookup"/>
  80.496 -      <summary>Lookup service providers package created</summary>
  80.497 -      <version major="1" minor="9"/>
  80.498 -      <date day="1" month="6" year="2001"/>
  80.499 -      <author login="jtulach"/>
  80.500 -      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.501 -      <description>
  80.502 -        Package <code>org.openide.util.lookup</code> created, should hold SPI
  80.503 -        interfaces for lookup. Initially filled with <code>AbstractLookup</code>
  80.504 -        which introduces <code>AbstractLookup.Pair</code> and with
  80.505 -        <code>ProxyLookup</code>.
  80.506 -      </description>
  80.507 -      <class package="org.openide.util.lookup" name="AbstractLookup"/>
  80.508 -      <class package="org.openide.util.lookup" name="ProxyLookup"/>
  80.509 -      <package name="org.openide.util.lookup"/>
  80.510 -    </change>
  80.511  <change id="Task.notifyRunning">
  80.512        <api name="util"/>
  80.513        <summary>More flexibility in controlling running of tasks</summary>
  80.514 @@ -1580,34 +1195,37 @@
  80.515        </description>
  80.516        <class package="org.openide.util" name="Task"/>
  80.517      </change>
  80.518 -<change>
  80.519 -      <api name="lookup"/>
  80.520 -      <summary>Added lookup items and support APIs</summary>
  80.521 -      <version major="1" minor="8"/>
  80.522 -      <date day="25" month="5" year="2001"/>
  80.523 -      <author login="jtulach"/>
  80.524 -      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.525 +    <change>
  80.526 +      <api name="util"/>
  80.527 +      <summary>
  80.528 +        <code>ErrorManager.isNotifiable</code> added</summary>
  80.529 +      <version major="3" minor="18"/>
  80.530 +      <date day="3" month="11" year="2002"/>
  80.531 +      <author login="jglick"/>
  80.532 +      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no">
  80.533 +        Existing code which assumes (incorrectly) that <code>isLoggable</code>
  80.534 +        can be used for this purpose, or which calls <code>notify</code> at a low
  80.535 +        level such as <code>INFORMATIONAL</code> without first checking
  80.536 +        <code>isNotifiable</code> for efficiency, should be revised.
  80.537 +      </compatibility>
  80.538        <description>
  80.539 -        <code>Lookup</code> enhanced. Interface <code>Lookup.Item</code> and
  80.540 -        additional methods to access it also added.
  80.541 +        The method <code>ErrorManager.isNotifiable</code> was added to capture
  80.542 +        the fact that an error manager implementation might be more aggressive
  80.543 +        about displaying stack traces than log messages.
  80.544        </description>
  80.545 -      <class package="org.openide.util" name="Lookup"/>
  80.546 +      <class package="org.openide" name="ErrorManager"/>
  80.547 +      <issue number="24056"/>
  80.548      </change>
  80.549 -<change>
  80.550 -      <api name="lookup"/>
  80.551 -      <summary>Lookup system introduced</summary>
  80.552 -      <date day="1" month="3" year="2001"/>
  80.553 -      <author login="jtulach"/>
  80.554 -      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
  80.555 +    <change id="clone-service-type" >
  80.556 +      <api name="util"/>
  80.557 +      <summary>
  80.558 +        <code>ServiceType.createClone</code> added</summary>
  80.559 +      <date day="30" month="11" year="2000"/>
  80.560 +      <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no">Subclasses are encouraged to implement <code>Cloneable</code>.</compatibility>
  80.561        <description>
  80.562 -        Better version of <code>Lookup</code> introduced. There is a
  80.563 -        <code>org.openide.util.Lookup</code> with bunch of inner classes and
  80.564 -        <code>org.openide.util.LookupListener</code> and
  80.565 -        <code>org.openide.util.LookupEvent</code>.
  80.566 +        <code>public final ServiceType createClone()</code> added.
  80.567        </description>
  80.568 -      <class package="org.openide.util" name="Lookup"/>
  80.569 -      <class package="org.openide.util" name="LookupEvent"/>
  80.570 -      <class package="org.openide.util" name="LookupListener"/>
  80.571 +      <class package="org.openide" name="ServiceType"/>
  80.572      </change>
  80.573  <change>
  80.574        <api name="util"/>
    81.1 --- a/openide.util/arch.xml	Thu Dec 10 19:23:25 2009 -0500
    81.2 +++ b/openide.util/arch.xml	Mon Dec 14 20:58:39 2009 +0100
    81.3 @@ -58,32 +58,20 @@
    81.4      <api group="java" name="UtilitiesAPI" category="official" type="export" url="@TOP@/org/openide/util/doc-files/api.html" /> 
    81.5      classes.
    81.6    </p>
    81.7 -  
    81.8 -  <p>
    81.9 -    Also this module defines the <a href="@TOP@/org/openide/util/Lookup.html">
   81.10 -    Lookup</a> which the NetBeans way for dynamic registration 
   81.11 -    and lookup of 
   81.12 -    components in our modularized component system. It allows lookup and discovery 
   81.13 -    of features by description of their interfaces. The classes are devided 
   81.14 -    into two parts. The 
   81.15 -    <api group="java" name="LookupAPI" type="export" category="official" url="@TOP@/org/openide/util/lookup/doc-files/lookup-api.html">
   81.16 -    allows the discovery</api> and the 
   81.17 -    <api group="java" name="LookupSPI" type="export" category="official" url="@TOP@/org/openide/util/lookup/doc-files/lookup-spi.html">
   81.18 -    simplifies creation and registration of own lookup objects</api>.
   81.19 -  </p>
   81.20   </answer>
   81.21  
   81.22  
   81.23   <answer id="arch-quality">
   81.24    <p>
   81.25     There is a lot of unit tests in 
   81.26 -   <a href="http://www.netbeans.org/source/browse/openide/util/test/unit/src/">CVS</a>.
   81.27 +   <a href="http://hg.netbeans.org/main-golden/openide.util/test/unit/src/">version control</a>
   81.28 +   system.
   81.29    </p>
   81.30   </answer>
   81.31  
   81.32   <answer id="arch-time">
   81.33    <p>
   81.34 -   The module has been around since 1997 and is stilly improved
   81.35 +   The module has been around since 1997 and is still improved
   81.36     from time to time.
   81.37    </p>
   81.38   </answer>
   81.39 @@ -91,130 +79,6 @@
   81.40  
   81.41  
   81.42   <answer id="arch-usecases">
   81.43 -  
   81.44 -    There is a great introduction to Lookup and its usage in its 
   81.45 -    <a href="@TOP@/org/openide/util/Lookup.html">javadoc</a>. Here is just
   81.46 -    a list of frequently asked or interesting questions slowly expanding as
   81.47 -    people ask them:
   81.48 -    
   81.49 -    <h3>Lookup faq:</h3>
   81.50 -    
   81.51 -    <usecase id="lookup-on-certain-platform" name="How to specify that a service in Lookup should be available only on Windows?" >
   81.52 -<em><b>Q:</b>
   81.53 -Most of the time I specify interfaces that I want to add to the Lookup class in the layer.xml file. 
   81.54 -But, let's say I have a platform-specific interface (something on Windows only, for instance).</em>
   81.55 -<p>
   81.56 -<em>
   81.57 -How can I specify (in the xml, or programmatically) that this service should only be added to the Lookup if the platform is Windows?
   81.58 -</em>>
   81.59 -</p>
   81.60 -In general there are three ways to achieve this.
   81.61 -<ul>
   81.62 -    <li><p>It is possible to write a specific module and enable it only on windows.
   81.63 -    See <a href="@org-openide-modules@/org/openide/modules/doc-files/api.html#how-os-specific">os specific modules</a> documentation.
   81.64 -    Then you can put a registration of your instance into your module's 
   81.65 -    <a href="@TOP@/org/openide/util/doc-files/api.html#service-lookup">META-INF/services</a> directory and it 
   81.66 -    will be available only on Windows.</p>
   81.67 -    </li>
   81.68 -    
   81.69 -    <li><p>Another possibility that does not require new module, but which executes 
   81.70 -    a code on startup (which may have performance implications) is to use <code>methodvalue</code>
   81.71 -    attribute. Register your instance in layer using <code>your-Object.instance</code> file
   81.72 -    as described at 
   81.73 -    <a href="@TOP@/org/openide/util/doc-files/api.html#ido-methodvalue">services
   81.74 -    </a> documentation and in your factory method either return the instance 
   81.75 -    your want or <code>null</code> depending on result of <a href="@TOP@/org/openide/util/Utilities.html#isWindows()">
   81.76 -    Utilities.isWindows()</a> call.</p>
   81.77 -    </li>
   81.78 -                <li>
   81.79 -                    <p>
   81.80 -                        In some cases, the interface for which you will register an implementation permits a
   81.81 -                        no-operation semantics. For example, <code>InstalledFileLocator.locate(...)</code> can
   81.82 -                        return a valid <code>File</code>, or null. You could always register an
   81.83 -                        <code>InstalledFileLocator</code> instance yet disable it on non-Windows platforms
   81.84 -                        (always returning null).
   81.85 -                    </p>
   81.86 -                </li>
   81.87 -</ul>
   81.88 -
   81.89 -    </usecase>
   81.90 -    
   81.91 -    <usecase id="lookup-extension-point" name="How shall I write an extension point for my module?" >
   81.92 -    <p>
   81.93 -        <em><b>Q:</b>
   81.94 -        I have more modules one of them providing the core functionality and
   81.95 -        few more that wish to extend it. What is the right way to do it?
   81.96 -        How does the Netbeans platform declare such extension point? 
   81.97 -        </em>
   81.98 -    </p>
   81.99 -
  81.100 -    <p>
  81.101 -    
  81.102 -    Start with declaring an extension interface in your
  81.103 -    core module and put it into the module's <em>public packages</em>. Imagine
  81.104 -    for example that the core module is in JAR file <code>org-my-netbeans-coremodule.jar</code>
  81.105 -    and already contains in manifests line like 
  81.106 -    <code>OpenIDE-Module: org.my.netbeans.coremodule/1</code> and wants 
  81.107 -    to display various tips of the day provided by other modules and thus defines:
  81.108 -    </p><pre> 
  81.109 -<span class="java-keywords">package</span> <span class="java-identifier">org</span><span class="java-operators">.</span><span class="java-identifier">my</span><span class="java-operators">.</span><span class="java-identifier">netbeans</span><span class="java-operators">.</span><span class="java-identifier">coremodule</span><span class="java-operators">;</span>
  81.110 -
  81.111 -<span class="java-keywords">public</span> <span class="java-keywords">interface</span> <span class="java-identifier">TipsOfTheDayProvider</span> <span class="java-operators">{</span>
  81.112 -    <span class="java-keywords">public</span> <span class="java-identifier">String</span> <span class="java-layer-method">provideTipOfTheDay</span> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">;</span>
  81.113 -<span class="java-operators">}</span>
  81.114 -</pre><p>
  81.115 -    And in its manifest adds line 
  81.116 -    <code>OpenIDE-Module-Public-Packages: org.my.netbeans.coremodule.*</code>
  81.117 -    to specify that this package contains exported API and shall be 
  81.118 -    accessible to other modules.
  81.119 -    </p>
  81.120 -    <p>
  81.121 -    When the core module is about to display the tip of the day it can ask
  81.122 -    the system for all registered instances of the <code>TipsOfTheDayProvider</code>,
  81.123 -    randomly select one of them:
  81.124 -    </p><pre>
  81.125 -<span class="java-keywords">import</span> <span class="java-identifier">java</span><span class="java-operators">.</span><span class="java-identifier">util</span><span class="java-operators">.</span><span class="java-identifier">Collection</span><span class="java-operators">;</span>
  81.126 -<span class="java-keywords">import</span> <span class="java-identifier">java</span><span class="java-operators">.</span><span class="java-identifier">util</span><span class="java-operators">.</span><span class="java-identifier">Collections</span><span class="java-operators">;</span>
  81.127 -<span class="java-keywords">import</span> <span class="java-identifier">org</span><span class="java-operators">.</span><span class="java-identifier">openide</span><span class="java-operators">.</span><span class="java-identifier">util</span><span class="java-operators">.</span><span class="java-identifier">Lookup</span><span class="java-operators">;</span>
  81.128 -
  81.129 -<a href="@TOP@org/openide/util/Lookup.Result.html"><span class="java-identifier">Lookup</span><span class="java-operators">.</span><span class="java-identifier">Result</span></a> <span class="java-identifier">result</span> <span class="java-operators">=</span> <a href="@TOP@org/openide/util/Lookup.html"><span class="java-identifier">Lookup</span></a><span class="java-operators">.</span><span class="java-layer-method">getDefault</span> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">.</span><span class="java-layer-method">lookup</span> <span class="java-operators">(</span><span class="java-keywords">new</span> <a href="@TOP@org/openide/util/Lookup.Template.html"><span class="java-identifier">Lookup</span><span class="java-operators">.</span><span class="java-layer-method">Template</span></a> <span class="java-operators">(</span><span class="java-identifier">TipsOfTheDayProvider</span><span class="java-operators">.</span><span class="java-keywords">class</span><span class="java-operators">)</span><span class="java-operators">)</span><span class="java-operators">;</span>
  81.130 -<span class="java-identifier">Collection</span> <span class="java-identifier">c</span> <span class="java-operators">=</span> <span class="java-identifier">result</span><span class="java-operators">.</span><a href="@TOP@org/openide/util/Lookup.Result.html#allInstances()"><span class="java-layer-method">allInstances</span></a> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">;</span>
  81.131 -<span class="java-identifier">Collections</span><span class="java-operators">.</span><span class="java-layer-method">shuffle</span> <span class="java-operators">(</span><span class="java-identifier">c</span><span class="java-operators">)</span><span class="java-operators">;</span>
  81.132 -<span class="java-identifier">TipsOfTheDayProvider</span> <span class="java-identifier">selected</span> <span class="java-operators">=</span> <span class="java-operators">(</span><span class="java-identifier">TipsOfTheDayProvider</span><span class="java-operators">)</span><span class="java-identifier">c</span><span class="java-operators">.</span><span class="java-layer-method">iterator</span> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">.</span><span class="java-layer-method">next</span> <span class="java-operators">(</span><span class="java-operators">)</span><span class="java-operators">;</span>
  81.133 -</pre><p>    
  81.134 -    and then display the tip. Simple, trivial, just by the usage of 
  81.135 -    <a href="@TOP@org/openide/util/Lookup.html">Lookup</a> interface once 
  81.136 -    creates a registry that other modules can enhance. But such enhancing 
  81.137 -    of course requires work on the other side. Each module that would like
  81.138 -    to register its <code>TipsOfTheDayProvider</code> needs to depend on the 
  81.139 -    core module - add 
  81.140 -    <code>OpenIDE-Module-Module-Dependencies: org.my.netbeans.coremodule/1</code>
  81.141 -    into its manifest and write a class with its own implementation of the
  81.142 -    provider:</p><pre>
  81.143 -<span class="java-keywords">package</span> <span class="java-identifier">org</span><span class="java-operators">.</span><span class="java-identifier">my</span><span class="java-operators">.</span><span class="java-identifier">netbeans</span><span class="java-operators">.</span><span class="java-identifier">extramodule</span><span class="java-operators">;</span>
  81.144 -
  81.145 -<span class="java-keywords">class</span> <span class="java-identifier">ExtraTip</span> <span class="java-keywords">implements</span> <span class="java-identifier">TipsOfTheDayProvider</span> <span class="java-operators">{</span>
  81.146 -    <span class="java-keywords">public</span> <span class="java-identifier">String</span> <span class="java-layer-method">provideTipOfTheDay</span> <span class="java-operators">(</span><span class="java-operators">)</span> <span class="java-operators">{</span>
  81.147 -        <span class="java-keywords">return</span> <span class="java-string-literal">"Do you know that in order to write extension point you should use Lookup?"</span><span class="java-operators">;</span>
  81.148 -    <span class="java-operators">}</span>
  81.149 -<span class="java-operators">}</span>
  81.150 -</pre><p>
  81.151 -    Then, the only necessary thing is to register such class by using the 
  81.152 -    J2SE standard <api name="ProviderRegistrationMechanism"
  81.153 -  type="import"
  81.154 -  category="standard"
  81.155 -  group="java" /> into plain text file
  81.156 -    <code>META-INF/services/org.my.netbeans.coremodule.TipsOfTheDayProvider</code>
  81.157 -    in the module JAR containing just one line: </p><pre>
  81.158 -org.my.netbeans.extramodule.ExtraTip
  81.159 -</pre><p>    
  81.160 -    and your modules are now ready to communicate
  81.161 -    using your own <em>extension point</em>.
  81.162 -    </p>
  81.163 -    
  81.164 -    </usecase>
  81.165 -
  81.166 -
  81.167      <usecase id="logging" name="How shall I do or influence logging in NetBeans?">
  81.168      <p>
  81.169          If you are interested in logging from inside your module, or in writing
  81.170 @@ -222,8 +86,6 @@
  81.171          to start is the <a href="@TOP@/org/openide/util/doc-files/logging.html">NetBeans logging guide</a>.
  81.172      </p>
  81.173      </usecase>
  81.174 -
  81.175 -
  81.176   </answer>
  81.177  
  81.178  
  81.179 @@ -249,28 +111,6 @@
  81.180    </p>
  81.181   </answer>
  81.182  
  81.183 -
  81.184 -
  81.185 - <answer id="compat-standards">
  81.186 -  <p>
  81.187 -    The default lookup registration follows the JDK's 
  81.188 -    <api name="ProviderRegistrationMechanism"
  81.189 -      type="import"
  81.190 -      category="standard"
  81.191 -      url="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Provider%20Configuration%20File"
  81.192 -      group="java" 
  81.193 -    />
  81.194 -    but enhances it to also support the 
  81.195 -    <api 
  81.196 -      name="ProviderRegistrationRemoval" 
  81.197 -      type="export" 
  81.198 -      category="devel" 
  81.199 -      url="@TOP@/org/openide/util/doc-files/api.html#service-lookup"
  81.200 -      group="java" 
  81.201 -    />. 
  81.202 -  </p>
  81.203 - </answer>
  81.204 -
  81.205   <answer id="compat-version">
  81.206    <p>
  81.207     This module has no settings. 
  81.208 @@ -301,7 +141,7 @@
  81.209     indirectly communicates with <a href="@org-openide-awt@/overview-summary.html">UI Utilities</a>
  81.210     module using <api name="AWTBridge" category="private" group="java" type="export" 
  81.211     url="http://www.netbeans.org/source/browse/openide/util/src/org/netbeans/modules/openide/util/AWTBridge.java">
  81.212 -   a class that is looked up in <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
  81.213 +   a class that is looked up in <a href="@org-openide-util-lookup@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
  81.214     and if registered can provide better UI elements for <a href="@JDK@/javax/swing/Action.html">Action</a>s.
  81.215     </api>
  81.216     
  81.217 @@ -486,50 +326,6 @@
  81.218          used on few places
  81.219          </api>.
  81.220      </li>
  81.221 -    
  81.222 -    <li>
  81.223 -    <api type="export" group="property" name="org.openide.util.Lookup" category="devel">
  81.224 -        checked by the initialization of the 
  81.225 -        <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
  81.226 -        and can
  81.227 -        contain name of a class that extends <code>org.openide.util.Lookup</code> and
  81.228 -        has public constructor, that should be instantiated and returned from 
  81.229 -        <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
  81.230 -        the class will be loaded by 
  81.231 -        <a href="@JDK@/java/lang/Thread.html#getContextClassLoader()">
  81.232 -        Thread.currentThread().getContextClassLoader()</a>
  81.233 -        classloader the first time <code>Lookup.getDefault</code> is invoked.
  81.234 -        <p/>
  81.235 -        The property can also contain value <code>"-"</code> which means to completely
  81.236 -        disable the lookup instantiation and return <a href="@TOP@/org/openide/util/Lookup.html#EMPTY">Lookup.EMPTY</a>
  81.237 -        from <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>.
  81.238 -        <p/>
  81.239 -        If the property is unspecified, the default <code>MetaInfServicesLookup</code>
  81.240 -        is constructed for <code>Thread.currentThread().getContextclassLoader()</code>
  81.241 -        that implements the <a href="architecture-summary.html#answer-compat-standards">JDK's standard</a>. If, by 
  81.242 -        a chance an instance of 
  81.243 -        <a href="@TOP@/org/openide/util/Lookup.Provider.html">Lookup.Provider</a>
  81.244 -        is found
  81.245 -        in there, its lookup is returned as result. Otherwise the <code>MetaInfServicesLookup</code>
  81.246 -        is the result of <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>.
  81.247 -    </api>
  81.248 -    </li>
  81.249 -
  81.250 -    <li>
  81.251 -    <api type="export" group="property" name="org.openide.util.Lookup.paths" category="devel">
  81.252 -        Sometimes it may be useful for the Lookup to contains objects from
  81.253 -        some system file system folder. This can be done with
  81.254 -        <code>org.openide.util.Lookup.paths=Folder1:Folder2:Folder3</code>.
  81.255 -        If this property is set prior to first call to
  81.256 -        <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>,
  81.257 -        it is split into pieces (separator is <code>':'</code>) and individual
  81.258 -        parts are then used to construct <code>Lookups.forPath("Folder1")</code>,
  81.259 -        etc. All these lookups then become part of the
  81.260 -        <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
  81.261 -        one. This property works since version 7.24
  81.262 -    </api>
  81.263 -    </li>
  81.264 -    
  81.265    </ul>
  81.266   </answer>
  81.267  
  81.268 @@ -553,20 +349,11 @@
  81.269     <api category="devel" group="java" name="WeakListener.setAccessible" type="export" url="@TOP@/org/openide/util/WeakListeners.html">
  81.270     used to call the remove method using reflection
  81.271     </api>. 
  81.272 -   <api category="devel" group="java" name="Lookups.metaInfServices" type="export" url="@TOP@/org/openide/util/lookup/Lookups.html#metaInfServices(java.lang.ClassLoader)">
  81.273 -   calls constructor of registered classes using reflection
  81.274 -   </api>. 
  81.275     <api category="private" group="lookup" name="ActionManagerInvocation" type="export" >
  81.276      because of the API separation, <a href="@TOP@/org/openide/util/actions/CallableSystemAction.html">CallableSystemAction</a> uses lookup for <code>ActionsBridge</code>
  81.277      provided by <code>org-openide-actions</code> module
  81.278      when looking for <a href="@org-openide-actions@/org/openide/actions/ActionManager.html">org.openide.actions.ActionManager</a> implementation.
  81.279      </api>.
  81.280 -   <api category="friend" group="java" name="Lookup.resetDefaultLookup" type="export">
  81.281 -    There is a static private method <code>Lookup.resetDefaultLookup</code> that 
  81.282 -    is called by NbJUnit's <code>MockServices</code> to properly reset default
  81.283 -    lookup and fire changes to all registred listeners.
  81.284 -   </api>. 
  81.285 -
  81.286    </p>
  81.287   </answer>
  81.288  
  81.289 @@ -631,12 +418,6 @@
  81.290  
  81.291   <answer id="lookup-lookup">
  81.292      <ul>
  81.293 -    <li><api name="LookupInitializationLookup" category="devel" group="lookup" type="export" url="#property-org.openide.util.Lookup">
  81.294 -    during 
  81.295 -    initialization of the <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
  81.296 -    the <a href="@TOP@/org/openide/util/Lookup.Provider.html">Lookup.Provider</a>
  81.297 -    is being searched</api>.
  81.298 -    </li>
  81.299      
  81.300      <li><api name="LookupSharedClassObject" category="devel" group="lookup" type="export">
  81.301      singleton subclasses of <a href="@TOP@/org/openide/util/SharedClassObject.html">SharedClassObject</a> 
  81.302 @@ -646,7 +427,7 @@
  81.303      <li><api name="LookupContextGlobalProvider" category="stable" group="lookup" type="export">
  81.304      <a href="@TOP@/org/openide/util/Utilities.html#actionsGlobalContext()">actionsGlobalContext</a>
  81.305      searches for <a href="@TOP@/org/openide/util/ContextGlobalProvider.html">ContextGlobalProvider</a> in 
  81.306 -    <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>.
  81.307 +    <a href="@org-openide-util-lookup@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>.
  81.308      The provider is usually provided by <a href="@org-openide-windows@/overview-summary.html">window 
  81.309      system implementation</a>.
  81.310      </api>.</li>
  81.311 @@ -666,7 +447,7 @@
  81.312      <li><api name="LookupClassLoader" category="devel" group="lookup" type="export">
  81.313      Nearly all resource looking functions and reflective code
  81.314      uses <a href="@JDK@/java/lang/ClassLoader.html">ClassLoader</a>
  81.315 -    obtained from <a href="@TOP@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
  81.316 +    obtained from <a href="@org-openide-util-lookup@/org/openide/util/Lookup.html#getDefault()">Lookup.getDefault()</a>
  81.317      for loading system wide resources.
  81.318      </api>.</li>
  81.319      
  81.320 @@ -744,11 +525,6 @@
  81.321  -->
  81.322   <answer id="perf-limit">
  81.323    <p>
  81.324 -    The default implementation of the <code>MetaInfServicesLookup</code> just 
  81.325 -    keeps hashmap between queried classes and their implementations. The amount
  81.326 -    of memory is linear to amount of registered classes, but of course we 
  81.327 -    are not counting the memory occupied by the instances which the lookup 
  81.328 -    creates, that can be arbitrary.
  81.329    </p>
  81.330   </answer>
  81.331  
  81.332 @@ -762,9 +538,7 @@
  81.333  -->
  81.334   <answer id="perf-mem">
  81.335    <p>
  81.336 -   There are no big data structures. The amount of memory occupied by
  81.337 -   instances of <a href="@TOP@/org/openide/util/lookup/AbstractLookup.html">AbstractLookup</a> 
  81.338 -   is measured by unit tests.
  81.339 +   There are no big data structures.
  81.340    </p>
  81.341   </answer>
  81.342  
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/openide.util/module-auto-deps.xml	Mon Dec 14 20:58:39 2009 +0100
    82.3 @@ -0,0 +1,61 @@
    82.4 +<?xml version="1.0" encoding="UTF-8"?>
    82.5 +<!--
    82.6 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    82.7 +
    82.8 +Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    82.9 +
   82.10 +
   82.11 +The contents of this file are subject to the terms of either the GNU
   82.12 +General Public License Version 2 only ("GPL") or the Common
   82.13 +Development and Distribution License("CDDL") (collectively, the
   82.14 +"License"). You may not use this file except in compliance with the
   82.15 +License. You can obtain a copy of the License at
   82.16 +http://www.netbeans.org/cddl-gplv2.html
   82.17 +or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   82.18 +specific language governing permissions and limitations under the
   82.19 +License.  When distributing the software, include this License Header
   82.20 +Notice in each file and include the License file at
   82.21 +nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   82.22 +particular file as subject to the "Classpath" exception as provided
   82.23 +by Sun in the GPL Version 2 section of the License file that
   82.24 +accompanied this code. If applicable, add the following below the
   82.25 +License Header, with the fields enclosed by brackets [] replaced by
   82.26 +your own identifying information:
   82.27 +"Portions Copyrighted [year] [name of copyright owner]"
   82.28 +
   82.29 +Contributor(s):
   82.30 +
   82.31 +The Original Software is NetBeans. The Initial Developer of the Original
   82.32 +Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   82.33 +Microsystems, Inc. All Rights Reserved.
   82.34 +
   82.35 +If you wish your version of this file to be governed by only the CDDL
   82.36 +or only the GPL Version 2, indicate your decision by adding
   82.37 +"[Contributor] elects to include this software in this distribution
   82.38 +under the [CDDL or GPL Version 2] license." If you do not indicate a
   82.39 +single choice of license, a recipient has the option to distribute
   82.40 +your version of this file under either the CDDL, the GPL Version 2 or
   82.41 +to extend the choice of license to its licensees as provided above.
   82.42 +However, if you add GPL Version 2 code and therefore, elected the GPL
   82.43 +Version 2 license, then the option applies only if the new code is
   82.44 +made subject to such option by the copyright holder.
   82.45 +-->
   82.46 +
   82.47 +<!DOCTYPE transformations PUBLIC "-//NetBeans//DTD Module Automatic Dependencies 1.0//EN" "http://www.netbeans.org/dtds/module-auto-deps-1_0.dtd">
   82.48 +
   82.49 +<transformations version="1.0">
   82.50 +    <transformationgroup>
   82.51 +        <description>#170056] Separate module for Lookup API</description>
   82.52 +        <transformation>
   82.53 +            <trigger-dependency type="older">
   82.54 +                <module-dependency codenamebase="org.openide.util" spec="8.0"/>
   82.55 +            </trigger-dependency>
   82.56 +            <implies>
   82.57 +                <result>
   82.58 +                    <module-dependency codenamebase="org.openide.util.lookup"  spec="8.0"/>
   82.59 +                </result>
   82.60 +            </implies>
   82.61 +        </transformation>
   82.62 +    </transformationgroup>
   82.63 +
   82.64 +</transformations>
    83.1 --- a/openide.util/nbproject/project.properties	Thu Dec 10 19:23:25 2009 -0500
    83.2 +++ b/openide.util/nbproject/project.properties	Mon Dec 14 20:58:39 2009 +0100
    83.3 @@ -42,7 +42,7 @@
    83.4  module.jar.dir=lib
    83.5  cp.extra=${nb_all}/apisupport.harness/external/openjdk-javac-6-b12.jar
    83.6  
    83.7 -spec.version.base=7.32.0
    83.8 +spec.version.base=8.0
    83.9  
   83.10  # For XMLSerializer, needed for XMLUtil.write to work w/ namespaces under JDK 1.4:
   83.11  
    84.1 --- a/openide.util/nbproject/project.xml	Thu Dec 10 19:23:25 2009 -0500
    84.2 +++ b/openide.util/nbproject/project.xml	Mon Dec 14 20:58:39 2009 +0100
    84.3 @@ -45,7 +45,16 @@
    84.4      <configuration>
    84.5          <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
    84.6              <code-name-base>org.openide.util</code-name-base>
    84.7 -            <module-dependencies/>
    84.8 +            <module-dependencies>
    84.9 +                <dependency>
   84.10 +                    <code-name-base>org.openide.util.lookup</code-name-base>
   84.11 +                    <build-prerequisite/>
   84.12 +                    <compile-dependency/>
   84.13 +                    <run-dependency>
   84.14 +                        <implementation-version/>
   84.15 +                    </run-dependency>
   84.16 +                </dependency>
   84.17 +            </module-dependencies>
   84.18              <test-dependencies>
   84.19                  <test-type>
   84.20                      <name>unit</name>
   84.21 @@ -58,6 +67,11 @@
   84.22                          <recursive/>
   84.23                          <compile-dependency/>
   84.24                      </test-dependency>
   84.25 +                    <test-dependency>
   84.26 +                        <code-name-base>org.openide.util.lookup</code-name-base>
   84.27 +                        <compile-dependency/>
   84.28 +                        <test/>
   84.29 +                    </test-dependency>
   84.30                  </test-type>
   84.31              </test-dependencies>
   84.32              <public-packages>
    85.1 --- a/openide.util/src/META-INF/services/javax.annotation.processing.Processor	Thu Dec 10 19:23:25 2009 -0500
    85.2 +++ b/openide.util/src/META-INF/services/javax.annotation.processing.Processor	Mon Dec 14 20:58:39 2009 +0100
    85.3 @@ -1,2 +1,1 @@
    85.4 -org.netbeans.modules.openide.util.ServiceProviderProcessor
    85.5  org.netbeans.modules.openide.util.URLStreamHandlerRegistrationProcessor
    86.1 --- a/openide.util/src/org/netbeans/modules/openide/util/AbstractServiceProviderProcessor.java	Thu Dec 10 19:23:25 2009 -0500
    86.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.3 @@ -1,289 +0,0 @@
    86.4 -/*
    86.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    86.6 - *
    86.7 - * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
    86.8 - *
    86.9 - * The contents of this file are subject to the terms of either the GNU
   86.10 - * General Public License Version 2 only ("GPL") or the Common
   86.11 - * Development and Distribution License("CDDL") (collectively, the
   86.12 - * "License"). You may not use this file except in compliance with the
   86.13 - * License. You can obtain a copy of the License at
   86.14 - * http://www.netbeans.org/cddl-gplv2.html
   86.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   86.16 - * specific language governing permissions and limitations under the
   86.17 - * License.  When distributing the software, include this License Header
   86.18 - * Notice in each file and include the License file at
   86.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   86.20 - * particular file as subject to the "Classpath" exception as provided
   86.21 - * by Sun in the GPL Version 2 section of the License file that
   86.22 - * accompanied this code. If applicable, add the following below the
   86.23 - * License Header, with the fields enclosed by brackets [] replaced by
   86.24 - * your own identifying information:
   86.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   86.26 - *
   86.27 - * If you wish your version of this file to be governed by only the CDDL
   86.28 - * or only the GPL Version 2, indicate your decision by adding
   86.29 - * "[Contributor] elects to include this software in this distribution
   86.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   86.31 - * single choice of license, a recipient has the option to distribute
   86.32 - * your version of this file under either the CDDL, the GPL Version 2 or
   86.33 - * to extend the choice of license to its licensees as provided above.
   86.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   86.35 - * Version 2 license, then the option applies only if the new code is
   86.36 - * made subject to such option by the copyright holder.
   86.37 - *
   86.38 - * Contributor(s):
   86.39 - *
   86.40 - * Portions Copyrighted 2009 Sun Microsystems, Inc.
   86.41 - */
   86.42 -
   86.43 -package org.netbeans.modules.openide.util;
   86.44 -
   86.45 -import java.io.BufferedReader;
   86.46 -import java.io.FileNotFoundException;
   86.47 -import java.io.IOException;
   86.48 -import java.io.InputStream;
   86.49 -import java.io.InputStreamReader;
   86.50 -import java.io.OutputStream;
   86.51 -import java.io.OutputStreamWriter;
   86.52 -import java.io.PrintWriter;
   86.53 -import java.lang.annotation.Annotation;
   86.54 -import java.util.ArrayList;
   86.55 -import java.util.HashMap;
   86.56 -import java.util.List;
   86.57 -import java.util.Map;
   86.58 -import java.util.Set;
   86.59 -import java.util.WeakHashMap;
   86.60 -import javax.annotation.processing.AbstractProcessor;
   86.61 -import javax.annotation.processing.ProcessingEnvironment;
   86.62 -import javax.annotation.processing.RoundEnvironment;
   86.63 -import javax.lang.model.element.AnnotationMirror;
   86.64 -import javax.lang.model.element.AnnotationValue;
   86.65 -import javax.lang.model.element.Element;
   86.66 -import javax.lang.model.element.ExecutableElement;
   86.67 -import javax.lang.model.element.Modifier;
   86.68 -import javax.lang.model.element.TypeElement;
   86.69 -import javax.lang.model.type.TypeMirror;
   86.70 -import javax.lang.model.util.ElementFilter;
   86.71 -import javax.tools.Diagnostic.Kind;
   86.72 -import javax.tools.FileObject;
   86.73 -import javax.tools.StandardLocation;
   86.74 -
   86.75 -/**
   86.76 - * Infrastructure for generating {@code META-INF/services/*} and
   86.77 - * {@code META-INF/namedservices/*} registrations from annotations.
   86.78 - */
   86.79 -public abstract class AbstractServiceProviderProcessor extends AbstractProcessor {
   86.80 -
   86.81 -    private final Map<ProcessingEnvironment,Map<String,List<String>>> outputFilesByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<String>>>();
   86.82 -    private final Map<ProcessingEnvironment,Map<String,List<Element>>> originatingElementsByProcessor = new WeakHashMap<ProcessingEnvironment,Map<String,List<Element>>>();
   86.83 -    private final Map<TypeElement,Boolean> verifiedClasses = new WeakHashMap<TypeElement,Boolean>();
   86.84 -
   86.85 -    /** For access by subclasses. */
   86.86 -    protected AbstractServiceProviderProcessor() {}
   86.87 -
   86.88 -    public @Override final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   86.89 -        if (roundEnv.errorRaised()) {
   86.90 -            return false;
   86.91 -        }
   86.92 -        if (roundEnv.processingOver()) {
   86.93 -            writeServices();
   86.94 -            outputFilesByProcessor.clear();
   86.95 -            originatingElementsByProcessor.clear();
   86.96 -            return true;
   86.97 -        } else {
   86.98 -            return handleProcess(annotations, roundEnv);
   86.99 -        }
  86.100 -    }
  86.101 -
  86.102 -    /**
  86.103 -     * The regular body of {@link #process}.
  86.104 -     * Called during regular rounds if there are no outstanding errors.
  86.105 -     * In the last round, one of the processors will write out generated registrations.
  86.106 -     * @param annotations as in {@link #process}
  86.107 -     * @param roundEnv as in {@link #process}
  86.108 -     * @return as in {@link #process}
  86.109 -     */
  86.110 -    protected abstract boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv);
  86.111 -
  86.112 -    /**
  86.113 -     * Register a service.
  86.114 -     * If the class does not have an appropriate signature, an error will be printed and the registration skipped.
  86.115 -     * @param clazz the service implementation type
  86.116 -     * @param annotation the (top-level) annotation registering the service, for diagnostic purposes
  86.117 -     * @param type the type to which the implementation must be assignable
  86.118 -     * @param path a path under which to register, or "" if inapplicable
  86.119 -     * @param position a position at which to register, or {@link Integer#MAX_VALUE} to skip
  86.120 -     * @param supersedes possibly empty list of implementation to supersede
  86.121 -     */
  86.122 -    protected final void register(TypeElement clazz, Class<? extends Annotation> annotation,
  86.123 -            TypeMirror type, String path, int position, String[] supersedes) {
  86.124 -        Boolean verify = verifiedClasses.get(clazz);
  86.125 -        if (verify == null) {
  86.126 -            verify = verifyServiceProviderSignature(clazz, annotation);
  86.127 -            verifiedClasses.put(clazz, verify);
  86.128 -        }
  86.129 -        if (!verify) {
  86.130 -            return;
  86.131 -        }
  86.132 -        String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString();
  86.133 -        String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString();
  86.134 -        if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) {
  86.135 -            AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
  86.136 -            processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface,
  86.137 -                    clazz, ann, findAnnotationValue(ann, "service"));
  86.138 -            return;
  86.139 -        }
  86.140 -        processingEnv.getMessager().printMessage(Kind.NOTE,
  86.141 -                impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : ""));
  86.142 -        String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface;
  86.143 -        {
  86.144 -            Map<String,List<Element>> originatingElements = originatingElementsByProcessor.get(processingEnv);
  86.145 -            if (originatingElements == null) {
  86.146 -                originatingElements = new HashMap<String,List<Element>>();
  86.147 -                originatingElementsByProcessor.put(processingEnv, originatingElements);
  86.148 -            }
  86.149 -            List<Element> origEls = originatingElements.get(rsrc);
  86.150 -            if (origEls == null) {
  86.151 -                origEls = new ArrayList<Element>();
  86.152 -                originatingElements.put(rsrc, origEls);
  86.153 -            }
  86.154 -            origEls.add(clazz);
  86.155 -        }
  86.156 -        Map<String,List<String>> outputFiles = outputFilesByProcessor.get(processingEnv);
  86.157 -        if (outputFiles == null) {
  86.158 -            outputFiles = new HashMap<String,List<String>>();
  86.159 -            outputFilesByProcessor.put(processingEnv, outputFiles);
  86.160 -        }
  86.161 -        List<String> lines = outputFiles.get(rsrc);
  86.162 -        if (lines == null) {
  86.163 -            lines = new ArrayList<String>();
  86.164 -            try {
  86.165 -                try {
  86.166 -                    FileObject in = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", rsrc);
  86.167 -                    in.openInputStream().close();
  86.168 -                    processingEnv.getMessager().printMessage(Kind.ERROR,
  86.169 -                            "Cannot generate " + rsrc + " because it already exists in sources: " + in.toUri());
  86.170 -                    return;
  86.171 -                } catch (FileNotFoundException x) {
  86.172 -                    // Good.
  86.173 -                }
  86.174 -                try {
  86.175 -                    FileObject in = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", rsrc);
  86.176 -                    InputStream is = in.openInputStream();
  86.177 -                    try {
  86.178 -                        BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
  86.179 -                        String line;
  86.180 -                        while ((line = r.readLine()) != null) {
  86.181 -                            lines.add(line);
  86.182 -                        }
  86.183 -                    } finally {
  86.184 -                        is.close();
  86.185 -                    }
  86.186 -                } catch (FileNotFoundException x) {
  86.187 -                    // OK, created for the first time
  86.188 -                }
  86.189 -            } catch (IOException x) {
  86.190 -                processingEnv.getMessager().printMessage(Kind.ERROR, x.toString());
  86.191 -                return;
  86.192 -            }
  86.193 -            outputFiles.put(rsrc, lines);
  86.194 -        }
  86.195 -        int idx = lines.indexOf(impl);
  86.196 -        if (idx != -1) {
  86.197 -            lines.remove(idx);
  86.198 -            while (lines.size() > idx && lines.get(idx).matches("#position=.+|#-.+")) {
  86.199 -                lines.remove(idx);
  86.200 -            }
  86.201 -        }
  86.202 -        lines.add(impl);
  86.203 -        if (position != Integer.MAX_VALUE) {
  86.204 -            lines.add("#position=" + position);
  86.205 -        }
  86.206 -        for (String exclude : supersedes) {
  86.207 -            lines.add("#-" + exclude);
  86.208 -        }
  86.209 -    }
  86.210 -
  86.211 -    /**
  86.212 -     * @param element a source element
  86.213 -     * @param annotation a type of annotation
  86.214 -     * @return the instance of that annotation on the element, or null if not found
  86.215 -     */
  86.216 -    private AnnotationMirror findAnnotationMirror(Element element, Class<? extends Annotation> annotation) {
  86.217 -        for (AnnotationMirror ann : element.getAnnotationMirrors()) {
  86.218 -            if (processingEnv.getElementUtils().getBinaryName((TypeElement) ann.getAnnotationType().asElement()).
  86.219 -                    contentEquals(annotation.getName())) {
  86.220 -                return ann;
  86.221 -            }
  86.222 -        }
  86.223 -        return null;
  86.224 -    }
  86.225 -
  86.226 -    /**
  86.227 -     * @param annotation an annotation instance (null permitted)
  86.228 -     * @param name the name of an attribute of that annotation
  86.229 -     * @return the corresponding value if found
  86.230 -     */
  86.231 -    private AnnotationValue findAnnotationValue(AnnotationMirror annotation, String name) {
  86.232 -        if (annotation != null) {
  86.233 -            for (Map.Entry<? extends ExecutableElement,? extends AnnotationValue> entry : annotation.getElementValues().entrySet()) {
  86.234 -                if (entry.getKey().getSimpleName().contentEquals(name)) {
  86.235 -                    return entry.getValue();
  86.236 -                }
  86.237 -            }
  86.238 -        }
  86.239 -        return null;
  86.240 -    }
  86.241 -
  86.242 -    private final boolean verifyServiceProviderSignature(TypeElement clazz, Class<? extends Annotation> annotation) {
  86.243 -        AnnotationMirror ann = findAnnotationMirror(clazz, annotation);
  86.244 -        if (!clazz.getModifiers().contains(Modifier.PUBLIC)) {
  86.245 -            processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must be public", clazz, ann);
  86.246 -            return false;
  86.247 -        }
  86.248 -        if (clazz.getModifiers().contains(Modifier.ABSTRACT)) {
  86.249 -            processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must not be abstract", clazz, ann);
  86.250 -            return false;
  86.251 -        }
  86.252 -        {
  86.253 -            boolean hasDefaultCtor = false;
  86.254 -            for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
  86.255 -                if (constructor.getModifiers().contains(Modifier.PUBLIC) && constructor.getParameters().isEmpty()) {
  86.256 -                    hasDefaultCtor = true;
  86.257 -                    break;
  86.258 -                }
  86.259 -            }
  86.260 -            if (!hasDefaultCtor) {
  86.261 -                processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must have a public no-argument constructor", clazz, ann);
  86.262 -                return false;
  86.263 -            }
  86.264 -        }
  86.265 -        return true;
  86.266 -    }
  86.267 -
  86.268 -    private void writeServices() {
  86.269 -        for (Map.Entry<ProcessingEnvironment,Map<String,List<String>>> outputFiles : outputFilesByProcessor.entrySet()) {
  86.270 -            for (Map.Entry<String, List<String>> entry : outputFiles.getValue().entrySet()) {
  86.271 -                try {
  86.272 -                    FileObject out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", entry.getKey(),
  86.273 -                            originatingElementsByProcessor.get(outputFiles.getKey()).get(entry.getKey()).toArray(new Element[0]));
  86.274 -                    OutputStream os = out.openOutputStream();
  86.275 -                    try {
  86.276 -                        PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
  86.277 -                        for (String line : entry.getValue()) {
  86.278 -                            w.println(line);
  86.279 -                        }
  86.280 -                        w.flush();
  86.281 -                        w.close();
  86.282 -                    } finally {
  86.283 -                        os.close();
  86.284 -                    }
  86.285 -                } catch (IOException x) {
  86.286 -                    processingEnv.getMessager().printMessage(Kind.ERROR, "Failed to write to " + entry.getKey() + ": " + x.toString());
  86.287 -                }
  86.288 -            }
  86.289 -        }
  86.290 -    }
  86.291 -
  86.292 -}
    87.1 --- a/openide.util/src/org/netbeans/modules/openide/util/ActiveQueue.java	Thu Dec 10 19:23:25 2009 -0500
    87.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.3 @@ -1,108 +0,0 @@
    87.4 -package org.netbeans.modules.openide.util;
    87.5 -
    87.6 -import java.lang.ref.Reference;
    87.7 -import java.lang.ref.ReferenceQueue;
    87.8 -import java.util.logging.Level;
    87.9 -import java.util.logging.Logger;
   87.10 -
   87.11 -/**
   87.12 - * Implementation of the active reference queue.
   87.13 - */
   87.14 -public final class ActiveQueue extends ReferenceQueue<Object> implements Runnable {
   87.15 -
   87.16 -    private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
   87.17 -    private static ActiveQueue activeReferenceQueue;
   87.18 -    
   87.19 -    /** number of known outstanding references */
   87.20 -    private int count;
   87.21 -    private boolean deprecated;
   87.22 -
   87.23 -    ActiveQueue(boolean deprecated) {
   87.24 -        super();
   87.25 -        this.deprecated = deprecated;
   87.26 -    }
   87.27 -
   87.28 -    public static synchronized ReferenceQueue<Object> queue() {
   87.29 -        if (activeReferenceQueue == null) {
   87.30 -            activeReferenceQueue = new ActiveQueue(false);
   87.31 -        }
   87.32 -
   87.33 -        activeReferenceQueue.ping();
   87.34 -
   87.35 -        return activeReferenceQueue;
   87.36 -    }
   87.37 -
   87.38 -    @Override
   87.39 -    public Reference<Object> poll() {
   87.40 -        throw new UnsupportedOperationException();
   87.41 -    }
   87.42 -
   87.43 -    @Override
   87.44 -    public Reference<Object> remove(long timeout) throws IllegalArgumentException, InterruptedException {
   87.45 -        throw new InterruptedException();
   87.46 -    }
   87.47 -
   87.48 -    @Override
   87.49 -    public Reference<Object> remove() throws InterruptedException {
   87.50 -        throw new InterruptedException();
   87.51 -    }
   87.52 -
   87.53 -    public void run() {
   87.54 -        while (true) {
   87.55 -            try {
   87.56 -                Reference<?> ref = super.remove(0);
   87.57 -                LOGGER.finer("dequeued reference");
   87.58 -                if (!(ref instanceof Runnable)) {
   87.59 -                    LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass());
   87.60 -                    continue;
   87.61 -                }
   87.62 -                if (deprecated) {
   87.63 -                    LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue");
   87.64 -                }
   87.65 -                // do the cleanup
   87.66 -                try {
   87.67 -                    ((Runnable) ref).run();
   87.68 -                } catch (ThreadDeath td) {
   87.69 -                    throw td;
   87.70 -                } catch (Throwable t) {
   87.71 -                    // Should not happen.
   87.72 -                    // If it happens, it is a bug in client code, notify!
   87.73 -                    LOGGER.log(Level.WARNING, null, t);
   87.74 -                } finally {
   87.75 -                    // to allow GC
   87.76 -                    ref = null;
   87.77 -                }
   87.78 -            } catch (InterruptedException ex) {
   87.79 -                // Can happen during VM shutdown, it seems. Ignore.
   87.80 -                continue;
   87.81 -            }
   87.82 -            synchronized (this) {
   87.83 -                assert count > 0;
   87.84 -                count--;
   87.85 -                if (count == 0) {
   87.86 -                    // We have processed all we have to process (for now at least).
   87.87 -                    // Could be restarted later if ping() called again.
   87.88 -                    // This could also happen in case someone called queue() once and tried
   87.89 -                    // to use it for several references; in that case run() might never be called on
   87.90 -                    // the later ones to be collected. Can't really protect against that situation.
   87.91 -                    // See issue #86625 for details.
   87.92 -                    LOGGER.fine("stopping thread");
   87.93 -                    break;
   87.94 -                }
   87.95 -            }
   87.96 -        }
   87.97 -    }
   87.98 -
   87.99 -    synchronized void ping() {
  87.100 -        if (count == 0) {
  87.101 -            Thread t = new Thread(this, "Active Reference Queue Daemon");
  87.102 -            t.setPriority(Thread.MIN_PRIORITY);
  87.103 -            t.setDaemon(true);
  87.104 -            t.start();
  87.105 -            LOGGER.fine("starting thread");
  87.106 -        } else {
  87.107 -            LOGGER.finer("enqueuing reference");
  87.108 -        }
  87.109 -        count++;
  87.110 -    }
  87.111 -}
    88.1 --- a/openide.util/src/org/netbeans/modules/openide/util/NamedServicesProvider.java	Thu Dec 10 19:23:25 2009 -0500
    88.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.3 @@ -1,81 +0,0 @@
    88.4 -/*
    88.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    88.6 - *
    88.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    88.8 - *
    88.9 - * The contents of this file are subject to the terms of either the GNU
   88.10 - * General Public License Version 2 only ("GPL") or the Common
   88.11 - * Development and Distribution License("CDDL") (collectively, the
   88.12 - * "License"). You may not use this file except in compliance with the
   88.13 - * License. You can obtain a copy of the License at
   88.14 - * http://www.netbeans.org/cddl-gplv2.html
   88.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   88.16 - * specific language governing permissions and limitations under the
   88.17 - * License.  When distributing the software, include this License Header
   88.18 - * Notice in each file and include the License file at
   88.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   88.20 - * particular file as subject to the "Classpath" exception as provided
   88.21 - * by Sun in the GPL Version 2 section of the License file that
   88.22 - * accompanied this code. If applicable, add the following below the
   88.23 - * License Header, with the fields enclosed by brackets [] replaced by
   88.24 - * your own identifying information:
   88.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   88.26 - *
   88.27 - * Contributor(s):
   88.28 - *
   88.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   88.30 - * Software is Sun Microsystems, Inc.
   88.31 - *
   88.32 - * Portions Copyrighted 2006 Sun Microsystems, Inc.
   88.33 - */
   88.34 -
   88.35 -package org.netbeans.modules.openide.util;
   88.36 -
   88.37 -import java.lang.ref.Reference;
   88.38 -import java.lang.ref.WeakReference;
   88.39 -import java.util.Collections;
   88.40 -import java.util.HashMap;
   88.41 -import java.util.Map;
   88.42 -import org.openide.util.Lookup;
   88.43 -import org.openide.util.lookup.Lookups;
   88.44 -
   88.45 -/** Interface for core/startup and core/settings
   88.46 - * to provide lookup over system filesystem.
   88.47 - *
   88.48 - * @author Jaroslav Tulach
   88.49 - */
   88.50 -public abstract class NamedServicesProvider {
   88.51 -
   88.52 -    private static final Map<String,Reference<Lookup>> map = Collections.synchronizedMap(new HashMap<String,Reference<Lookup>>());
   88.53 -    
   88.54 -    public abstract Lookup create(String path);
   88.55 -    
   88.56 -    public static Lookup find(String path) {
   88.57 -        if (!path.endsWith("/")) {
   88.58 -            path = path + "/";
   88.59 -        }
   88.60 -        
   88.61 -        Reference<Lookup> ref = map.get(path);
   88.62 -        Lookup lkp = ref == null ? null : ref.get();
   88.63 -        if (lkp != null) {
   88.64 -            return lkp;
   88.65 -        }
   88.66 -        NamedServicesProvider prov = Lookup.getDefault().lookup(NamedServicesProvider.class);
   88.67 -        if (prov != null && /* avoid stack overflow during initialization */ !path.startsWith(URLStreamHandlerRegistrationProcessor.REGISTRATION_PREFIX)) {
   88.68 -            lkp = prov.create(path);
   88.69 -        } else {
   88.70 -            ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
   88.71 -            if (l == null) {
   88.72 -                l = Thread.currentThread().getContextClassLoader();
   88.73 -                if (l == null) {
   88.74 -                    l = NamedServicesProvider.class.getClassLoader();
   88.75 -                }
   88.76 -            }
   88.77 -            lkp = Lookups.metaInfServices(l, "META-INF/namedservices/" + path);
   88.78 -        }
   88.79 -        
   88.80 -        map.put(path, new WeakReference<Lookup>(lkp));
   88.81 -        return lkp;
   88.82 -    }
   88.83 -    
   88.84 -}
    89.1 --- a/openide.util/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java	Thu Dec 10 19:23:25 2009 -0500
    89.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.3 @@ -1,173 +0,0 @@
    89.4 -/*
    89.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    89.6 - *
    89.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    89.8 - *
    89.9 - * The contents of this file are subject to the terms of either the GNU
   89.10 - * General Public License Version 2 only ("GPL") or the Common
   89.11 - * Development and Distribution License("CDDL") (collectively, the
   89.12 - * "License"). You may not use this file except in compliance with the
   89.13 - * License. You can obtain a copy of the License at
   89.14 - * http://www.netbeans.org/cddl-gplv2.html
   89.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   89.16 - * specific language governing permissions and limitations under the
   89.17 - * License.  When distributing the software, include this License Header
   89.18 - * Notice in each file and include the License file at
   89.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   89.20 - * particular file as subject to the "Classpath" exception as provided
   89.21 - * by Sun in the GPL Version 2 section of the License file that
   89.22 - * accompanied this code. If applicable, add the following below the
   89.23 - * License Header, with the fields enclosed by brackets [] replaced by
   89.24 - * your own identifying information:
   89.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   89.26 - *
   89.27 - * If you wish your version of this file to be governed by only the CDDL
   89.28 - * or only the GPL Version 2, indicate your decision by adding
   89.29 - * "[Contributor] elects to include this software in this distribution
   89.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   89.31 - * single choice of license, a recipient has the option to distribute
   89.32 - * your version of this file under either the CDDL, the GPL Version 2 or
   89.33 - * to extend the choice of license to its licensees as provided above.
   89.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   89.35 - * Version 2 license, then the option applies only if the new code is
   89.36 - * made subject to such option by the copyright holder.
   89.37 - *
   89.38 - * Contributor(s):
   89.39 - *
   89.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   89.41 - */
   89.42 -
   89.43 -package org.netbeans.modules.openide.util;
   89.44 -
   89.45 -import java.lang.annotation.Annotation;
   89.46 -import java.util.Arrays;
   89.47 -import java.util.Collection;
   89.48 -import java.util.Collections;
   89.49 -import java.util.HashSet;
   89.50 -import java.util.LinkedList;
   89.51 -import java.util.List;
   89.52 -import java.util.Set;
   89.53 -import javax.annotation.processing.Completion;
   89.54 -import javax.annotation.processing.RoundEnvironment;
   89.55 -import javax.annotation.processing.SupportedSourceVersion;
   89.56 -import javax.lang.model.SourceVersion;
   89.57 -import javax.lang.model.element.AnnotationMirror;
   89.58 -import javax.lang.model.element.Element;
   89.59 -import javax.lang.model.element.ExecutableElement;
   89.60 -import javax.lang.model.element.TypeElement;
   89.61 -import javax.lang.model.type.MirroredTypeException;
   89.62 -import javax.lang.model.type.TypeKind;
   89.63 -import javax.lang.model.type.TypeMirror;
   89.64 -import org.openide.util.lookup.ServiceProvider;
   89.65 -import org.openide.util.lookup.ServiceProviders;
   89.66 -
   89.67 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
   89.68 -public class ServiceProviderProcessor extends AbstractServiceProviderProcessor {
   89.69 -
   89.70 -    public @Override Set<String> getSupportedAnnotationTypes() {
   89.71 -        return new HashSet<String>(Arrays.asList(
   89.72 -            ServiceProvider.class.getCanonicalName(),
   89.73 -            ServiceProviders.class.getCanonicalName()
   89.74 -        ));
   89.75 -    }
   89.76 -
   89.77 -    /** public for ServiceLoader */
   89.78 -    public ServiceProviderProcessor() {}
   89.79 -
   89.80 -    protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   89.81 -        for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) {
   89.82 -            TypeElement clazz = (TypeElement) el;
   89.83 -            ServiceProvider sp = clazz.getAnnotation(ServiceProvider.class);
   89.84 -            register(clazz, ServiceProvider.class, sp);
   89.85 -        }
   89.86 -        for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProviders.class)) {
   89.87 -            TypeElement clazz = (TypeElement) el;
   89.88 -            ServiceProviders spp = clazz.getAnnotation(ServiceProviders.class);
   89.89 -            for (ServiceProvider sp : spp.value()) {
   89.90 -                register(clazz, ServiceProviders.class, sp);
   89.91 -            }
   89.92 -        }
   89.93 -        return true;
   89.94 -    }
   89.95 -
   89.96 -    private void register(TypeElement clazz, Class<? extends Annotation> annotation, ServiceProvider svc) {
   89.97 -        try {
   89.98 -            svc.service();
   89.99 -            assert false;
  89.100 -            return;
  89.101 -        } catch (MirroredTypeException e) {
  89.102 -            register(clazz, annotation, e.getTypeMirror(), svc.path(), svc.position(), svc.supersedes());
  89.103 -        }
  89.104 -    }
  89.105 -
  89.106 -    @Override
  89.107 -    public Iterable<? extends Completion> getCompletions(Element annotated, AnnotationMirror annotation, ExecutableElement attr, String userText) {
  89.108 -        if (processingEnv == null || annotated == null || !annotated.getKind().isClass()) {
  89.109 -            return Collections.emptyList();
  89.110 -        }
  89.111 -
  89.112 -        if (   annotation == null
  89.113 -            || !"org.openide.util.lookup.ServiceProvider".contentEquals(((TypeElement) annotation.getAnnotationType().asElement()).getQualifiedName())) {
  89.114 -            return Collections.emptyList();
  89.115 -        }
  89.116 -
  89.117 -        if (!"service".contentEquals(attr.getSimpleName())) {
  89.118 -            return Collections.emptyList();
  89.119 -        }
  89.120 -
  89.121 -        TypeElement jlObject = processingEnv.getElementUtils().getTypeElement("java.lang.Object");
  89.122 -
  89.123 -        if (jlObject == null) {
  89.124 -            return Collections.emptyList();
  89.125 -        }
  89.126 -        
  89.127 -        Collection<Completion> result = new LinkedList<Completion>();
  89.128 -        List<TypeElement> toProcess = new LinkedList<TypeElement>();
  89.129 -
  89.130 -        toProcess.add((TypeElement) annotated);
  89.131 -
  89.132 -        while (!toProcess.isEmpty()) {
  89.133 -            TypeElement c = toProcess.remove(0);
  89.134 -
  89.135 -            result.add(new TypeCompletion(c.getQualifiedName().toString() + ".class"));
  89.136 -
  89.137 -            List<TypeMirror> parents = new LinkedList<TypeMirror>();
  89.138 -
  89.139 -            parents.add(c.getSuperclass());
  89.140 -            parents.addAll(c.getInterfaces());
  89.141 -
  89.142 -            for (TypeMirror tm : parents) {
  89.143 -                if (tm == null || tm.getKind() != TypeKind.DECLARED) {
  89.144 -                    continue;
  89.145 -                }
  89.146 -
  89.147 -                TypeElement type = (TypeElement) processingEnv.getTypeUtils().asElement(tm);
  89.148 -
  89.149 -                if (!jlObject.equals(type)) {
  89.150 -                    toProcess.add(type);
  89.151 -                }
  89.152 -            }
  89.153 -        }
  89.154 -
  89.155 -        return result;
  89.156 -    }
  89.157 -
  89.158 -    private static final class TypeCompletion implements Completion {
  89.159 -
  89.160 -        private final String type;
  89.161 -
  89.162 -        public TypeCompletion(String type) {
  89.163 -            this.type = type;
  89.164 -        }
  89.165 -
  89.166 -        public String getValue() {
  89.167 -            return type;
  89.168 -        }
  89.169 -
  89.170 -        public String getMessage() {
  89.171 -            return null;
  89.172 -        }
  89.173 -        
  89.174 -    }
  89.175 -
  89.176 -}
    90.1 --- a/openide.util/src/org/openide/util/Lookup.java	Thu Dec 10 19:23:25 2009 -0500
    90.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.3 @@ -1,544 +0,0 @@
    90.4 -/*
    90.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    90.6 - *
    90.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    90.8 - *
    90.9 - * The contents of this file are subject to the terms of either the GNU
   90.10 - * General Public License Version 2 only ("GPL") or the Common
   90.11 - * Development and Distribution License("CDDL") (collectively, the
   90.12 - * "License"). You may not use this file except in compliance with the
   90.13 - * License. You can obtain a copy of the License at
   90.14 - * http://www.netbeans.org/cddl-gplv2.html
   90.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   90.16 - * specific language governing permissions and limitations under the
   90.17 - * License.  When distributing the software, include this License Header
   90.18 - * Notice in each file and include the License file at
   90.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   90.20 - * particular file as subject to the "Classpath" exception as provided
   90.21 - * by Sun in the GPL Version 2 section of the License file that
   90.22 - * accompanied this code. If applicable, add the following below the
   90.23 - * License Header, with the fields enclosed by brackets [] replaced by
   90.24 - * your own identifying information:
   90.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   90.26 - *
   90.27 - * Contributor(s):
   90.28 - *
   90.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   90.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   90.31 - * Microsystems, Inc. All Rights Reserved.
   90.32 - *
   90.33 - * If you wish your version of this file to be governed by only the CDDL
   90.34 - * or only the GPL Version 2, indicate your decision by adding
   90.35 - * "[Contributor] elects to include this software in this distribution
   90.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   90.37 - * single choice of license, a recipient has the option to distribute
   90.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   90.39 - * to extend the choice of license to its licensees as provided above.
   90.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   90.41 - * Version 2 license, then the option applies only if the new code is
   90.42 - * made subject to such option by the copyright holder.
   90.43 - */
   90.44 -
   90.45 -package org.openide.util;
   90.46 -
   90.47 -import java.util.ArrayList;
   90.48 -import java.util.Collection;
   90.49 -import java.util.Collections;
   90.50 -import java.util.Iterator;
   90.51 -import java.util.List;
   90.52 -import java.util.Set;
   90.53 -import org.openide.util.lookup.Lookups;
   90.54 -import org.openide.util.lookup.ProxyLookup;
   90.55 -import org.openide.util.lookup.ServiceProvider;
   90.56 -
   90.57 -/**
   90.58 - * A general registry permitting clients to find instances of services
   90.59 - * (implementation of a given interface).
   90.60 - * This class is inspired by the
   90.61 - * <a href="http://www.jini.org/">Jini</a>
   90.62 - * registration and lookup mechanism. The difference is that the methods do
   90.63 - * not throw checked exceptions (as they usually work only locally and not over the network)
   90.64 - * and that the Lookup API concentrates on the lookup, not on the registration
   90.65 - * (although {@link Lookup#getDefault} is strongly encouraged to support
   90.66 - * {@link Lookups#metaInfServices} for registration in addition to whatever
   90.67 - * else it decides to support).
   90.68 - * <p>
   90.69 - * For a general talk about the idea behind the lookup pattern please see
   90.70 - * <UL>
   90.71 - *      <LI><a href="lookup/doc-files/index.html">The Solution to Communication Between Components</a>
   90.72 - *      page
   90.73 - *      <LI>the introduction to the <a href="lookup/doc-files/lookup-api.html">lookup API via
   90.74 - *      use cases</a>
   90.75 - *      <LI>the examples of <a href="lookup/doc-files/lookup-spi.html">how to write your own lookup</a>
   90.76 - * </UL>
   90.77 - *
   90.78 - * @see org.openide.util.lookup.AbstractLookup
   90.79 - * @see Lookups
   90.80 - * @see LookupListener
   90.81 - * @see LookupEvent
   90.82 - * @author  Jaroslav Tulach
   90.83 - */
   90.84 -public abstract class Lookup {
   90.85 -    /** A dummy lookup that never returns any results.
   90.86 -     */
   90.87 -    public static final Lookup EMPTY = new Empty();
   90.88 -
   90.89 -    /** default instance */
   90.90 -    private static Lookup defaultLookup;
   90.91 -
   90.92 -    /** Empty constructor for use by subclasses. */
   90.93 -    public Lookup() {
   90.94 -    }
   90.95 -
   90.96 -    /** Static method to obtain the global lookup in the whole system.
   90.97 -     * The actual returned implementation can be different in different
   90.98 -     * systems, but the default one is based on
   90.99 -     * {@link org.openide.util.lookup.Lookups#metaInfServices}
  90.100 -     * with the context classloader of the first caller. Each system is
  90.101 -     * adviced to honor this and include some form of <code>metaInfServices</code>
  90.102 -     * implementation in the returned lookup as usage of <code>META-INF/services</code>
  90.103 -     * is a JDK standard.
  90.104 -     *
  90.105 -     * @return the global lookup in the system
  90.106 -     * @see ServiceProvider
  90.107 -     */
  90.108 -    public static synchronized Lookup getDefault() {
  90.109 -        if (defaultLookup != null) {
  90.110 -            return defaultLookup;
  90.111 -        }
  90.112 -
  90.113 -        // You can specify a Lookup impl using a system property if you like.
  90.114 -        String className = System.getProperty("org.openide.util.Lookup" // NOI18N
  90.115 -            );
  90.116 -
  90.117 -        if ("-".equals(className)) { // NOI18N
  90.118 -
  90.119 -            // Suppress even MetaInfServicesLookup.
  90.120 -            return EMPTY;
  90.121 -        }
  90.122 -
  90.123 -        ClassLoader l = Thread.currentThread().getContextClassLoader();
  90.124 -
  90.125 -        try {
  90.126 -            if (className != null) {
  90.127 -                defaultLookup = (Lookup) Class.forName(className, true, l).newInstance();
  90.128 -
  90.129 -                return defaultLookup;
  90.130 -            }
  90.131 -        } catch (Exception e) {
  90.132 -            // do not use ErrorManager because we are in the startup code
  90.133 -            // and ErrorManager might not be ready
  90.134 -            e.printStackTrace();
  90.135 -        }
  90.136 -
  90.137 -        // OK, none specified (successfully) in a system property.
  90.138 -        // Try MetaInfServicesLookup as a default, which may also
  90.139 -        // have a org.openide.util.Lookup line specifying the lookup.
  90.140 -        Lookup misl = Lookups.metaInfServices(l);
  90.141 -        defaultLookup = misl.lookup(Lookup.class);
  90.142 -
  90.143 -        if (defaultLookup != null) {
  90.144 -            return defaultLookup;
  90.145 -        }
  90.146 -
  90.147 -        // You may also specify a Lookup.Provider.
  90.148 -        Lookup.Provider prov = misl.lookup(Lookup.Provider.class);
  90.149 -
  90.150 -        if (prov != null) {
  90.151 -            defaultLookup = Lookups.proxy(prov);
  90.152 -
  90.153 -            return defaultLookup;
  90.154 -        }
  90.155 -
  90.156 -        DefLookup def = new DefLookup();
  90.157 -        def.init(l, misl, false);
  90.158 -        defaultLookup = def;
  90.159 -        def.init(l, misl, true);
  90.160 -        return defaultLookup;
  90.161 -    }
  90.162 -    
  90.163 -    private static final class DefLookup extends ProxyLookup {
  90.164 -        public DefLookup() {
  90.165 -            super(new Lookup[0]);
  90.166 -        }
  90.167 -        
  90.168 -        public void init(ClassLoader loader, Lookup metaInfLookup, boolean addPath) {
  90.169 -            // Had no such line, use simple impl.
  90.170 -            // It does however need to have ClassLoader available or many things will break.
  90.171 -            // Use the thread context classloader in effect now.
  90.172 -            Lookup clLookup = Lookups.singleton(loader);
  90.173 -            List<Lookup> arr = new ArrayList<Lookup>();
  90.174 -            arr.add(metaInfLookup);
  90.175 -            arr.add(clLookup);
  90.176 -            String paths = System.getProperty("org.openide.util.Lookup.paths"); // NOI18N
  90.177 -            if (addPath && paths != null) {
  90.178 -                for (String p : paths.split(":")) { // NOI18N
  90.179 -                    arr.add(Lookups.forPath(p));
  90.180 -                }
  90.181 -            }
  90.182 -            setLookups(arr.toArray(new Lookup[0]));
  90.183 -        }
  90.184 -    }
  90.185 -    
  90.186 -    /** Called from MockServices to reset default lookup in case services change
  90.187 -     */
  90.188 -    private static void resetDefaultLookup() {
  90.189 -        if (defaultLookup instanceof DefLookup) {
  90.190 -            DefLookup def = (DefLookup)defaultLookup;
  90.191 -            ClassLoader l = Thread.currentThread().getContextClassLoader();
  90.192 -            def.init(l, Lookups.metaInfServices(l), true);
  90.193 -        }
  90.194 -    }
  90.195 -
  90.196 -    /** Look up an object matching a given interface.
  90.197 -     * This is the simplest method to use.
  90.198 -     * If more than one object matches, the first will be returned.
  90.199 -     * The template class may be a class or interface; the instance is
  90.200 -     * guaranteed to be assignable to it.
  90.201 -     *
  90.202 -     * @param clazz class of the object we are searching for
  90.203 -     * @return an object implementing the given class or <code>null</code> if no such
  90.204 -     *         implementation is found
  90.205 -     */
  90.206 -    public abstract <T> T lookup(Class<T> clazz);
  90.207 -
  90.208 -    /** The general lookup method. Callers can get list of all instances and classes
  90.209 -     * that match the given <code>template</code>, request more info about
  90.210 -     * them in form of {@link Lookup.Item} and attach a listener to
  90.211 -     * this be notified about changes. The general interface does not
  90.212 -     * specify whether subsequent calls with the same template produce new
  90.213 -     * instance of the {@link Lookup.Result} or return shared instance. The
  90.214 -     * prefered behaviour however is to return shared one.
  90.215 -     *
  90.216 -     * @param template a template describing the services to look for
  90.217 -     * @return an object containing the results
  90.218 -     */
  90.219 -    public abstract <T> Result<T> lookup(Template<T> template);
  90.220 -
  90.221 -    /** Look up the first item matching a given template.
  90.222 -     * Includes not only the instance but other associated information.
  90.223 -     * @param template the template to check
  90.224 -     * @return a matching item or <code>null</code>
  90.225 -     *
  90.226 -     * @since 1.8
  90.227 -     */
  90.228 -    public <T> Item<T> lookupItem(Template<T> template) {
  90.229 -        Result<T> res = lookup(template);
  90.230 -        Iterator<? extends Item<T>> it = res.allItems().iterator();
  90.231 -        return it.hasNext() ? it.next() : null;
  90.232 -    }
  90.233 -
  90.234 -    /**
  90.235 -     * Find a result corresponding to a given class.
  90.236 -     * Equivalent to calling {@link #lookup(Lookup.Template)} but slightly more convenient.
  90.237 -     * Subclasses may override this method to produce the same semantics more efficiently.
  90.238 -     * @param clazz the supertype of the result
  90.239 -     * @return a live object representing instances of that type
  90.240 -     * @since org.openide.util 6.10
  90.241 -     */
  90.242 -    public <T> Lookup.Result<T> lookupResult(Class<T> clazz) {
  90.243 -        return lookup(new Lookup.Template<T>(clazz));
  90.244 -    }
  90.245 -
  90.246 -    /**
  90.247 -     * Find all instances corresponding to a given class.
  90.248 -     * Equivalent to calling {@link #lookupResult} and asking for {@link Lookup.Result#allInstances} but slightly more convenient.
  90.249 -     * Subclasses may override this method to produce the same semantics more efficiently.
  90.250 -     * <div class="nonnormative">
  90.251 -     * <p>Example usage:</p>
  90.252 -     * <pre>
  90.253 -     * for (MyService svc : Lookup.getDefault().lookupAll(MyService.class)) {
  90.254 -     *     svc.useMe();
  90.255 -     * }
  90.256 -     * </pre>
  90.257 -     * </div>
  90.258 -     * @param clazz the supertype of the result
  90.259 -     * @return all currently available instances of that type
  90.260 -     * @since org.openide.util 6.10
  90.261 -     */
  90.262 -    public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
  90.263 -        return lookupResult(clazz).allInstances();
  90.264 -    }
  90.265 -
  90.266 -    /**
  90.267 -     * Objects implementing interface Lookup.Provider are capable of
  90.268 -     * and willing to provide a lookup (usually bound to the object).
  90.269 -     * @since 3.6
  90.270 -     */
  90.271 -    public interface Provider {
  90.272 -        /**
  90.273 -         * Returns lookup associated with the object.
  90.274 -         * @return fully initialized lookup instance provided by this object
  90.275 -         */
  90.276 -        Lookup getLookup();
  90.277 -    }
  90.278 -
  90.279 -    /*
  90.280 -     * I expect this class to grow in the future, but for now, it is
  90.281 -     * enough to start with something simple.
  90.282 -     */
  90.283 -
  90.284 -    /** Template defining a pattern to filter instances by.
  90.285 -     */
  90.286 -    public static final class Template<T> extends Object {
  90.287 -        /** cached hash code */
  90.288 -        private int hashCode;
  90.289 -
  90.290 -        /** type of the service */
  90.291 -        private Class<T> type;
  90.292 -
  90.293 -        /** identity to search for */
  90.294 -        private String id;
  90.295 -
  90.296 -        /** instance to search for */
  90.297 -        private T instance;
  90.298 -
  90.299 -        /** General template to find all possible instances.
  90.300 -         * @deprecated Use <code>new Template (Object.class)</code> which
  90.301 -         *   is going to be better typed with JDK1.5 templates and should produce
  90.302 -         *   the same result.
  90.303 -         */
  90.304 -        @Deprecated
  90.305 -        public Template() {
  90.306 -            this(null);
  90.307 -        }
  90.308 -
  90.309 -        /** Create a simple template matching by class.
  90.310 -         * @param type the class of service we are looking for (subclasses will match)
  90.311 -         */
  90.312 -        public Template(Class<T> type) {
  90.313 -            this(type, null, null);
  90.314 -        }
  90.315 -
  90.316 -        /** Constructor to create new template.
  90.317 -         * @param type the class of service we are looking for or <code>null</code> to leave unspecified
  90.318 -         * @param id the ID of the item/service we are looking for or <code>null</code> to leave unspecified
  90.319 -         * @param instance a specific known instance to look for or <code>null</code> to leave unspecified
  90.320 -         */
  90.321 -        public Template(Class<T> type, String id, T instance) {
  90.322 -            this.type = extractType(type);
  90.323 -            this.id = id;
  90.324 -            this.instance = instance;
  90.325 -        }
  90.326 -
  90.327 -        @SuppressWarnings("unchecked")
  90.328 -        private Class<T> extractType(Class<T> type) {
  90.329 -            return (type == null) ? (Class<T>)Object.class : type;
  90.330 -        }
  90.331 -
  90.332 -        /** Get the class (or superclass or interface) to search for.
  90.333 -         * If it was not specified in the constructor, <code>Object</code> is used as
  90.334 -         * this will match any instance.
  90.335 -         * @return the class to search for
  90.336 -         */
  90.337 -        public Class<T> getType() {
  90.338 -            return type;
  90.339 -        }
  90.340 -
  90.341 -        /** Get the persistent identifier being searched for, if any.
  90.342 -         * @return the ID or <code>null</code>
  90.343 -         * @see Lookup.Item#getId
  90.344 -         *
  90.345 -         * @since 1.8
  90.346 -         */
  90.347 -        public String getId() {
  90.348 -            return id;
  90.349 -        }
  90.350 -
  90.351 -        /** Get the specific instance being searched for, if any.
  90.352 -         * Most useful for finding an <code>Item</code> when the instance
  90.353 -         * is already known.
  90.354 -         *
  90.355 -         * @return the object to find or <code>null</code>
  90.356 -         *
  90.357 -         * @since 1.8
  90.358 -         */
  90.359 -        public T getInstance() {
  90.360 -            return instance;
  90.361 -        }
  90.362 -
  90.363 -        /* Computes hashcode for this template. The hashcode is cached.
  90.364 -         * @return hashcode
  90.365 -         */
  90.366 -        @Override
  90.367 -        public int hashCode() {
  90.368 -            if (hashCode != 0) {
  90.369 -                return hashCode;
  90.370 -            }
  90.371 -
  90.372 -            hashCode = ((type == null) ? 1 : type.hashCode()) + ((id == null) ? 2 : id.hashCode()) +
  90.373 -                ((instance == null) ? 3 : 0);
  90.374 -
  90.375 -            return hashCode;
  90.376 -        }
  90.377 -
  90.378 -        /* Checks whether two templates represent the same query.
  90.379 -         * @param obj another template to check
  90.380 -         * @return true if so, false otherwise
  90.381 -         */
  90.382 -        @Override
  90.383 -        public boolean equals(Object obj) {
  90.384 -            if (!(obj instanceof Template)) {
  90.385 -                return false;
  90.386 -            }
  90.387 -
  90.388 -            Template t = (Template) obj;
  90.389 -
  90.390 -            if (hashCode() != t.hashCode()) {
  90.391 -                // this is an optimalization - the hashCodes should have been
  90.392 -                // precomputed
  90.393 -                return false;
  90.394 -            }
  90.395 -
  90.396 -            if (type != t.type) {
  90.397 -                return false;
  90.398 -            }
  90.399 -
  90.400 -            if (id == null) {
  90.401 -                if (t.id != null) {
  90.402 -                    return false;
  90.403 -                }
  90.404 -            } else {
  90.405 -                if (!id.equals(t.id)) {
  90.406 -                    return false;
  90.407 -                }
  90.408 -            }
  90.409 -
  90.410 -            if (instance == null) {
  90.411 -                return (t.instance == null);
  90.412 -            } else {
  90.413 -                return instance.equals(t.instance);
  90.414 -            }
  90.415 -        }
  90.416 -
  90.417 -        /* for debugging */
  90.418 -        @Override
  90.419 -        public String toString() {
  90.420 -            return "Lookup.Template[type=" + type + ",id=" + id + ",instance=" + instance + "]"; // NOI18N
  90.421 -        }
  90.422 -    }
  90.423 -
  90.424 -    /** Result of a lookup request.
  90.425 -     * Allows access to all matching instances at once.
  90.426 -     * Also permits listening to changes in the result.
  90.427 -     * Result can contain duplicate items.
  90.428 -     */
  90.429 -    public static abstract class Result<T> extends Object {
  90.430 -        /** Registers a listener that is invoked when there is a possible
  90.431 -         * change in this result.
  90.432 -         *
  90.433 -         * @param l the listener to add
  90.434 -         */
  90.435 -        public abstract void addLookupListener(LookupListener l);
  90.436 -
  90.437 -        /** Unregisters a listener previously added.
  90.438 -         * @param l the listener to remove
  90.439 -         */
  90.440 -        public abstract void removeLookupListener(LookupListener l);
  90.441 -
  90.442 -        /** Get all instances in the result. The return value type
  90.443 -         * should be List instead of Collection, but it is too late to change it.
  90.444 -         * @return unmodifiable collection of all instances that will never change its content
  90.445 -         */
  90.446 -        public abstract Collection<? extends T> allInstances();
  90.447 -
  90.448 -        /** Get all classes represented in the result.
  90.449 -         * That is, the set of concrete classes
  90.450 -         * used by instances present in the result.
  90.451 -         * All duplicate classes will be omitted.
  90.452 -         * @return unmodifiable set of <code>Class</code> objects that will never change its content
  90.453 -         *
  90.454 -         * @since 1.8
  90.455 -         */
  90.456 -        public Set<Class<? extends T>> allClasses() {
  90.457 -            return Collections.emptySet();
  90.458 -        }
  90.459 -
  90.460 -        /** Get all registered items.
  90.461 -         * This should include all pairs of instances together
  90.462 -         * with their classes, IDs, and so on. The return value type
  90.463 -         * should be List instead of Collection, but it is too late to change it.
  90.464 -         * @return unmodifiable collection of {@link Lookup.Item} that will never change its content
  90.465 -         *
  90.466 -         * @since 1.8
  90.467 -         */
  90.468 -        public Collection<? extends Item<T>> allItems() {
  90.469 -            return Collections.emptyList();
  90.470 -        }
  90.471 -    }
  90.472 -
  90.473 -    /** A single item in a lookup result.
  90.474 -     * This wrapper provides unified access to not just the instance,
  90.475 -     * but its class, a possible persistent identifier, and so on.
  90.476 -     *
  90.477 -     * @since 1.25
  90.478 -     */
  90.479 -    public static abstract class Item<T> extends Object {
  90.480 -        /** Get the instance itself.
  90.481 -         * @return the instance or null if the instance cannot be created
  90.482 -         */
  90.483 -        public abstract T getInstance();
  90.484 -
  90.485 -        /** Get the implementing class of the instance.
  90.486 -         * @return the class of the item
  90.487 -         */
  90.488 -        public abstract Class<? extends T> getType();
  90.489 -
  90.490 -        // XXX can it be null??
  90.491 -
  90.492 -        /** Get a persistent indentifier for the item.
  90.493 -         * This identifier should uniquely represent the item
  90.494 -         * within its containing lookup (and if possible within the
  90.495 -         * global lookup as a whole). For example, it might represent
  90.496 -         * the source of the instance as a file name. The ID may be
  90.497 -         * persisted and in a later session used to find the same instance
  90.498 -         * as was encountered earlier, by means of passing it into a
  90.499 -         * lookup template.
  90.500 -         *
  90.501 -         * @return a string ID of the item
  90.502 -         */
  90.503 -        public abstract String getId();
  90.504 -
  90.505 -        /** Get a human presentable name for the item.
  90.506 -         * This might be used when summarizing all the items found in a
  90.507 -         * lookup result in some part of a GUI.
  90.508 -         * @return the string suitable for presenting the object to a user
  90.509 -         */
  90.510 -        public abstract String getDisplayName();
  90.511 -
  90.512 -        /* show ID for debugging */
  90.513 -        @Override
  90.514 -        public String toString() {
  90.515 -            return getId();
  90.516 -        }
  90.517 -    }
  90.518 -
  90.519 -    //
  90.520 -    // Implementation of the default lookup
  90.521 -    //
  90.522 -    private static final class Empty extends Lookup {
  90.523 -        private static final Result NO_RESULT = new Result() {
  90.524 -                public void addLookupListener(LookupListener l) {
  90.525 -                }
  90.526 -
  90.527 -                public void removeLookupListener(LookupListener l) {
  90.528 -                }
  90.529 -
  90.530 -                public Collection allInstances() {
  90.531 -                    return Collections.EMPTY_SET;
  90.532 -                }
  90.533 -            };
  90.534 -
  90.535 -        Empty() {
  90.536 -        }
  90.537 -
  90.538 -        public <T> T lookup(Class<T> clazz) {
  90.539 -            return null;
  90.540 -        }
  90.541 -
  90.542 -        @SuppressWarnings("unchecked")
  90.543 -        public <T> Result<T> lookup(Template<T> template) {
  90.544 -            return NO_RESULT;
  90.545 -        }
  90.546 -    }
  90.547 -}
    91.1 --- a/openide.util/src/org/openide/util/LookupEvent.java	Thu Dec 10 19:23:25 2009 -0500
    91.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.3 @@ -1,57 +0,0 @@
    91.4 -/*
    91.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    91.6 - *
    91.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    91.8 - *
    91.9 - * The contents of this file are subject to the terms of either the GNU
   91.10 - * General Public License Version 2 only ("GPL") or the Common
   91.11 - * Development and Distribution License("CDDL") (collectively, the
   91.12 - * "License"). You may not use this file except in compliance with the
   91.13 - * License. You can obtain a copy of the License at
   91.14 - * http://www.netbeans.org/cddl-gplv2.html
   91.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   91.16 - * specific language governing permissions and limitations under the
   91.17 - * License.  When distributing the software, include this License Header
   91.18 - * Notice in each file and include the License file at
   91.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   91.20 - * particular file as subject to the "Classpath" exception as provided
   91.21 - * by Sun in the GPL Version 2 section of the License file that
   91.22 - * accompanied this code. If applicable, add the following below the
   91.23 - * License Header, with the fields enclosed by brackets [] replaced by
   91.24 - * your own identifying information:
   91.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   91.26 - *
   91.27 - * Contributor(s):
   91.28 - *
   91.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   91.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   91.31 - * Microsystems, Inc. All Rights Reserved.
   91.32 - *
   91.33 - * If you wish your version of this file to be governed by only the CDDL
   91.34 - * or only the GPL Version 2, indicate your decision by adding
   91.35 - * "[Contributor] elects to include this software in this distribution
   91.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   91.37 - * single choice of license, a recipient has the option to distribute
   91.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   91.39 - * to extend the choice of license to its licensees as provided above.
   91.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   91.41 - * Version 2 license, then the option applies only if the new code is
   91.42 - * made subject to such option by the copyright holder.
   91.43 - */
   91.44 -package org.openide.util;
   91.45 -
   91.46 -import java.util.*;
   91.47 -
   91.48 -
   91.49 -/** An event describing the change in the lookup's result.
   91.50 - *
   91.51 - * @author  Jaroslav Tulach
   91.52 - */
   91.53 -public final class LookupEvent extends EventObject {
   91.54 -    /** Create a new lookup event.
   91.55 -     * @param source the lookup result which has changed
   91.56 -     */
   91.57 -    public LookupEvent(Lookup.Result source) {
   91.58 -        super(source);
   91.59 -    }
   91.60 -}
    92.1 --- a/openide.util/src/org/openide/util/LookupListener.java	Thu Dec 10 19:23:25 2009 -0500
    92.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.3 @@ -1,59 +0,0 @@
    92.4 -/*
    92.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    92.6 - *
    92.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    92.8 - *
    92.9 - * The contents of this file are subject to the terms of either the GNU
   92.10 - * General Public License Version 2 only ("GPL") or the Common
   92.11 - * Development and Distribution License("CDDL") (collectively, the
   92.12 - * "License"). You may not use this file except in compliance with the
   92.13 - * License. You can obtain a copy of the License at
   92.14 - * http://www.netbeans.org/cddl-gplv2.html
   92.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   92.16 - * specific language governing permissions and limitations under the
   92.17 - * License.  When distributing the software, include this License Header
   92.18 - * Notice in each file and include the License file at
   92.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   92.20 - * particular file as subject to the "Classpath" exception as provided
   92.21 - * by Sun in the GPL Version 2 section of the License file that
   92.22 - * accompanied this code. If applicable, add the following below the
   92.23 - * License Header, with the fields enclosed by brackets [] replaced by
   92.24 - * your own identifying information:
   92.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   92.26 - *
   92.27 - * Contributor(s):
   92.28 - *
   92.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   92.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   92.31 - * Microsystems, Inc. All Rights Reserved.
   92.32 - *
   92.33 - * If you wish your version of this file to be governed by only the CDDL
   92.34 - * or only the GPL Version 2, indicate your decision by adding
   92.35 - * "[Contributor] elects to include this software in this distribution
   92.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   92.37 - * single choice of license, a recipient has the option to distribute
   92.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   92.39 - * to extend the choice of license to its licensees as provided above.
   92.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   92.41 - * Version 2 license, then the option applies only if the new code is
   92.42 - * made subject to such option by the copyright holder.
   92.43 - */
   92.44 -package org.openide.util;
   92.45 -
   92.46 -import java.util.*;
   92.47 -
   92.48 -
   92.49 -/** General listener for changes in lookup.
   92.50 - *
   92.51 - * @author  Jaroslav Tulach
   92.52 - */
   92.53 -public interface LookupListener extends EventListener {
   92.54 -    /** A change in lookup occured. Please note that this method
   92.55 -     * should never block since it might be called from lookup implementation
   92.56 -     * internal threads. If you block here you are in risk that the thread
   92.57 -     * you wait for might in turn to wait for the lookup internal thread to
   92.58 -     * finish its work.
   92.59 -     * @param ev event describing the change
   92.60 -     */
   92.61 -    public void resultChanged(LookupEvent ev);
   92.62 -}
    93.1 --- a/openide.util/src/org/openide/util/doc-files/api.html	Thu Dec 10 19:23:25 2009 -0500
    93.2 +++ b/openide.util/src/org/openide/util/doc-files/api.html	Mon Dec 14 20:58:39 2009 +0100
    93.3 @@ -58,8 +58,8 @@
    93.4  <h2>Package <a href="../package-summary.html"><code>org.openide.util</code></a></h2>
    93.5  
    93.6  <ol>
    93.7 -    <li><a href="../Lookup.html">Lookup</a> and its associated
    93.8 -    <a href="../lookup/package-summary.html">support package</a> as that
    93.9 +    <li><a href="@org-openide-util-lookup@/org/openide/util/Lookup.html">Lookup</a> and its associated
   93.10 +    <a href="@org-openide-util-lookup@/org/openide/util/lookup/package-summary.html">support package</a> as that
   93.11      is the <em>adaptable</em> interface that objects can provide if
   93.12      they wish to offer dynamic capabilities.
   93.13      </li>
   93.14 @@ -114,11 +114,11 @@
   93.15  
   93.16  <p>For lookup, this centers around
   93.17  
   93.18 -<a href="../Lookup.html"><code>Lookup</code></a>
   93.19 +<a href="@org-openide-util-lookup@/org/openide/util/Lookup.html"><code>Lookup</code></a>
   93.20  
   93.21  and helper implementations in
   93.22  
   93.23 -<a href="../lookup/package-summary.html"><code>org.openide.util.lookup</code></a>.
   93.24 +<a href="@org-openide-util-lookup@/org/openide/util/lookup/package-summary.html"><code>org.openide.util.lookup</code></a>.
   93.25  
   93.26  
   93.27  
   93.28 @@ -447,7 +447,7 @@
   93.29  
   93.30  The client side of the lookup system centers around one class,
   93.31  
   93.32 -<a href="../Lookup.html"><code>Lookup</code></a>.
   93.33 +<a href="@org-openide-util-lookup@/org/openide/util/Lookup.html"><code>Lookup</code></a>.
   93.34  
   93.35  In the simplest usage, all that is needed is to get some single
   93.36  instance of a given class (or subclass). For example, if some kind of
   93.37 @@ -456,7 +456,7 @@
   93.38  may simply use:
   93.39  
   93.40  <pre>
   93.41 -<font class="type">MyService</font> <font class="variable-name">impl</font> = (<font class="type">MyService</font>)Lookup.getDefault().<a href="../Lookup.html#lookup(java.lang.Class)">lookup</a>(MyService.<font class="keyword">class</font>);
   93.42 +<font class="type">MyService</font> <font class="variable-name">impl</font> = (<font class="type">MyService</font>)Lookup.getDefault().<a href="@org-openide-util-lookup@/org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(MyService.<font class="keyword">class</font>);
   93.43  <font class="keyword">if</font> (impl == <font class="constant">null</font>) <font class="comment">/* nothing registered */</font> ...
   93.44  impl.useIt();
   93.45  </pre>
   93.46 @@ -558,12 +558,12 @@
   93.47  general method:
   93.48  
   93.49  <pre>
   93.50 -<font class="type"><a href="../Lookup.Template.html">Lookup.Template</a></font> <font class="variable-name">templ</font> = <font class="keyword">new</font> <font class="type">Lookup.Template</font>(MyService.<font class="keyword">class</font>);
   93.51 -<font class="keyword">final</font> <font class="type"><a href="../Lookup.Result.html">Lookup.Result</a></font> <font class="variable-name">result</font> = Lookup.getDefault().lookup(templ);
   93.52 +<font class="type"><a href="@org-openide-util-lookup@/org/openide/util/Lookup.Template.html">Lookup.Template</a></font> <font class="variable-name">templ</font> = <font class="keyword">new</font> <font class="type">Lookup.Template</font>(MyService.<font class="keyword">class</font>);
   93.53 +<font class="keyword">final</font> <font class="type"><a href="@org-openide-util-lookup@/org/openide/util/Lookup.Result.html">Lookup.Result</a></font> <font class="variable-name">result</font> = Lookup.getDefault().lookup(templ);
   93.54  <font class="type">Collection</font> <font class="variable-name">impls</font> = result.allInstances(); <font class="comment">// Collection&lt;MyService&gt;
   93.55  // use Java Collections API to get iterator, ...
   93.56  // Pay attention to subsequent changes in the result.
   93.57 -</font>result.addLookupListener(<font class="keyword">new</font> <font class="type"><a href="../LookupListener.html">LookupListener</a></font>() {
   93.58 +</font>result.addLookupListener(<font class="keyword">new</font> <font class="type"><a href="@org-openide-util-lookup@/org/openide/util/LookupListener.html">LookupListener</a></font>() {
   93.59      <font class="keyword">public</font> <font class="type">void</font> <font class="function-name">resultChanged</font>(<font class="type">LookupEvent</font> <font class="variable-name">ev</font>) {
   93.60          <font class="comment">// Now it is different.
   93.61  </font>        <font class="type">Collection</font> <font class="variable-name">impls2</font> = result.allInstances();
   93.62 @@ -611,7 +611,7 @@
   93.63  <font class="type">Lookup.Result</font> <font class="variable-name">result</font> = Lookup.getDefault().lookup(templ);
   93.64  <font class="type">Iterator</font> <font class="variable-name">it</font> = result.allItems().iterator();
   93.65  <font class="keyword">while</font> (it.hasNext()) {
   93.66 -    <font class="type"><a href="../Lookup.Item.html">Lookup.Item</a></font> <font class="variable-name">item</font> = (<font class="type">Lookup.Item</font>)it.next();
   93.67 +    <font class="type"><a href="@org-openide-util-lookup@/org/openide/util/Lookup.Item.html">Lookup.Item</a></font> <font class="variable-name">item</font> = (<font class="type">Lookup.Item</font>)it.next();
   93.68      <font class="type">String</font> <font class="variable-name">displayName</font> = item.getDisplayName();
   93.69      <font class="keyword">if</font> (<font class="comment">/* user accepts displayName as the right one */</font>) {
   93.70          <font class="type">MyService</font> <font class="variable-name">instance</font> = (<font class="type">MyService</font>)item.getInstance();
   93.71 @@ -623,7 +623,7 @@
   93.72  }
   93.73  <font class="comment">// later...
   93.74  </font><font class="type">String</font> <font class="variable-name">storedID</font> = someSettings.getChosenService();
   93.75 -<font class="type">Lookup.Template</font> <font class="variable-name">templ</font> = <font class="keyword">new</font> <font class="type"><a href="../Lookup.Template.html#Lookup.Template(java.lang.Class,java.lang.String,java.lang.Object)">Lookup.Template</a></font>(MyService.<font class="keyword">class</font>, storedID, <font class="constant">null</font>);
   93.76 +<font class="type">Lookup.Template</font> <font class="variable-name">templ</font> = <font class="keyword">new</font> <font class="type"><a href="@org-openide-util-lookup@/org/openide/util/Lookup.Template.html#Lookup.Template(java.lang.Class,java.lang.String,java.lang.Object)">Lookup.Template</a></font>(MyService.<font class="keyword">class</font>, storedID, <font class="constant">null</font>);
   93.77  <font class="type">Iterator</font> <font class="variable-name">it</font> = Lookup.getDefault().lookup(templ).allInstances().iterator();
   93.78  <font class="keyword">if</font> (! it.hasNext()) <font class="comment">/* failed to find it... */</font>
   93.79  <font class="type">MyService</font> <font class="variable-name">instance</font> = (<font class="type">MyService</font>)it.next();
   93.80 @@ -661,7 +661,7 @@
   93.81  <p>The simplest way to create a fresh lookup is to base it on other
   93.82  existing ones.
   93.83  
   93.84 -<a href="../lookup/ProxyLookup.html"><code>ProxyLookup</code></a>
   93.85 +<a href="@org-openide-util-lookup@/org/openide/util/lookup/ProxyLookup.html"><code>ProxyLookup</code></a>
   93.86  
   93.87  accepts a list of other lookup implementations (in the constructor and
   93.88  also changeable later). The results it provides are constructed by
   93.89 @@ -673,7 +673,7 @@
   93.90  If you want to use the common mechanism of finding instances in
   93.91  folders (or subfolders) and serving these as the results,
   93.92  
   93.93 -<a href="../lookup/Lookups.html#forPath(java.lang.String)">Lookups.forPath(String)</a>
   93.94 +<a href="@org-openide-util-lookup@/org/openide/util/lookup/Lookups.html#forPath(java.lang.String)">Lookups.forPath(String)</a>
   93.95  
   93.96  makes this possible: you need only provide a name of a folder to look in, and
   93.97  use
   93.98 @@ -723,7 +723,7 @@
   93.99  <p>The most powerful way to provide a lookup is to directly define
  93.100  what instances and items it should provide, by subclassing. For this,
  93.101  
  93.102 -<a href="../lookup/AbstractLookup.html"><code>AbstractLookup</code></a>
  93.103 +<a href="@org-openide-util-lookup@/org/openide/util/lookup/AbstractLookup.html"><code>AbstractLookup</code></a>
  93.104  
  93.105  is recommended as it is easiest to use.
  93.106  
  93.107 @@ -731,18 +731,18 @@
  93.108  public constructor (in which case you need not subclass it). Here you
  93.109  provide an
  93.110  
  93.111 -<a href="../lookup/AbstractLookup.Content.html"><code>AbstractLookup.Content</code></a>
  93.112 +<a href="@org-openide-util-lookup@/org/openide/util/lookup/AbstractLookup.Content.html"><code>AbstractLookup.Content</code></a>
  93.113  
  93.114  object which you have created and hold on to privately, and which
  93.115  keeps track of instances and permits them to be registered and
  93.116  deregistered. Often
  93.117  
  93.118 -<a href="../lookup/InstanceContent.html"><code>InstanceContent</code></a>
  93.119 +<a href="@org-openide-util-lookup@/org/openide/util/lookup/InstanceContent.html"><code>InstanceContent</code></a>
  93.120  
  93.121  is used as the content implementation. To add something to the lookup,
  93.122  simply use
  93.123  
  93.124 -<a href="../lookup/InstanceContent.html#add(java.lang.Object)"><code>add(Object)</code></a>
  93.125 +<a href="@org-openide-util-lookup@/org/openide/util/lookup/InstanceContent.html#add(java.lang.Object)"><code>add(Object)</code></a>
  93.126  
  93.127  (and <code>remove(Object)</code> for the reverse). These may be called
  93.128  at any time and will update the set of registered instances (firing
  93.129 @@ -752,7 +752,7 @@
  93.130  lookup, but there is some cheap "key" which can easily generate it,
  93.131  you may instead register the key by passing in an
  93.132  
  93.133 -<a href="../lookup/InstanceContent.Convertor.html"><code>InstanceContent.Convertor</code></a>.
  93.134 +<a href="@org-openide-util-lookup@/org/openide/util/lookup/InstanceContent.Convertor.html"><code>InstanceContent.Convertor</code></a>.
  93.135  
  93.136  This convertor translates the key to the real instance that the lookup
  93.137  client sees, if and when needed. For example, if you have a long list
    94.1 --- a/openide.util/src/org/openide/util/lookup/ALPairComparator.java	Thu Dec 10 19:23:25 2009 -0500
    94.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.3 @@ -1,88 +0,0 @@
    94.4 -/*
    94.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    94.6 - *
    94.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    94.8 - *
    94.9 - * The contents of this file are subject to the terms of either the GNU
   94.10 - * General Public License Version 2 only ("GPL") or the Common
   94.11 - * Development and Distribution License("CDDL") (collectively, the
   94.12 - * "License"). You may not use this file except in compliance with the
   94.13 - * License. You can obtain a copy of the License at
   94.14 - * http://www.netbeans.org/cddl-gplv2.html
   94.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   94.16 - * specific language governing permissions and limitations under the
   94.17 - * License.  When distributing the software, include this License Header
   94.18 - * Notice in each file and include the License file at
   94.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   94.20 - * particular file as subject to the "Classpath" exception as provided
   94.21 - * by Sun in the GPL Version 2 section of the License file that
   94.22 - * accompanied this code. If applicable, add the following below the
   94.23 - * License Header, with the fields enclosed by brackets [] replaced by
   94.24 - * your own identifying information:
   94.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   94.26 - *
   94.27 - * Contributor(s):
   94.28 - *
   94.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   94.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   94.31 - * Microsystems, Inc. All Rights Reserved.
   94.32 - *
   94.33 - * If you wish your version of this file to be governed by only the CDDL
   94.34 - * or only the GPL Version 2, indicate your decision by adding
   94.35 - * "[Contributor] elects to include this software in this distribution
   94.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   94.37 - * single choice of license, a recipient has the option to distribute
   94.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   94.39 - * to extend the choice of license to its licensees as provided above.
   94.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   94.41 - * Version 2 license, then the option applies only if the new code is
   94.42 - * made subject to such option by the copyright holder.
   94.43 - */
   94.44 -package org.openide.util.lookup;
   94.45 -
   94.46 -import java.util.Comparator;
   94.47 -import org.openide.util.lookup.AbstractLookup.Pair;
   94.48 -
   94.49 -
   94.50 -/** Implementation of comparator for AbstractLookup.Pair
   94.51 - *
   94.52 - * @author  Jaroslav Tulach
   94.53 - */
   94.54 -final class ALPairComparator implements Comparator<Pair<?>> {
   94.55 -    public static final Comparator<Pair<?>> DEFAULT = new ALPairComparator();
   94.56 -
   94.57 -    /** Creates a new instance of ALPairComparator */
   94.58 -    private ALPairComparator() {
   94.59 -    }
   94.60 -
   94.61 -    /** Compares two items.
   94.62 -    */
   94.63 -    public int compare(Pair<?> i1, Pair<?> i2) {
   94.64 -        int result = i1.getIndex() - i2.getIndex();
   94.65 -
   94.66 -        if (result == 0) {
   94.67 -            if (i1 != i2) {
   94.68 -                java.io.ByteArrayOutputStream bs = new java.io.ByteArrayOutputStream();
   94.69 -                java.io.PrintStream ps = new java.io.PrintStream(bs);
   94.70 -
   94.71 -                ps.println(
   94.72 -                    "Duplicate pair in tree" + // NOI18N
   94.73 -                    "Pair1: " + i1 + " pair2: " + i2 + " index1: " + i1.getIndex() + " index2: " +
   94.74 -                    i2.getIndex() // NOI18N
   94.75 -                     +" item1: " + i1.getInstance() + " item2: " + i2.getInstance() // NOI18N
   94.76 -                     +" id1: " + Integer.toHexString(System.identityHashCode(i1)) // NOI18N
   94.77 -                     +" id2: " + Integer.toHexString(System.identityHashCode(i2)) // NOI18N
   94.78 -                );
   94.79 -
   94.80 -                //                print (ps, false);
   94.81 -                ps.close();
   94.82 -
   94.83 -                throw new IllegalStateException(bs.toString());
   94.84 -            }
   94.85 -
   94.86 -            return 0;
   94.87 -        }
   94.88 -
   94.89 -        return result;
   94.90 -    }
   94.91 -}
    95.1 --- a/openide.util/src/org/openide/util/lookup/AbstractLookup.java	Thu Dec 10 19:23:25 2009 -0500
    95.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.3 @@ -1,1467 +0,0 @@
    95.4 -/*
    95.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    95.6 - *
    95.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    95.8 - *
    95.9 - * The contents of this file are subject to the terms of either the GNU
   95.10 - * General Public License Version 2 only ("GPL") or the Common
   95.11 - * Development and Distribution License("CDDL") (collectively, the
   95.12 - * "License"). You may not use this file except in compliance with the
   95.13 - * License. You can obtain a copy of the License at
   95.14 - * http://www.netbeans.org/cddl-gplv2.html
   95.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   95.16 - * specific language governing permissions and limitations under the
   95.17 - * License.  When distributing the software, include this License Header
   95.18 - * Notice in each file and include the License file at
   95.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   95.20 - * particular file as subject to the "Classpath" exception as provided
   95.21 - * by Sun in the GPL Version 2 section of the License file that
   95.22 - * accompanied this code. If applicable, add the following below the
   95.23 - * License Header, with the fields enclosed by brackets [] replaced by
   95.24 - * your own identifying information:
   95.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   95.26 - *
   95.27 - * Contributor(s):
   95.28 - *
   95.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   95.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   95.31 - * Microsystems, Inc. All Rights Reserved.
   95.32 - *
   95.33 - * If you wish your version of this file to be governed by only the CDDL
   95.34 - * or only the GPL Version 2, indicate your decision by adding
   95.35 - * "[Contributor] elects to include this software in this distribution
   95.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   95.37 - * single choice of license, a recipient has the option to distribute
   95.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   95.39 - * to extend the choice of license to its licensees as provided above.
   95.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   95.41 - * Version 2 license, then the option applies only if the new code is
   95.42 - * made subject to such option by the copyright holder.
   95.43 - */
   95.44 -package org.openide.util.lookup;
   95.45 -
   95.46 -import java.io.PrintStream;
   95.47 -import org.openide.util.Lookup;
   95.48 -import org.openide.util.LookupEvent;
   95.49 -import org.openide.util.LookupListener;
   95.50 -
   95.51 -import java.io.IOException;
   95.52 -import java.io.ObjectOutputStream;
   95.53 -import java.io.Serializable;
   95.54 -
   95.55 -import java.lang.ref.ReferenceQueue;
   95.56 -import java.lang.ref.WeakReference;
   95.57 -import java.util.ArrayList;
   95.58 -import java.util.Arrays;
   95.59 -import java.util.Collection;
   95.60 -import java.util.Collections;
   95.61 -import java.util.Enumeration;
   95.62 -import java.util.HashMap;
   95.63 -import java.util.HashSet;
   95.64 -import java.util.Iterator;
   95.65 -import java.util.LinkedHashSet;
   95.66 -import java.util.Map;
   95.67 -import java.util.Set;
   95.68 -import java.util.TreeSet;
   95.69 -
   95.70 -import java.util.concurrent.Executor;
   95.71 -import org.netbeans.modules.openide.util.ActiveQueue;
   95.72 -
   95.73 -
   95.74 -/** Implementation of the lookup from OpenAPIs that is based on the
   95.75 - * introduction of Item. This class should provide the default way
   95.76 - * of how to store (Class, Object) pairs in the lookups. It offers
   95.77 - * protected methods for subclasses to register the pairs.
   95.78 - * <p>Serializable since 3.27.
   95.79 - * @author  Jaroslav Tulach
   95.80 - * @since 1.9
   95.81 - */
   95.82 -public class AbstractLookup extends Lookup implements Serializable {
   95.83 -    static final long serialVersionUID = 5L;
   95.84 -
   95.85 -    /** lock for initialization of the maps of lookups */
   95.86 -    private static final Object treeLock = new Object();
   95.87 -
   95.88 -    /** the tree that registers all items (or Integer as a treshold size) */
   95.89 -    private Object tree;
   95.90 -
   95.91 -    /** count of items in to lookup */
   95.92 -    private int count;
   95.93 -
   95.94 -    /** Constructor to create this lookup and associate it with given
   95.95 -     * Content. The content than allows the creator to invoke protected
   95.96 -     * methods which are not accessible for any other user of the lookup.
   95.97 -     *
   95.98 -     * @param content the content to assciate with
   95.99 -     *
  95.100 -     * @since 1.25
  95.101 -     */
  95.102 -    public AbstractLookup(Content content) {
  95.103 -        content.attach(this);
  95.104 -    }
  95.105 -
  95.106 -    /** Constructor for testing purposes that allows specification of storage
  95.107 -     * as mechanism as well.
  95.108 -     */
  95.109 -    AbstractLookup(Content content, Storage<?> storage) {
  95.110 -        this(content);
  95.111 -        this.tree = storage;
  95.112 -        initialize();
  95.113 -    }
  95.114 -
  95.115 -    /** Constructor for testing purposes that allows specification of storage
  95.116 -     * as mechanism as well.
  95.117 -     * @param trashhold number of Pair to "remain small"
  95.118 -     */
  95.119 -    AbstractLookup(Content content, Integer trashhold) {
  95.120 -        this(content);
  95.121 -        this.tree = trashhold;
  95.122 -    }
  95.123 -
  95.124 -    /** Default constructor for subclasses that do not need to provide a content
  95.125 -     */
  95.126 -    protected AbstractLookup() {
  95.127 -    }
  95.128 -
  95.129 -    @Override
  95.130 -    public String toString() {
  95.131 -        if (tree instanceof Storage) {
  95.132 -            return "AbstractLookup" + lookup(new Lookup.Template<Object>(Object.class)).allItems(); // NOI18N
  95.133 -        } else {
  95.134 -            return super.toString();
  95.135 -        }
  95.136 -    }
  95.137 -
  95.138 -    /** Entres the storage management system.
  95.139 -     */
  95.140 -    @SuppressWarnings("unchecked")
  95.141 -    private <T> AbstractLookup.Storage<T> enterStorage() {
  95.142 -        for (;;) {
  95.143 -            synchronized (treeLock) {
  95.144 -                if (tree instanceof AbstractLookup.Storage) {
  95.145 -                    if (tree instanceof DelegatingStorage) {
  95.146 -                        // somebody is using the lookup right now
  95.147 -                        DelegatingStorage del = (DelegatingStorage) tree;
  95.148 -
  95.149 -                        // check whether there is not access from the same 
  95.150 -                        // thread (can throw exception)
  95.151 -                        del.checkForTreeModification();
  95.152 -
  95.153 -                        try {
  95.154 -                            treeLock.wait();
  95.155 -                        } catch (InterruptedException ex) {
  95.156 -                            // ignore and go on
  95.157 -                        }
  95.158 -
  95.159 -                        continue;
  95.160 -                    } else {
  95.161 -                        // ok, tree is initialized and nobody is using it yet
  95.162 -                        tree = new DelegatingStorage((Storage<T>) tree);
  95.163 -
  95.164 -                        return (Storage<T>) tree;
  95.165 -                    }
  95.166 -                }
  95.167 -
  95.168 -                // first time initialization of the tree
  95.169 -                if (tree instanceof Integer) {
  95.170 -                    tree = new ArrayStorage((Integer) tree);
  95.171 -                } else {
  95.172 -                    tree = new ArrayStorage();
  95.173 -                }
  95.174 -            }
  95.175 -
  95.176 -            // the tree has not yet been initilized, initialize and go on again
  95.177 -            initialize();
  95.178 -        }
  95.179 -    }
  95.180 -
  95.181 -    /** Exists tree ownership.
  95.182 -     */
  95.183 -    private AbstractLookup.Storage exitStorage() {
  95.184 -        synchronized (treeLock) {
  95.185 -            AbstractLookup.Storage stor = ((DelegatingStorage) tree).exitDelegate();
  95.186 -            tree = stor;
  95.187 -            treeLock.notifyAll();
  95.188 -
  95.189 -            return stor;
  95.190 -        }
  95.191 -    }
  95.192 -
  95.193 -    /** Method for subclasses to initialize them selves.
  95.194 -     */
  95.195 -    protected void initialize() {
  95.196 -    }
  95.197 -
  95.198 -    /** Notifies subclasses that a query is about to be processed.
  95.199 -     * @param template the template
  95.200 -     */
  95.201 -    protected void beforeLookup(Template<?> template) {
  95.202 -    }
  95.203 -
  95.204 -    /** The method to add instance to the lookup with.
  95.205 -     * @param pair class/instance pair
  95.206 -     */
  95.207 -    protected final void addPair(Pair<?> pair) {
  95.208 -        addPairImpl(pair, null);
  95.209 -    }
  95.210 -
  95.211 -    /** The method to add instance to the lookup with.
  95.212 -     * @param pair class/instance pair
  95.213 -     * @param notifyIn the executor that will handle the notification of events
  95.214 -     * @since 7.16
  95.215 -     */
  95.216 -    protected final void addPair(Pair<?> pair, Executor notifyIn) {
  95.217 -        addPairImpl(pair, notifyIn);
  95.218 -    }
  95.219 -
  95.220 -    private final <Transaction> void addPairImpl(Pair<?> pair, Executor notifyIn) {
  95.221 -        HashSet<R> toNotify = new HashSet<R>();
  95.222 -
  95.223 -        AbstractLookup.Storage<Transaction> t = enterStorage();
  95.224 -        Transaction transaction = null;
  95.225 -
  95.226 -        try {
  95.227 -            transaction = t.beginTransaction(-2);
  95.228 -
  95.229 -            if (t.add(pair, transaction)) {
  95.230 -                try {
  95.231 -                    pair.setIndex(t, count++);
  95.232 -                } catch (IllegalStateException ex) {
  95.233 -                    // remove the pair
  95.234 -                    t.remove(pair, transaction);
  95.235 -
  95.236 -                    // rethrow the exception
  95.237 -                    throw ex;
  95.238 -                }
  95.239 -
  95.240 -                // if the pair is newly added and was not there before
  95.241 -                t.endTransaction(transaction, toNotify);
  95.242 -            } else {
  95.243 -                // just finish the process by calling endTransaction
  95.244 -                t.endTransaction(transaction, new HashSet<R>());
  95.245 -            }
  95.246 -        } finally {
  95.247 -            exitStorage();
  95.248 -        }
  95.249 -
  95.250 -        notifyIn(notifyIn, toNotify);
  95.251 -    }
  95.252 -
  95.253 -    /** Remove instance.
  95.254 -     * @param pair class/instance pair
  95.255 -     */
  95.256 -    protected final void removePair(Pair<?> pair) {
  95.257 -        removePairImpl(pair, null);
  95.258 -    }
  95.259 -    /** Remove instance.
  95.260 -     * @param pair class/instance pair
  95.261 -     * @param notifyIn the executor that will handle the notification of events
  95.262 -     * @since 7.16
  95.263 -     */
  95.264 -    protected final void removePair(Pair<?> pair, Executor notifyIn) {
  95.265 -        removePairImpl(pair, notifyIn);
  95.266 -    }
  95.267 -
  95.268 -    private <Transaction> void removePairImpl(Pair<?> pair, Executor notifyIn) {
  95.269 -        HashSet<R> toNotify = new HashSet<R>();
  95.270 -
  95.271 -        AbstractLookup.Storage<Transaction> t = enterStorage();
  95.272 -        Transaction transaction = null;
  95.273 -
  95.274 -        try {
  95.275 -            transaction = t.beginTransaction(-1);
  95.276 -            t.remove(pair, transaction);
  95.277 -            t.endTransaction(transaction, toNotify);
  95.278 -        } finally {
  95.279 -            exitStorage();
  95.280 -        }
  95.281 -
  95.282 -        notifyIn(notifyIn, toNotify);
  95.283 -    }
  95.284 -
  95.285 -    /** Changes all pairs in the lookup to new values.
  95.286 -     * @param collection the collection of (Pair) objects
  95.287 -     */
  95.288 -    protected final void setPairs(Collection<? extends Pair> collection) {
  95.289 -        setPairs(collection, null);
  95.290 -    }
  95.291 -
  95.292 -    /** Changes all pairs in the lookup to new values, notifies listeners
  95.293 -     * using provided executor.
  95.294 -     * 
  95.295 -     * @param collection the collection of (Pair) objects
  95.296 -     * @param notifyIn the executor that will handle the notification of events
  95.297 -     * @since 7.16
  95.298 -     */
  95.299 -    protected final void setPairs(Collection<? extends Pair> collection, Executor notifyIn) {
  95.300 -        HashSet<R> listeners = setPairsAndCollectListeners(collection);
  95.301 -        notifyIn(notifyIn, listeners);
  95.302 -    }
  95.303 -    
  95.304 -    private final void notifyIn(Executor notifyIn, final HashSet<R> listeners) {
  95.305 -        NotifyListeners notify = new NotifyListeners(listeners);
  95.306 -        if (notify.shallRun()) {
  95.307 -            if (notifyIn == null) {
  95.308 -                notify.run();
  95.309 -            } else {
  95.310 -                notifyIn.execute(notify);
  95.311 -            }
  95.312 -        }
  95.313 -    }
  95.314 -    
  95.315 -    /** Getter for set of pairs. Package private contract with MetaInfServicesLookup.
  95.316 -     * @return a LinkedHashSet that can be modified
  95.317 -     */
  95.318 -    final LinkedHashSet<Pair<?>> getPairsAsLHS() {
  95.319 -        AbstractLookup.Storage<?> t = enterStorage();
  95.320 -
  95.321 -        try {
  95.322 -            Enumeration<Pair<Object>> en = t.lookup(Object.class);
  95.323 -            TreeSet<Pair<?>> arr = new TreeSet<Pair<?>>(ALPairComparator.DEFAULT);
  95.324 -            while (en.hasMoreElements()) {
  95.325 -                Pair<Object> item = en.nextElement();
  95.326 -                arr.add(item);
  95.327 -            }
  95.328 -            return new LinkedHashSet<Pair<?>>(arr);
  95.329 -        } finally {
  95.330 -            exitStorage();
  95.331 -        }
  95.332 -    }
  95.333 -
  95.334 -    /** Collects listeners without notification. Needed in MetaInfServicesLookup
  95.335 -     * right now, but maybe will become an API later.
  95.336 -     */
  95.337 -    final <Transaction> HashSet<R> setPairsAndCollectListeners(Collection<? extends Pair> collection) {
  95.338 -        HashSet<R> toNotify = new HashSet<R>(27);
  95.339 -
  95.340 -        AbstractLookup.Storage<Transaction> t = enterStorage();
  95.341 -        Transaction transaction = null;
  95.342 -
  95.343 -        try {
  95.344 -            // map between the Items and their indexes (Integer)
  95.345 -            HashMap<Item<?>,Info> shouldBeThere = new HashMap<Item<?>,Info>(collection.size() * 2);
  95.346 -
  95.347 -            count = 0;
  95.348 -
  95.349 -            Iterator it = collection.iterator();
  95.350 -            transaction = t.beginTransaction(collection.size());
  95.351 -
  95.352 -            while (it.hasNext()) {
  95.353 -                Pair item = (Pair) it.next();
  95.354 -
  95.355 -                if (t.add(item, transaction)) {
  95.356 -                    // the item has not been there yet
  95.357 -                    //t.endTransaction(transaction, toNotify);
  95.358 -                }
  95.359 -
  95.360 -                // remeber the item, because it should not be removed
  95.361 -                shouldBeThere.put(item, new Info(count++, transaction));
  95.362 -
  95.363 -                //                    arr.clear ();
  95.364 -            }
  95.365 -
  95.366 -            //            Object transaction = t.beginTransaction ();
  95.367 -            // deletes all objects that should not be there and
  95.368 -            t.retainAll(shouldBeThere, transaction);
  95.369 -
  95.370 -            // collect listeners
  95.371 -            t.endTransaction(transaction, toNotify);
  95.372 -
  95.373 -            /*
  95.374 -            // check consistency
  95.375 -            Enumeration en = t.lookup (java.lang.Object.class);
  95.376 -            boolean[] max = new boolean[count];
  95.377 -            int mistake = -1;
  95.378 -            while (en.hasMoreElements ()) {
  95.379 -                Pair item = (Pair)en.nextElement ();
  95.380 -
  95.381 -                if (max[item.index]) {
  95.382 -                    mistake = item.index;
  95.383 -                }
  95.384 -                max[item.index] = true;
  95.385 -            }
  95.386 -
  95.387 -            if (mistake != -1) {
  95.388 -                System.err.println ("Mistake at: " + mistake);
  95.389 -                tree.print (System.err, true);
  95.390 -            }
  95.391 -            */
  95.392 -        } finally {
  95.393 -            exitStorage();
  95.394 -        }
  95.395 -
  95.396 -        return toNotify;
  95.397 -    }
  95.398 -
  95.399 -    private final void writeObject(ObjectOutputStream oos)
  95.400 -    throws IOException {
  95.401 -        AbstractLookup.Storage s = enterStorage();
  95.402 -
  95.403 -        try {
  95.404 -            // #36830: Serializing only InheritanceTree no ArrayStorage
  95.405 -            s.beginTransaction(Integer.MAX_VALUE);
  95.406 -
  95.407 -            // #32040: don't write half-made changes
  95.408 -            oos.defaultWriteObject();
  95.409 -        } finally {
  95.410 -            exitStorage();
  95.411 -        }
  95.412 -    }
  95.413 -
  95.414 -    public final <T> T lookup(Class<T> clazz) {
  95.415 -        Lookup.Item<T> item = lookupItem(new Lookup.Template<T>(clazz));
  95.416 -        return (item == null) ? null : item.getInstance();
  95.417 -    }
  95.418 -
  95.419 -    @Override
  95.420 -    public final <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
  95.421 -        AbstractLookup.this.beforeLookup(template);
  95.422 -
  95.423 -        ArrayList<Pair<T>> list = null;
  95.424 -        AbstractLookup.Storage<?> t = enterStorage();
  95.425 -
  95.426 -        try {
  95.427 -            Enumeration<Pair<T>> en;
  95.428 -
  95.429 -            try {
  95.430 -                en = t.lookup(template.getType());
  95.431 -
  95.432 -                return findSmallest(en, template, false);
  95.433 -            } catch (AbstractLookup.ISE ex) {
  95.434 -                // not possible to enumerate the exception, ok, copy it 
  95.435 -                // to create new
  95.436 -                list = new ArrayList<Pair<T>>();
  95.437 -                en = t.lookup(null); // this should get all the items without any checks
  95.438 -
  95.439 -                // the checks will be done out side of the storage
  95.440 -                while (en.hasMoreElements()) {
  95.441 -                    list.add(en.nextElement());
  95.442 -                }
  95.443 -            }
  95.444 -        } finally {
  95.445 -            exitStorage();
  95.446 -        }
  95.447 -
  95.448 -        return findSmallest(Collections.enumeration(list), template, true);
  95.449 -    }
  95.450 -
  95.451 -    private static <T> Pair<T> findSmallest(Enumeration<Pair<T>> en, Lookup.Template<T> template, boolean deepCheck) {
  95.452 -        int smallest = InheritanceTree.unsorted(en) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
  95.453 -        Pair<T> res = null;
  95.454 -
  95.455 -        while (en.hasMoreElements()) {
  95.456 -            Pair<T> item = en.nextElement();
  95.457 -
  95.458 -            if (matches(template, item, deepCheck)) {
  95.459 -                if (smallest == Integer.MIN_VALUE) {
  95.460 -                    // ok, sorted enumeration the first that matches is fine
  95.461 -                    return item;
  95.462 -                } else {
  95.463 -                    // check for the smallest item
  95.464 -                    if (smallest > item.getIndex()) {
  95.465 -                        smallest = item.getIndex();
  95.466 -                        res = item;
  95.467 -                    }
  95.468 -                }
  95.469 -            }
  95.470 -        }
  95.471 -
  95.472 -        return res;
  95.473 -    }
  95.474 -
  95.475 -    public final <T> Lookup.Result<T> lookup(Lookup.Template<T> template) {
  95.476 -        for (;;) {
  95.477 -            AbstractLookup.ISE toRun = null;
  95.478 -
  95.479 -            AbstractLookup.Storage<?> t = enterStorage();
  95.480 -
  95.481 -            try {
  95.482 -                R<T> r = new R<T>();
  95.483 -                ReferenceToResult<T> newRef = new ReferenceToResult<T>(r, this, template);
  95.484 -                newRef.next = t.registerReferenceToResult(newRef);
  95.485 -
  95.486 -                return r;
  95.487 -            } catch (AbstractLookup.ISE ex) {
  95.488 -                toRun = ex;
  95.489 -            } finally {
  95.490 -                exitStorage();
  95.491 -            }
  95.492 -
  95.493 -            toRun.recover(this);
  95.494 -
  95.495 -            // and try again
  95.496 -        }
  95.497 -    }
  95.498 -
  95.499 -    /** Notifies listeners.
  95.500 -     * @param allAffectedResults set of R
  95.501 -     */
  95.502 -    static final class NotifyListeners implements Runnable {
  95.503 -        private final ArrayList<Object> evAndListeners;
  95.504 -        
  95.505 -        public NotifyListeners(Set<R> allAffectedResults) {
  95.506 -            if (allAffectedResults.isEmpty()) {
  95.507 -                evAndListeners = null;
  95.508 -                return;
  95.509 -            }
  95.510 -
  95.511 -            evAndListeners = new ArrayList<Object>();
  95.512 -            {
  95.513 -                for (R<?> result : allAffectedResults) {
  95.514 -                    result.collectFires(evAndListeners);
  95.515 -                }
  95.516 -            }
  95.517 -        }
  95.518 -
  95.519 -        public boolean shallRun() {
  95.520 -            return evAndListeners != null && !evAndListeners.isEmpty();
  95.521 -        }
  95.522 -
  95.523 -        public void run() {
  95.524 -            Iterator it = evAndListeners.iterator();
  95.525 -            while (it.hasNext()) {
  95.526 -                LookupEvent ev = (LookupEvent)it.next();
  95.527 -                LookupListener l = (LookupListener)it.next();
  95.528 -                l.resultChanged(ev);
  95.529 -            }
  95.530 -        }
  95.531 -    }
  95.532 -
  95.533 -    /**
  95.534 -     * Call resultChanged on all listeners.
  95.535 -     * @param listeners array of listeners in the format used by
  95.536 -     *        javax.swing.EventListenerList. It means that there are Class
  95.537 -     *        objects on even positions and the listeners on odd positions
  95.538 -     * @param ev the event to fire
  95.539 -     */
  95.540 -    static void notifyListeners(Object[] listeners, LookupEvent ev, Collection<Object> evAndListeners) {
  95.541 -        for (int i = listeners.length - 1; i >= 0; i--) {
  95.542 -            if (! (listeners[i] instanceof LookupListener)) {
  95.543 -                continue;
  95.544 -            }
  95.545 -            LookupListener ll = (LookupListener)listeners[i];
  95.546 -
  95.547 -            try {
  95.548 -                if (evAndListeners != null) {
  95.549 -                    if (ll instanceof WaitableResult) {
  95.550 -                        WaitableResult<?> wr = (WaitableResult<?>)ll;
  95.551 -                        wr.collectFires(evAndListeners);
  95.552 -                    } else {
  95.553 -                        evAndListeners.add(ev);
  95.554 -                        evAndListeners.add(ll);
  95.555 -                    }
  95.556 -                } else {
  95.557 -                    ll.resultChanged(ev);
  95.558 -                }
  95.559 -            } catch (StackOverflowError err) {
  95.560 -                throw new CycleError(evAndListeners); // NOI18N
  95.561 -            } catch (RuntimeException e) {
  95.562 -                // Such as e.g. occurred in #32040. Do not halt other things.
  95.563 -                e.printStackTrace();
  95.564 -            }
  95.565 -        }
  95.566 -    }
  95.567 -
  95.568 -    private static class CycleError extends StackOverflowError {
  95.569 -        private final Collection<Object> print;
  95.570 -        public CycleError(Collection<Object> evAndListeners) {
  95.571 -            this.print = evAndListeners;
  95.572 -        }
  95.573 -
  95.574 -        @Override
  95.575 -        public String getMessage() {
  95.576 -            StringBuilder sb = new StringBuilder();
  95.577 -            sb.append("StackOverflowError, here are the listeners:\n"); // NOI18N
  95.578 -            for (Object o : print) {
  95.579 -                sb.append('\n').append(o);
  95.580 -                if (sb.length() > 10000) {
  95.581 -                    break;
  95.582 -                }
  95.583 -            }
  95.584 -            return sb.toString();
  95.585 -        }
  95.586 -    } // end of CycleError
  95.587 -
  95.588 -    /** A method that defines matching between Item and Template.
  95.589 -     * @param t template providing the criteria
  95.590 -     * @param item the item to match
  95.591 -     * @param deepCheck true if type of the pair should be tested, false if it is already has been tested
  95.592 -     * @return true if item matches the template requirements, false if not
  95.593 -     */
  95.594 -    static boolean matches(Template<?> t, Pair<?> item, boolean deepCheck) {
  95.595 -        String id = t.getId();
  95.596 -
  95.597 -        if (id != null && !id.equals(item.getId())) {
  95.598 -            return false;
  95.599 -        }
  95.600 -
  95.601 -        Object instance = t.getInstance();
  95.602 -
  95.603 -        if ((instance != null) && !item.creatorOf(instance)) {
  95.604 -            return false;
  95.605 -        }
  95.606 -
  95.607 -        if (deepCheck) {
  95.608 -            return item.instanceOf(t.getType());
  95.609 -        } else {
  95.610 -            return true;
  95.611 -        }
  95.612 -    }
  95.613 -
  95.614 -    /**
  95.615 -     * Compares the array elements for equality.
  95.616 -     * @return true if all elements in the arrays are equal
  95.617 -     *  (by calling equals(Object x) method)
  95.618 -     */
  95.619 -    private static boolean compareArrays(Object[] a, Object[] b) {
  95.620 -        // handle null values
  95.621 -        if (a == null) {
  95.622 -            return (b == null);
  95.623 -        } else {
  95.624 -            if (b == null) {
  95.625 -                return false;
  95.626 -            }
  95.627 -        }
  95.628 -
  95.629 -        if (a.length != b.length) {
  95.630 -            return false;
  95.631 -        }
  95.632 -
  95.633 -        for (int i = 0; i < a.length; i++) {
  95.634 -            // handle null values for individual elements
  95.635 -            if (a[i] == null) {
  95.636 -                if (b[i] != null) {
  95.637 -                    return false;
  95.638 -                }
  95.639 -
  95.640 -                // both are null --> ok, take next
  95.641 -                continue;
  95.642 -            } else {
  95.643 -                if (b[i] == null) {
  95.644 -                    return false;
  95.645 -                }
  95.646 -            }
  95.647 -
  95.648 -            // perform the comparison
  95.649 -            if (!a[i].equals(b[i])) {
  95.650 -                return false;
  95.651 -            }
  95.652 -        }
  95.653 -
  95.654 -        return true;
  95.655 -    }
  95.656 -
  95.657 -    /** Method to be called when a result is cleared to signal that the list
  95.658 -     * of all result should be checked for clearing.
  95.659 -     * @param template the template the result was for
  95.660 -     * @return true if the hash map with all items has been cleared
  95.661 -     */
  95.662 -    <T> boolean cleanUpResult(Lookup.Template<T> template) {
  95.663 -        AbstractLookup.Storage<?> t = enterStorage();
  95.664 -
  95.665 -        try {
  95.666 -            return t.cleanUpResult(template) == null;
  95.667 -        } finally {
  95.668 -            exitStorage();
  95.669 -        }
  95.670 -    }
  95.671 -
  95.672 -    /** Storage check for tests. */
  95.673 -    static boolean isSimple(AbstractLookup l) {
  95.674 -        return DelegatingStorage.isSimple((Storage)l.tree);
  95.675 -    }
  95.676 -
  95.677 -    /** Generic support for listeners, so it can be used in other results
  95.678 -     * as well.
  95.679 -     * @param add true to add it, false to modify
  95.680 -     * @param l listener to modify
  95.681 -     * @param ref the value of the reference to listener or listener list
  95.682 -     * @return new value to the reference to listener or list
  95.683 -     */
  95.684 -    @SuppressWarnings("unchecked")
  95.685 -    static Object modifyListenerList(boolean add, LookupListener l, Object ref) {
  95.686 -        if (add) {
  95.687 -            if (ref == null) {
  95.688 -                return l;
  95.689 -            }
  95.690 -
  95.691 -            if (ref instanceof LookupListener) {
  95.692 -                ArrayList arr = new ArrayList();
  95.693 -                arr.add(ref);
  95.694 -                ref = arr;
  95.695 -            }
  95.696 -
  95.697 -            ((ArrayList) ref).add(l);
  95.698 -
  95.699 -            return ref;
  95.700 -        } else {
  95.701 -            // remove
  95.702 -            if (ref == null) {
  95.703 -                return null;
  95.704 -            }
  95.705 -
  95.706 -            if (ref == l) {
  95.707 -                return null;
  95.708 -            }
  95.709 -
  95.710 -            ArrayList arr = (ArrayList) ref;
  95.711 -            arr.remove(l);
  95.712 -
  95.713 -            if (arr.size() == 1) {
  95.714 -                return arr.iterator().next();
  95.715 -            } else {
  95.716 -                return arr;
  95.717 -            }
  95.718 -        }
  95.719 -    }
  95.720 -
  95.721 -    private static ReferenceQueue<Object> activeQueue() {
  95.722 -        return ActiveQueue.queue();
  95.723 -    }
  95.724 -
  95.725 -    /** Storage to keep the internal structure of Pairs and to answer
  95.726 -     * different queries.
  95.727 -     */
  95.728 -    interface Storage<Transaction> {
  95.729 -        /** Initializes a modification operation by creating an object
  95.730 -         * that will be passsed to all add, remove, retainAll methods
  95.731 -         * and should collect enough information about the change to
  95.732 -         * notify listeners about the transaction later
  95.733 -         *
  95.734 -         * @param ensure the amount of items that will appear in the storage
  95.735 -         *   after the modifications (-1 == remove one, -2 == add one, >= 0
  95.736 -         *   the amount of objects at the end
  95.737 -         * @return a token to identify the transaction
  95.738 -         */
  95.739 -        public Transaction beginTransaction(int ensure);
  95.740 -
  95.741 -        /** Collects all affected results R that were modified in the
  95.742 -         * given transaction.
  95.743 -         *
  95.744 -         * @param modified place to add results R to
  95.745 -         * @param transaction the transaction indentification
  95.746 -         */
  95.747 -        public void endTransaction(Transaction transaction, Set<R> modifiedResults);
  95.748 -
  95.749 -        /** Adds an item into the storage.
  95.750 -        * @param item to add
  95.751 -        * @param transaction transaction token
  95.752 -        * @return true if the Item has been added for the first time or false if some other
  95.753 -        *    item equal to this one already existed in the lookup
  95.754 -        */
  95.755 -        public boolean add(AbstractLookup.Pair<?> item, Transaction transaction);
  95.756 -
  95.757 -        /** Removes an item.
  95.758 -        */
  95.759 -        public void remove(AbstractLookup.Pair item, Transaction transaction);
  95.760 -
  95.761 -        /** Removes all items that are not present in the provided collection.
  95.762 -        * @param retain collection of Pairs to keep them in
  95.763 -        * @param transaction the transaction context
  95.764 -        */
  95.765 -        public void retainAll(Map retain, Transaction transaction);
  95.766 -
  95.767 -        /** Queries for instances of given class.
  95.768 -        * @param clazz the class to check
  95.769 -        * @return enumeration of Item
  95.770 -        * @see #unsorted
  95.771 -        */
  95.772 -        public <T> Enumeration<Pair<T>> lookup(Class<T> clazz);
  95.773 -
  95.774 -        /** Registers another reference to a result with the storage. This method
  95.775 -         * has also a special meaning.
  95.776 -         *
  95.777 -         * @param newRef the new reference to remember
  95.778 -         * @return the previous reference that was kept (null if newRef is the first one)
  95.779 -         *    the applications is expected to link from newRef to this returned
  95.780 -         *    value to form a linked list
  95.781 -         */
  95.782 -        public ReferenceToResult<?> registerReferenceToResult(ReferenceToResult<?> newRef);
  95.783 -
  95.784 -        /** Given the provided template, Do cleanup the results.
  95.785 -         * @param templ template of a result(s) that should be checked
  95.786 -         * @return null if all references for this template were cleared or one of them
  95.787 -         */
  95.788 -        public ReferenceToResult<?> cleanUpResult(Lookup.Template<?> templ);
  95.789 -    }
  95.790 -
  95.791 -    /** Extension to the default lookup item that offers additional information
  95.792 -     * for the data structures use in AbstractLookup
  95.793 -     */
  95.794 -    public static abstract class Pair<T> extends Lookup.Item<T> implements Serializable {
  95.795 -        private static final long serialVersionUID = 1L;
  95.796 -
  95.797 -        /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */
  95.798 -        private int index = -1;
  95.799 -
  95.800 -        /** For use by subclasses. */
  95.801 -        protected Pair() {
  95.802 -        }
  95.803 -
  95.804 -        final int getIndex() {
  95.805 -            return index;
  95.806 -        }
  95.807 -
  95.808 -        final void setIndex(AbstractLookup.Storage<?> tree, int x) {
  95.809 -            if (tree == null) {
  95.810 -                this.index = x;
  95.811 -
  95.812 -                return;
  95.813 -            }
  95.814 -
  95.815 -            if (this.index == -1) {
  95.816 -                this.index = x;
  95.817 -            } else {
  95.818 -                throw new IllegalStateException("You cannot use " + this + " in more than one AbstractLookup. Prev: " + this.index + " new: " + x); // NOI18N
  95.819 -            }
  95.820 -        }
  95.821 -
  95.822 -        /** Tests whether this item can produce object
  95.823 -        * of class c.
  95.824 -        */
  95.825 -        protected abstract boolean instanceOf(Class<?> c);
  95.826 -
  95.827 -        /** Method that can test whether an instance of a class has been created
  95.828 -         * by this item.
  95.829 -         *
  95.830 -         * @param obj the instance
  95.831 -         * @return if the item has already create an instance and it is the same
  95.832 -         *   as obj.
  95.833 -         */
  95.834 -        protected abstract boolean creatorOf(Object obj);
  95.835 -    }
  95.836 -
  95.837 -    /** Result based on one instance returned.
  95.838 -     */
  95.839 -    static final class R<T> extends WaitableResult<T> {
  95.840 -        /** reference our result is attached to (do not modify) */
  95.841 -        public ReferenceToResult<T> reference;
  95.842 -
  95.843 -        /** listeners on the results or pointer to one listener */
  95.844 -        private Object listeners;
  95.845 -
  95.846 -        public R() {
  95.847 -        }
  95.848 -
  95.849 -        /** Checks whether we have simple behaviour of complex.
  95.850 -         */
  95.851 -        private boolean isSimple() {
  95.852 -            Storage s = (Storage) reference.lookup.tree;
  95.853 -
  95.854 -            return DelegatingStorage.isSimple(s);
  95.855 -        }
  95.856 -
  95.857 -        //
  95.858 -        // Handling cache management for both cases, no caches
  95.859 -        // for simple (but mark that we needed them, so refresh can
  95.860 -        // be done in cloneList) and complex when all 3 types
  95.861 -        // of result are cached
  95.862 -        //
  95.863 -        private Object getFromCache(int indx) {
  95.864 -            if (isSimple()) {
  95.865 -                return null;
  95.866 -            }
  95.867 -
  95.868 -            Object maybeArray = reference.caches;
  95.869 -
  95.870 -            if (maybeArray instanceof Object[]) {
  95.871 -                return ((Object[]) maybeArray)[indx];
  95.872 -            }
  95.873 -
  95.874 -            return null;
  95.875 -        }
  95.876 -
  95.877 -        @SuppressWarnings("unchecked")
  95.878 -        private Set<Class<? extends T>> getClassesCache() {
  95.879 -            return (Set<Class<? extends T>>) getFromCache(0);
  95.880 -        }
  95.881 -
  95.882 -        private void setClassesCache(Set s) {
  95.883 -            if (isSimple()) {
  95.884 -                // mark it as being used
  95.885 -                reference.caches = reference;
  95.886 -
  95.887 -                return;
  95.888 -            }
  95.889 -
  95.890 -            if (!(reference.caches instanceof Object[])) {
  95.891 -                reference.caches = new Object[3];
  95.892 -            }
  95.893 -
  95.894 -            ((Object[]) reference.caches)[0] = s;
  95.895 -        }
  95.896 -
  95.897 -        @SuppressWarnings("unchecked")
  95.898 -        private Collection<T> getInstancesCache() {
  95.899 -            return (Collection<T>) getFromCache(1);
  95.900 -        }
  95.901 -
  95.902 -        private void setInstancesCache(Collection c) {
  95.903 -            if (isSimple()) {
  95.904 -                // mark it as being used
  95.905 -                reference.caches = reference;
  95.906 -
  95.907 -                return;
  95.908 -            }
  95.909 -
  95.910 -            if (!(reference.caches instanceof Object[])) {
  95.911 -                reference.caches = new Object[3];
  95.912 -            }
  95.913 -
  95.914 -            ((Object[]) reference.caches)[1] = c;
  95.915 -        }
  95.916 -
  95.917 -        @SuppressWarnings("unchecked")
  95.918 -        private Pair<T>[] getItemsCache() {
  95.919 -            return (Pair<T>[]) getFromCache(2);
  95.920 -        }
  95.921 -
  95.922 -        private void setItemsCache(Collection<?> c) {
  95.923 -            if (isSimple()) {
  95.924 -                // mark it as being used
  95.925 -                reference.caches = reference;
  95.926 -
  95.927 -                return;
  95.928 -            }
  95.929 -
  95.930 -            if (!(reference.caches instanceof Object[])) {
  95.931 -                reference.caches = new Object[3];
  95.932 -            }
  95.933 -
  95.934 -            ((Object[]) reference.caches)[2] = c.toArray(new Pair[0]);
  95.935 -        }
  95.936 -
  95.937 -        private void clearCaches() {
  95.938 -            if (reference.caches instanceof Object[]) {
  95.939 -                reference.caches = new Object[3];
  95.940 -            }
  95.941 -        }
  95.942 -
  95.943 -        /** Ok, register listeners to all classes and super classes.
  95.944 -         */
  95.945 -        public synchronized void addLookupListener(LookupListener l) {
  95.946 -            listeners = modifyListenerList(true, l, listeners);
  95.947 -        }
  95.948 -
  95.949 -        /** Ok, register listeners to all classes and super classes.
  95.950 -         */
  95.951 -        public synchronized void removeLookupListener(LookupListener l) {
  95.952 -            listeners = modifyListenerList(false, l, listeners);
  95.953 -        }
  95.954 -
  95.955 -        /** Delete all cached values, the template changed.
  95.956 -         */
  95.957 -        protected  void collectFires(Collection<Object> evAndListeners) {
  95.958 -            Object[] previousItems = getItemsCache();
  95.959 -            clearCaches();
  95.960 -            
  95.961 -            if (previousItems != null) {
  95.962 -                Object[] newArray = allItemsWithoutBeforeLookup().toArray();
  95.963 -
  95.964 -                if (compareArrays(previousItems, newArray)) {
  95.965 -                    // do not fire any change if nothing has been changed
  95.966 -                    return;
  95.967 -                }
  95.968 -            }
  95.969 -
  95.970 -            LookupListener[] arr;
  95.971 -
  95.972 -            synchronized (this) {
  95.973 -                if (listeners == null) {
  95.974 -                    return;
  95.975 -                }
  95.976 -
  95.977 -                if (listeners instanceof LookupListener) {
  95.978 -                    arr = new LookupListener[] { (LookupListener) listeners };
  95.979 -                } else {
  95.980 -                    ArrayList<?> l = (ArrayList<?>) listeners;
  95.981 -                    arr = l.toArray(new LookupListener[l.size()]);
  95.982 -                }
  95.983 -            }
  95.984 -
  95.985 -            final LookupListener[] ll = arr;
  95.986 -            final LookupEvent ev = new LookupEvent(this);
  95.987 -            notifyListeners(ll, ev, evAndListeners);
  95.988 -        }
  95.989 -
  95.990 -        public Collection<T> allInstances() {
  95.991 -            reference.lookup.beforeLookup(reference.template);
  95.992 -
  95.993 -            Collection<T> s = getInstancesCache();
  95.994 -
  95.995 -            if (s != null) {
  95.996 -                return s;
  95.997 -            }
  95.998 -
  95.999 -            Collection<Pair<T>> items = allItemsWithoutBeforeLookup();
 95.1000 -            ArrayList<T> list = new ArrayList<T>(items.size());
 95.1001 -
 95.1002 -            Iterator<Pair<T>> it = items.iterator();
 95.1003 -
 95.1004 -            while (it.hasNext()) {
 95.1005 -                Pair<T> item = it.next();
 95.1006 -                T obj = item.getInstance();
 95.1007 -
 95.1008 -                if (reference.template.getType().isInstance(obj)) {
 95.1009 -                    list.add(obj);
 95.1010 -                }
 95.1011 -            }
 95.1012 -            
 95.1013 -            s = Collections.unmodifiableList(list);
 95.1014 -            setInstancesCache(s);
 95.1015 -
 95.1016 -            return s;
 95.1017 -        }
 95.1018 -
 95.1019 -        /** Set of all classes.
 95.1020 -         *
 95.1021 -         */
 95.1022 -        @Override
 95.1023 -        public Set<Class<? extends T>> allClasses() {
 95.1024 -            reference.lookup.beforeLookup(reference.template);
 95.1025 -
 95.1026 -            Set<Class<? extends T>> s = getClassesCache();
 95.1027 -
 95.1028 -            if (s != null) {
 95.1029 -                return s;
 95.1030 -            }
 95.1031 -
 95.1032 -            s = new HashSet<Class<? extends T>>();
 95.1033 -
 95.1034 -            for (Pair<T> item : allItemsWithoutBeforeLookup()) {
 95.1035 -                Class<? extends T> clazz = item.getType();
 95.1036 -
 95.1037 -                if (clazz != null) {
 95.1038 -                    s.add(clazz);
 95.1039 -                }
 95.1040 -            }
 95.1041 -
 95.1042 -            s = Collections.unmodifiableSet(s);
 95.1043 -            setClassesCache(s);
 95.1044 -
 95.1045 -            return s;
 95.1046 -        }
 95.1047 -
 95.1048 -        /** Items are stored directly in the allItems.
 95.1049 -         */
 95.1050 -        @Override
 95.1051 -        public Collection<? extends Item<T>> allItems() {
 95.1052 -            reference.lookup.beforeLookup(reference.template);
 95.1053 -
 95.1054 -            return allItemsWithoutBeforeLookup();
 95.1055 -        }
 95.1056 -
 95.1057 -        /** Implements the search for allItems, but without asking for before lookup */
 95.1058 -        private Collection<Pair<T>> allItemsWithoutBeforeLookup() {
 95.1059 -            Pair<T>[] c = getItemsCache();
 95.1060 -
 95.1061 -            if (c != null) {
 95.1062 -                return Collections.unmodifiableList(Arrays.asList(c));
 95.1063 -            }
 95.1064 -
 95.1065 -            ArrayList<Pair<Object>> saferCheck = null;
 95.1066 -            AbstractLookup.Storage<?> t = reference.lookup.enterStorage();
 95.1067 -
 95.1068 -            try {
 95.1069 -                try {
 95.1070 -                    return Collections.unmodifiableCollection(initItems(t));
 95.1071 -                } catch (AbstractLookup.ISE ex) {
 95.1072 -                    // do less effective evaluation of items outside of the 
 95.1073 -                    // locked storage
 95.1074 -                    saferCheck = new ArrayList<Pair<Object>>();
 95.1075 -
 95.1076 -                    Enumeration<Pair<Object>> en = t.lookup(null); // get all Pairs
 95.1077 -
 95.1078 -                    while (en.hasMoreElements()) {
 95.1079 -                        Pair<Object> i = en.nextElement();
 95.1080 -                        saferCheck.add(i);
 95.1081 -                    }
 95.1082 -                }
 95.1083 -            } finally {
 95.1084 -                reference.lookup.exitStorage();
 95.1085 -            }
 95.1086 -            return extractPairs(saferCheck);
 95.1087 -        }
 95.1088 -
 95.1089 -        @SuppressWarnings("unchecked")
 95.1090 -        private Collection<Pair<T>> extractPairs(final ArrayList<Pair<Object>> saferCheck) {
 95.1091 -            TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
 95.1092 -            for (Pair<Object> i : saferCheck) {
 95.1093 -                if (matches(reference.template, i, false)) {
 95.1094 -                    items.add((Pair<T>)i);
 95.1095 -                }
 95.1096 -            }
 95.1097 -            return Collections.unmodifiableCollection(items);
 95.1098 -        }
 95.1099 -
 95.1100 -        /** Initializes items.
 95.1101 -         */
 95.1102 -        private Collection<Pair<T>> initItems(Storage<?> t) {
 95.1103 -            // manipulation with the tree must be synchronized
 95.1104 -            Enumeration<Pair<T>> en = t.lookup(reference.template.getType());
 95.1105 -
 95.1106 -            // InheritanceTree is comparator for AbstractLookup.Pairs
 95.1107 -            TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
 95.1108 -
 95.1109 -            while (en.hasMoreElements()) {
 95.1110 -                Pair<T> i = en.nextElement();
 95.1111 -
 95.1112 -                if (matches(reference.template, i, false)) {
 95.1113 -                    items.add(i);
 95.1114 -                }
 95.1115 -            }
 95.1116 -
 95.1117 -            // create a correctly sorted copy using the tree as the comparator
 95.1118 -            setItemsCache(items);
 95.1119 -
 95.1120 -            return items;
 95.1121 -        }
 95.1122 -
 95.1123 -        /** Used by proxy results to synchronize before lookup.
 95.1124 -         */
 95.1125 -        protected void beforeLookup(Lookup.Template t) {
 95.1126 -            if (t.getType() == reference.template.getType()) {
 95.1127 -                reference.lookup.beforeLookup(t);
 95.1128 -            }
 95.1129 -        }
 95.1130 -
 95.1131 -        /* Do not need to implement it, the default way is ok.
 95.1132 -        public boolean equals(java.lang.Object obj) {
 95.1133 -            return obj == this;
 95.1134 -        }
 95.1135 -        */
 95.1136 -        @Override
 95.1137 -        public String toString() {
 95.1138 -            return super.toString() + " for " + reference.template;
 95.1139 -        }
 95.1140 -    }
 95.1141 -     // end of R
 95.1142 -
 95.1143 -    /** A class that can be used by the creator of the AbstractLookup to
 95.1144 -     * control its content. It can be passed to AbstractLookup constructor
 95.1145 -     * and used to add and remove pairs.
 95.1146 -     *
 95.1147 -     * @since 1.25
 95.1148 -     */
 95.1149 -    public static class Content extends Object implements Serializable {
 95.1150 -        private static final long serialVersionUID = 1L;
 95.1151 -
 95.1152 -        // one of them is always null (except attach stage)
 95.1153 -
 95.1154 -        /** abstract lookup we are connected to */
 95.1155 -        private AbstractLookup al;
 95.1156 -        private transient Object notifyIn;
 95.1157 -        
 95.1158 -        /** Default constructor.
 95.1159 -         */
 95.1160 -        public Content() {
 95.1161 -            this(null);
 95.1162 -        }
 95.1163 -        
 95.1164 -        /** Creates a content associated with an executor to handle dispatch
 95.1165 -         * of changes.
 95.1166 -         * @param notifyIn the executor to notify changes in
 95.1167 -         * @since  7.16
 95.1168 -         */
 95.1169 -        public Content(Executor notifyIn) {
 95.1170 -            this.notifyIn = notifyIn;
 95.1171 -        }
 95.1172 -        
 95.1173 -        /** for testing purposes */
 95.1174 -        final void attachExecutor(Executor notifyIn) {
 95.1175 -            this.notifyIn = notifyIn;
 95.1176 -        }
 95.1177 -
 95.1178 -        /** A lookup attaches to this object.
 95.1179 -         */
 95.1180 -        final synchronized void attach(AbstractLookup al) {
 95.1181 -            if (this.al == null) {
 95.1182 -                this.al = al;
 95.1183 -
 95.1184 -                ArrayList<Pair> ep = getEarlyPairs();
 95.1185 -                if (ep != null) {
 95.1186 -                    notifyIn = null;
 95.1187 -                    setPairs(ep);
 95.1188 -                }
 95.1189 -            } else {
 95.1190 -                throw new IllegalStateException(
 95.1191 -                    "Trying to use content for " + al + " but it is already used for " + this.al
 95.1192 -                ); // NOI18N
 95.1193 -            }
 95.1194 -        }
 95.1195 -
 95.1196 -        /** The method to add instance to the lookup with.
 95.1197 -         * @param pair class/instance pair
 95.1198 -         */
 95.1199 -        public final void addPair(Pair<?> pair) {
 95.1200 -            AbstractLookup a = al;
 95.1201 -            Executor e = getExecutor();
 95.1202 -
 95.1203 -            if (a != null || e != null) {
 95.1204 -                a.addPair(pair, e);
 95.1205 -            } else {
 95.1206 -                if (notifyIn == null) {
 95.1207 -                    notifyIn = new ArrayList<Pair>(3);
 95.1208 -                }
 95.1209 -
 95.1210 -                getEarlyPairs().add(pair);
 95.1211 -            }
 95.1212 -        }
 95.1213 -
 95.1214 -        /** Remove instance.
 95.1215 -         * @param pair class/instance pair
 95.1216 -         */
 95.1217 -        public final void removePair(Pair<?> pair) {
 95.1218 -            AbstractLookup a = al;
 95.1219 -            Executor e = getExecutor();
 95.1220 -
 95.1221 -            if (a != null || e != null) {
 95.1222 -                a.removePair(pair, e);
 95.1223 -            } else {
 95.1224 -                if (notifyIn == null) {
 95.1225 -                    notifyIn = new ArrayList<Pair>(3);
 95.1226 -                }
 95.1227 -
 95.1228 -                getEarlyPairs().remove(pair);
 95.1229 -            }
 95.1230 -        }
 95.1231 -
 95.1232 -        /** Changes all pairs in the lookup to new values.
 95.1233 -         * @param c the collection of (Pair) objects
 95.1234 -         */
 95.1235 -        public final void setPairs(Collection<? extends Pair> c) {
 95.1236 -            AbstractLookup a = al;
 95.1237 -            Executor e = getExecutor();
 95.1238 -            
 95.1239 -            if (a != null || e != null) {
 95.1240 -                a.setPairs(c, e);
 95.1241 -            } else {
 95.1242 -                notifyIn = new ArrayList<Pair>(c);
 95.1243 -            }
 95.1244 -        }
 95.1245 -
 95.1246 -        @SuppressWarnings("unchecked")
 95.1247 -        private ArrayList<Pair> getEarlyPairs() {
 95.1248 -            Object o = notifyIn;
 95.1249 -            return o instanceof ArrayList ? (ArrayList<Pair>)o : null;
 95.1250 -        }
 95.1251 -        
 95.1252 -        private Executor getExecutor() {
 95.1253 -            Object o = notifyIn;
 95.1254 -            return o instanceof Executor ? (Executor)o : null;
 95.1255 -        }
 95.1256 -    }
 95.1257 -     // end of Content
 95.1258 -
 95.1259 -    /** Just a holder for index & modified values.
 95.1260 -     */
 95.1261 -    final static class Info extends Object {
 95.1262 -        public int index;
 95.1263 -        public Object transaction;
 95.1264 -
 95.1265 -        public Info(int i, Object t) {
 95.1266 -            index = i;
 95.1267 -            transaction = t;
 95.1268 -        }
 95.1269 -    }
 95.1270 -
 95.1271 -    /** Reference to a result R
 95.1272 -     */
 95.1273 -    static final class ReferenceToResult<T> extends WeakReference<R<T>> implements Runnable {
 95.1274 -        /** next refernece in chain, modified only from AbstractLookup or this */
 95.1275 -        private ReferenceToResult<?> next;
 95.1276 -
 95.1277 -        /** the template for the result */
 95.1278 -        public final Template<T> template;
 95.1279 -
 95.1280 -        /** the lookup we are attached to */
 95.1281 -        public final AbstractLookup lookup;
 95.1282 -
 95.1283 -        /** caches for results */
 95.1284 -        public Object caches;
 95.1285 -
 95.1286 -        /** Creates a weak refernece to a new result R in context of lookup
 95.1287 -         * for given template
 95.1288 -         */
 95.1289 -        private ReferenceToResult(R<T> result, AbstractLookup lookup, Template<T> template) {
 95.1290 -            super(result, activeQueue());
 95.1291 -            this.template = template;
 95.1292 -            this.lookup = lookup;
 95.1293 -            getResult().reference = this;
 95.1294 -        }
 95.1295 -
 95.1296 -        /** Returns the result or null
 95.1297 -         */
 95.1298 -        R<T> getResult() {
 95.1299 -            return get();
 95.1300 -        }
 95.1301 -
 95.1302 -        /** Cleans the reference. Implements Runnable interface, do not call
 95.1303 -         * directly.
 95.1304 -         */
 95.1305 -        public void run() {
 95.1306 -            lookup.cleanUpResult(this.template);
 95.1307 -        }
 95.1308 -
 95.1309 -        /** Clones the reference list to given Storage.
 95.1310 -         * @param storage storage to clone to
 95.1311 -         */
 95.1312 -        public void cloneList(AbstractLookup.Storage<?> storage) {
 95.1313 -            ReferenceIterator it = new ReferenceIterator(this);
 95.1314 -
 95.1315 -            while (it.next()) {
 95.1316 -                ReferenceToResult<?> current = it.current();
 95.1317 -                ReferenceToResult<?> newRef = current.cloneRef();
 95.1318 -                newRef.next = storage.registerReferenceToResult(newRef);
 95.1319 -                newRef.caches = current.caches;
 95.1320 -
 95.1321 -                if (current.caches == current) {
 95.1322 -                    current.getResult().initItems(storage);
 95.1323 -                }
 95.1324 -            }
 95.1325 -        }
 95.1326 -
 95.1327 -        private ReferenceToResult<T> cloneRef() {
 95.1328 -            return new ReferenceToResult<T>(getResult(), lookup, template);
 95.1329 -        }
 95.1330 -    }
 95.1331 -     // end of ReferenceToResult
 95.1332 -
 95.1333 -    /** Supporting class to iterate over linked list of ReferenceToResult
 95.1334 -     * Use:
 95.1335 -     * <PRE>
 95.1336 -     *  ReferenceIterator it = new ReferenceIterator (this.ref);
 95.1337 -     *  while (it.next ()) {
 95.1338 -     *    it.current (): // do some work
 95.1339 -     *  }
 95.1340 -     *  this.ref = it.first (); // remember the first one
 95.1341 -     */
 95.1342 -    static final class ReferenceIterator extends Object {
 95.1343 -        private ReferenceToResult<?> first;
 95.1344 -        private ReferenceToResult<?> current;
 95.1345 -
 95.1346 -        /** hard reference to current result, so it is not GCed meanwhile */
 95.1347 -        private R<?> currentResult;
 95.1348 -
 95.1349 -        /** Initializes the iterator with first reference.
 95.1350 -         */
 95.1351 -        public ReferenceIterator(ReferenceToResult<?> first) {
 95.1352 -            this.first = first;
 95.1353 -        }
 95.1354 -
 95.1355 -        /** Moves the current to next possition */
 95.1356 -        public boolean next() {
 95.1357 -            ReferenceToResult<?> prev;
 95.1358 -            ReferenceToResult<?> ref;
 95.1359 -
 95.1360 -            if (current == null) {
 95.1361 -                ref = first;
 95.1362 -                prev = null;
 95.1363 -            } else {
 95.1364 -                prev = current;
 95.1365 -                ref = current.next;
 95.1366 -            }
 95.1367 -
 95.1368 -            while (ref != null) {
 95.1369 -                R<?> result = ref.get();
 95.1370 -
 95.1371 -                if (result == null) {
 95.1372 -                    if (prev == null) {
 95.1373 -                        // move the head
 95.1374 -                        first = ref.next;
 95.1375 -                    } else {
 95.1376 -                        // skip over this reference
 95.1377 -                        prev.next = ref.next;
 95.1378 -                    }
 95.1379 -
 95.1380 -                    prev = ref;
 95.1381 -                    ref = ref.next;
 95.1382 -                } else {
 95.1383 -                    // we have found next item
 95.1384 -                    currentResult = result;
 95.1385 -                    current = ref;
 95.1386 -
 95.1387 -                    return true;
 95.1388 -                }
 95.1389 -            }
 95.1390 -
 95.1391 -            currentResult = null;
 95.1392 -            current = null;
 95.1393 -
 95.1394 -            return false;
 95.1395 -        }
 95.1396 -
 95.1397 -        /** Access to current reference.
 95.1398 -         */
 95.1399 -        public ReferenceToResult<?> current() {
 95.1400 -            return current;
 95.1401 -        }
 95.1402 -
 95.1403 -        /** Access to reference that is supposed to be the first one.
 95.1404 -         */
 95.1405 -        public ReferenceToResult<?> first() {
 95.1406 -            return first;
 95.1407 -        }
 95.1408 -    }
 95.1409 -
 95.1410 -    /** Signals that a lookup is being modified from a lookup query.
 95.1411 -     *
 95.1412 -     * @author  Jaroslav Tulach
 95.1413 -     */
 95.1414 -    static final class ISE extends IllegalStateException {
 95.1415 -        static final long serialVersionUID = 100L;
 95.1416 -        
 95.1417 -        /** list of jobs to execute. */
 95.1418 -        private java.util.List<Job> jobs;
 95.1419 -
 95.1420 -        /** @param msg message
 95.1421 -         */
 95.1422 -        public ISE(String msg) {
 95.1423 -            super(msg);
 95.1424 -        }
 95.1425 -
 95.1426 -        /** Registers a job to be executed partially out and partially in
 95.1427 -         * the lock over storage.
 95.1428 -         */
 95.1429 -        public void registerJob(Job job) {
 95.1430 -            if (jobs == null) {
 95.1431 -                jobs = new java.util.ArrayList<Job>();
 95.1432 -            }
 95.1433 -
 95.1434 -            jobs.add(job);
 95.1435 -        }
 95.1436 -
 95.1437 -        /** Executes the jobs outside, and then inside a locked session.
 95.1438 -         */
 95.1439 -        public void recover(AbstractLookup lookup) {
 95.1440 -            if (jobs == null) {
 95.1441 -                // no recovery plan, throw itself
 95.1442 -                throw this;
 95.1443 -            }
 95.1444 -
 95.1445 -            for (Job j : jobs) {
 95.1446 -                j.before();
 95.1447 -            }
 95.1448 -
 95.1449 -            AbstractLookup.Storage s = lookup.enterStorage();
 95.1450 -
 95.1451 -            try {
 95.1452 -                for (Job j : jobs) {
 95.1453 -                    j.inside();
 95.1454 -                }
 95.1455 -            } finally {
 95.1456 -                lookup.exitStorage();
 95.1457 -            }
 95.1458 -        }
 95.1459 -
 95.1460 -        /** A job to be executed partially outside and partially inside
 95.1461 -         * the storage lock.
 95.1462 -         */
 95.1463 -        static interface Job {
 95.1464 -            public void before();
 95.1465 -
 95.1466 -            public void inside();
 95.1467 -        }
 95.1468 -    }
 95.1469 -     // end of ISE
 95.1470 -}
    96.1 --- a/openide.util/src/org/openide/util/lookup/ArrayStorage.java	Thu Dec 10 19:23:25 2009 -0500
    96.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.3 @@ -1,477 +0,0 @@
    96.4 -/*
    96.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    96.6 - *
    96.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    96.8 - *
    96.9 - * The contents of this file are subject to the terms of either the GNU
   96.10 - * General Public License Version 2 only ("GPL") or the Common
   96.11 - * Development and Distribution License("CDDL") (collectively, the
   96.12 - * "License"). You may not use this file except in compliance with the
   96.13 - * License. You can obtain a copy of the License at
   96.14 - * http://www.netbeans.org/cddl-gplv2.html
   96.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   96.16 - * specific language governing permissions and limitations under the
   96.17 - * License.  When distributing the software, include this License Header
   96.18 - * Notice in each file and include the License file at
   96.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   96.20 - * particular file as subject to the "Classpath" exception as provided
   96.21 - * by Sun in the GPL Version 2 section of the License file that
   96.22 - * accompanied this code. If applicable, add the following below the
   96.23 - * License Header, with the fields enclosed by brackets [] replaced by
   96.24 - * your own identifying information:
   96.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   96.26 - *
   96.27 - * Contributor(s):
   96.28 - *
   96.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   96.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   96.31 - * Microsystems, Inc. All Rights Reserved.
   96.32 - *
   96.33 - * If you wish your version of this file to be governed by only the CDDL
   96.34 - * or only the GPL Version 2, indicate your decision by adding
   96.35 - * "[Contributor] elects to include this software in this distribution
   96.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   96.37 - * single choice of license, a recipient has the option to distribute
   96.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   96.39 - * to extend the choice of license to its licensees as provided above.
   96.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   96.41 - * Version 2 license, then the option applies only if the new code is
   96.42 - * made subject to such option by the copyright holder.
   96.43 - */
   96.44 -package org.openide.util.lookup;
   96.45 -
   96.46 -import org.openide.util.Lookup;
   96.47 -
   96.48 -
   96.49 -
   96.50 -import java.util.*;
   96.51 -import org.openide.util.lookup.AbstractLookup.Pair;
   96.52 -
   96.53 -
   96.54 -/** ArrayStorage of Pairs from AbstractLookup.
   96.55 - * @author  Jaroslav Tulach
   96.56 - */
   96.57 -final class ArrayStorage extends Object
   96.58 -implements AbstractLookup.Storage<ArrayStorage.Transaction> {
   96.59 -    /** default trashold */
   96.60 -    static final Integer DEFAULT_TRASH = new Integer(11);
   96.61 -
   96.62 -    /** list of items */
   96.63 -    private Object content;
   96.64 -
   96.65 -    /** linked list of refernces to results */
   96.66 -    private transient AbstractLookup.ReferenceToResult<?> results;
   96.67 -
   96.68 -    /** Constructor
   96.69 -     */
   96.70 -    public ArrayStorage() {
   96.71 -        this(DEFAULT_TRASH);
   96.72 -    }
   96.73 -
   96.74 -    /** Constructs new ArrayStorage */
   96.75 -    public ArrayStorage(Integer treshhold) {
   96.76 -        this.content = treshhold;
   96.77 -    }
   96.78 -
   96.79 -    /** Adds an item into the tree.
   96.80 -    * @param item to add
   96.81 -    * @return true if the Item has been added for the first time or false if some other
   96.82 -    *    item equal to this one already existed in the lookup
   96.83 -    */
   96.84 -    public boolean add(AbstractLookup.Pair<?> item, Transaction changed) {
   96.85 -        Object[] arr = changed.current;
   96.86 -
   96.87 -        if (changed.arr == null) {
   96.88 -            // just simple add of one item
   96.89 -            for (int i = 0; i < arr.length; i++) {
   96.90 -                if (arr[i] == null) {
   96.91 -                    arr[i] = item;
   96.92 -                    changed.add(item);
   96.93 -
   96.94 -                    return true;
   96.95 -                }
   96.96 -
   96.97 -                if (arr[i].equals(item)) {
   96.98 -                    // reassign the item number
   96.99 -                    item.setIndex(null, ((AbstractLookup.Pair) arr[i]).getIndex());
  96.100 -
  96.101 -                    // already there, but update it
  96.102 -                    arr[i] = item;
  96.103 -
  96.104 -                    return false;
  96.105 -                }
  96.106 -            }
  96.107 -
  96.108 -            // cannot happen as the beginTransaction ensured we can finish 
  96.109 -            // correctly
  96.110 -            throw new IllegalStateException();
  96.111 -        } else {
  96.112 -            // doing remainAll after that, let Transaction hold the new array
  96.113 -            int newIndex = changed.addPair(item);
  96.114 -
  96.115 -            for (int i = 0; i < arr.length; i++) {
  96.116 -                if (arr[i] == null) {
  96.117 -                    changed.add(item);
  96.118 -
  96.119 -                    return true;
  96.120 -                }
  96.121 -
  96.122 -                if (arr[i].equals(item)) {
  96.123 -                    // already there
  96.124 -                    if (i != newIndex) {
  96.125 -                        // change in index
  96.126 -                        changed.add(item);
  96.127 -
  96.128 -                        return false;
  96.129 -                    } else {
  96.130 -                        // no change
  96.131 -                        return false;
  96.132 -                    }
  96.133 -                }
  96.134 -            }
  96.135 -
  96.136 -            // if not found in the original array
  96.137 -            changed.add(item);
  96.138 -
  96.139 -            return true;
  96.140 -        }
  96.141 -    }
  96.142 -
  96.143 -    /** Removes an item.
  96.144 -    */
  96.145 -    public void remove(AbstractLookup.Pair item, Transaction changed) {
  96.146 -        Object[] arr = changed.current;
  96.147 -        if (arr == null) {
  96.148 -            return;
  96.149 -        }
  96.150 -
  96.151 -        int found = -1;
  96.152 -
  96.153 -        for (int i = 0; i < arr.length;) {
  96.154 -            if (arr[i] == null) {
  96.155 -                // end of task
  96.156 -                return;
  96.157 -            }
  96.158 -
  96.159 -            if ((found == -1) && arr[i].equals(item)) {
  96.160 -                // already there
  96.161 -                Pair<?> p = (Pair<?>)arr[i];
  96.162 -                p.setIndex(null, -1);
  96.163 -                changed.add(p);
  96.164 -                found = i;
  96.165 -            }
  96.166 -
  96.167 -            i++;
  96.168 -
  96.169 -            if (found != -1) {
  96.170 -                if (i < arr.length && !(arr[i] instanceof Integer)) {
  96.171 -                    // moving the array
  96.172 -                    arr[i - 1] = arr[i];
  96.173 -                } else {
  96.174 -                    arr[i - 1] = null;
  96.175 -                }
  96.176 -            }
  96.177 -        }
  96.178 -    }
  96.179 -
  96.180 -    /** Removes all items that are not present in the provided collection.
  96.181 -    * @param retain Pair -> AbstractLookup.Info map
  96.182 -    * @param notify set of Classes that has possibly changed
  96.183 -    */
  96.184 -    public void retainAll(Map retain, Transaction changed) {
  96.185 -        Object[] arr = changed.current;
  96.186 -
  96.187 -        for (int from = 0; from < arr.length; from++) {
  96.188 -            if (!(arr[from] instanceof AbstractLookup.Pair)) {
  96.189 -                // end of content
  96.190 -                break;
  96.191 -            }
  96.192 -
  96.193 -            AbstractLookup.Pair p = (AbstractLookup.Pair) arr[from];
  96.194 -
  96.195 -            AbstractLookup.Info info = (AbstractLookup.Info) retain.get(p);
  96.196 -
  96.197 -            if (info == null) {
  96.198 -                // was removed
  96.199 -
  96.200 -                /*
  96.201 -                if (info != null) {
  96.202 -                if (info.index < arr.length) {
  96.203 -                    newArr[info.index] = p;
  96.204 -                }
  96.205 -
  96.206 -                if (p.getIndex() != info.index) {
  96.207 -                    p.setIndex (null, info.index);
  96.208 -                    changed.add (p);
  96.209 -                }
  96.210 -                } else {
  96.211 -                // removed
  96.212 -                 */
  96.213 -                changed.add(p);
  96.214 -            }
  96.215 -        }
  96.216 -    }
  96.217 -
  96.218 -    /** Queries for instances of given class.
  96.219 -    * @param clazz the class to check
  96.220 -    * @return enumeration of Item
  96.221 -    * @see #unsorted
  96.222 -    */
  96.223 -    public <T> Enumeration<Pair<T>> lookup(final Class<T> clazz) {
  96.224 -        if (content instanceof Object[]) {
  96.225 -            final Enumeration<Object> all = InheritanceTree.arrayEn((Object[]) content);
  96.226 -            class JustPairs implements Enumeration<Pair<T>> {
  96.227 -                private Pair<T> next;
  96.228 -
  96.229 -                @SuppressWarnings("unchecked")
  96.230 -                private Pair<T> findNext() {
  96.231 -                    for (;;) {
  96.232 -                        if (next != null) {
  96.233 -                            return next;
  96.234 -                        }
  96.235 -                        if (!all.hasMoreElements()) {
  96.236 -                            return null;
  96.237 -                        }
  96.238 -                        Object o = all.nextElement();
  96.239 -                        boolean ok;
  96.240 -                        if (o instanceof AbstractLookup.Pair) {
  96.241 -                            ok = (clazz == null) || ((AbstractLookup.Pair<?>) o).instanceOf(clazz);
  96.242 -                        } else {
  96.243 -                            ok = false;
  96.244 -                        }
  96.245 -
  96.246 -                        next = ok ? (Pair<T>) o : null;
  96.247 -                    }
  96.248 -                }
  96.249 -                
  96.250 -                public boolean hasMoreElements() {
  96.251 -                    return findNext() != null;
  96.252 -                }
  96.253 -
  96.254 -                public Pair<T> nextElement() {
  96.255 -                    Pair<T> r = findNext();
  96.256 -                    if (r == null) {
  96.257 -                        throw new NoSuchElementException();
  96.258 -                    }
  96.259 -                    next = null;
  96.260 -                    return r;
  96.261 -                }
  96.262 -            } // end of JustPairs
  96.263 -            return new JustPairs();
  96.264 -        } else {
  96.265 -            return InheritanceTree.emptyEn();
  96.266 -        }
  96.267 -    }
  96.268 -
  96.269 -    /** Associates another result with this storage.
  96.270 -     */
  96.271 -    public AbstractLookup.ReferenceToResult registerReferenceToResult(AbstractLookup.ReferenceToResult<?> newRef) {
  96.272 -        AbstractLookup.ReferenceToResult prev = this.results;
  96.273 -        this.results = newRef;
  96.274 -
  96.275 -        return prev;
  96.276 -    }
  96.277 -
  96.278 -    /** Cleanup the references
  96.279 -     */
  96.280 -    public AbstractLookup.ReferenceToResult cleanUpResult(Lookup.Template<?> templ) {
  96.281 -        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
  96.282 -
  96.283 -        while (it.next()) {
  96.284 -            // empty
  96.285 -        }
  96.286 -
  96.287 -        return this.results = it.first();
  96.288 -    }
  96.289 -
  96.290 -    /** We use a hash set of all modified Pair to handle the transaction */
  96.291 -    public Transaction beginTransaction(int ensure) {
  96.292 -        return new Transaction(ensure, content);
  96.293 -    }
  96.294 -
  96.295 -    /** Extract all results.
  96.296 -     */
  96.297 -    public void endTransaction(Transaction changed, Set<AbstractLookup.R> modified) {
  96.298 -        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
  96.299 -
  96.300 -        if (changed.arr == null) {
  96.301 -            // either add or remove, only check the content of check HashSet
  96.302 -            while (it.next()) {
  96.303 -                AbstractLookup.ReferenceToResult ref = it.current();
  96.304 -                Iterator<Pair<?>> pairs = changed.iterator();
  96.305 -
  96.306 -                while (pairs.hasNext()) {
  96.307 -                    AbstractLookup.Pair p = (AbstractLookup.Pair) pairs.next();
  96.308 -
  96.309 -                    if (AbstractLookup.matches(ref.template, p, true)) {
  96.310 -                        modified.add(ref.getResult());
  96.311 -                    }
  96.312 -                }
  96.313 -            }
  96.314 -        } else {
  96.315 -            // do full check of changes
  96.316 -            while (it.next()) {
  96.317 -                AbstractLookup.ReferenceToResult ref = it.current();
  96.318 -
  96.319 -                int oldIndex = -1;
  96.320 -                int newIndex = -1;
  96.321 -
  96.322 -                for (;;) {
  96.323 -                    oldIndex = findMatching(ref.template, changed.current, oldIndex);
  96.324 -                    newIndex = findMatching(ref.template, changed.arr, newIndex);
  96.325 -
  96.326 -                    if ((oldIndex == -1) && (newIndex == -1)) {
  96.327 -                        break;
  96.328 -                    }
  96.329 -
  96.330 -                    if (
  96.331 -                        (oldIndex == -1) || (newIndex == -1) ||
  96.332 -                            !changed.current[oldIndex].equals(changed.arr[newIndex])
  96.333 -                    ) {
  96.334 -                        modified.add(ref.getResult());
  96.335 -
  96.336 -                        break;
  96.337 -                    }
  96.338 -                }
  96.339 -            }
  96.340 -        }
  96.341 -
  96.342 -        this.results = it.first();
  96.343 -        this.content = changed.newContent(this.content);
  96.344 -    }
  96.345 -
  96.346 -    private static int findMatching(Lookup.Template t, Object[] arr, int from) {
  96.347 -        while (++from < arr.length) {
  96.348 -            if (arr[from] instanceof AbstractLookup.Pair) {
  96.349 -                if (AbstractLookup.matches(t, (AbstractLookup.Pair) arr[from], true)) {
  96.350 -                    return from;
  96.351 -                }
  96.352 -            }
  96.353 -        }
  96.354 -
  96.355 -        return -1;
  96.356 -    }
  96.357 -
  96.358 -    /** HashSet with additional field for new array which is callocated
  96.359 -     * in case we are doing replace to hold all new items.
  96.360 -     */
  96.361 -    static final class Transaction extends HashSet<Pair<?>> {
  96.362 -        /** array with current objects */
  96.363 -        public final Object[] current;
  96.364 -
  96.365 -        /** array with new objects */
  96.366 -        public final Object[] arr;
  96.367 -
  96.368 -        /** number of objects in the array */
  96.369 -        private int cnt;
  96.370 -
  96.371 -        public Transaction(int ensure, Object currentContent) {
  96.372 -            Integer trashold;
  96.373 -            Object[] _arr;
  96.374 -
  96.375 -            if (currentContent instanceof Integer) {
  96.376 -                trashold = (Integer) currentContent;
  96.377 -                _arr = null;
  96.378 -            } else {
  96.379 -                _arr = (Object[]) currentContent;
  96.380 -
  96.381 -                if (_arr[_arr.length - 1] instanceof Integer) {
  96.382 -                    trashold = (Integer) _arr[_arr.length - 1];
  96.383 -                } else {
  96.384 -                    // nowhere to grow we have reached the limit
  96.385 -                    trashold = null;
  96.386 -                }
  96.387 -            }
  96.388 -
  96.389 -            int maxSize = (trashold == null) ? _arr.length : trashold.intValue();
  96.390 -
  96.391 -            if (ensure > maxSize) {
  96.392 -                throw new UnsupportedOperationException();
  96.393 -            }
  96.394 -
  96.395 -            if (ensure == -1) {
  96.396 -                // remove => it is ok
  96.397 -                this.current = currentContent instanceof Integer ? null : (Object[]) currentContent;
  96.398 -                this.arr = null;
  96.399 -
  96.400 -                return;
  96.401 -            }
  96.402 -
  96.403 -            if (ensure == -2) {
  96.404 -                // adding one
  96.405 -                if (_arr == null) {
  96.406 -                    // first time add, let's allocate the array
  96.407 -                    _arr = new Object[2];
  96.408 -                    _arr[1] = trashold;
  96.409 -                } else {
  96.410 -                    if (_arr[_arr.length - 1] instanceof AbstractLookup.Pair) {
  96.411 -                        // we are full
  96.412 -                        throw new UnsupportedOperationException();
  96.413 -                    } else {
  96.414 -                        // ensure we have allocated enough space
  96.415 -                        if (_arr.length < 2 || _arr[_arr.length - 2] != null) {
  96.416 -                            // double the array
  96.417 -                            int newSize = (_arr.length - 1) * 2;
  96.418 -                            
  96.419 -                            if (newSize <= 1) {
  96.420 -                                newSize = 2;
  96.421 -                            }
  96.422 -
  96.423 -                            if (newSize > maxSize) {
  96.424 -                                newSize = maxSize;
  96.425 -
  96.426 -                                if (newSize <= _arr.length) {
  96.427 -                                    // no space to get in
  96.428 -                                    throw new UnsupportedOperationException();
  96.429 -                                }
  96.430 -
  96.431 -                                _arr = new Object[newSize];
  96.432 -                            } else {
  96.433 -                                // still a lot of space
  96.434 -                                _arr = new Object[newSize + 1];
  96.435 -                                _arr[newSize] = trashold;
  96.436 -                            }
  96.437 -
  96.438 -                            // copy content of original array without the last Integer into 
  96.439 -                            // the new one
  96.440 -                            System.arraycopy(currentContent, 0, _arr, 0, ((Object[]) currentContent).length - 1);
  96.441 -                        }
  96.442 -                    }
  96.443 -                }
  96.444 -
  96.445 -                this.current = _arr;
  96.446 -                this.arr = null;
  96.447 -            } else {
  96.448 -                // allocate array for complete replacement
  96.449 -                if (ensure == maxSize) {
  96.450 -                    this.arr = new Object[ensure];
  96.451 -                } else {
  96.452 -                    this.arr = new Object[ensure + 1];
  96.453 -                    this.arr[ensure] = trashold;
  96.454 -                }
  96.455 -
  96.456 -                this.current = (currentContent instanceof Object[]) ? (Object[]) currentContent : new Object[0];
  96.457 -            }
  96.458 -        }
  96.459 -
  96.460 -        public int addPair(AbstractLookup.Pair<?> p) {
  96.461 -            p.setIndex(null, cnt);
  96.462 -            arr[cnt++] = p;
  96.463 -
  96.464 -            return p.getIndex();
  96.465 -        }
  96.466 -
  96.467 -        public Object newContent(Object prev) {
  96.468 -            if (arr == null) {
  96.469 -                if (current == null) {
  96.470 -                    return prev;
  96.471 -                } else {
  96.472 -                    return current;
  96.473 -                }
  96.474 -            } else {
  96.475 -                return arr;
  96.476 -            }
  96.477 -        }
  96.478 -    }
  96.479 -     // end of Transaction
  96.480 -}
    97.1 --- a/openide.util/src/org/openide/util/lookup/DelegatingStorage.java	Thu Dec 10 19:23:25 2009 -0500
    97.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.3 @@ -1,180 +0,0 @@
    97.4 -/*
    97.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    97.6 - *
    97.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    97.8 - *
    97.9 - * The contents of this file are subject to the terms of either the GNU
   97.10 - * General Public License Version 2 only ("GPL") or the Common
   97.11 - * Development and Distribution License("CDDL") (collectively, the
   97.12 - * "License"). You may not use this file except in compliance with the
   97.13 - * License. You can obtain a copy of the License at
   97.14 - * http://www.netbeans.org/cddl-gplv2.html
   97.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   97.16 - * specific language governing permissions and limitations under the
   97.17 - * License.  When distributing the software, include this License Header
   97.18 - * Notice in each file and include the License file at
   97.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   97.20 - * particular file as subject to the "Classpath" exception as provided
   97.21 - * by Sun in the GPL Version 2 section of the License file that
   97.22 - * accompanied this code. If applicable, add the following below the
   97.23 - * License Header, with the fields enclosed by brackets [] replaced by
   97.24 - * your own identifying information:
   97.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   97.26 - *
   97.27 - * Contributor(s):
   97.28 - *
   97.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   97.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   97.31 - * Microsystems, Inc. All Rights Reserved.
   97.32 - *
   97.33 - * If you wish your version of this file to be governed by only the CDDL
   97.34 - * or only the GPL Version 2, indicate your decision by adding
   97.35 - * "[Contributor] elects to include this software in this distribution
   97.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   97.37 - * single choice of license, a recipient has the option to distribute
   97.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   97.39 - * to extend the choice of license to its licensees as provided above.
   97.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   97.41 - * Version 2 license, then the option applies only if the new code is
   97.42 - * made subject to such option by the copyright holder.
   97.43 - */
   97.44 -package org.openide.util.lookup;
   97.45 -
   97.46 -import org.openide.util.Lookup;
   97.47 -
   97.48 -import java.io.*;
   97.49 -
   97.50 -import java.lang.ref.WeakReference;
   97.51 -
   97.52 -import java.util.*;
   97.53 -import org.openide.util.lookup.AbstractLookup.Pair;
   97.54 -
   97.55 -
   97.56 -/** Storages that can switch between another storages.
   97.57 - * @author  Jaroslav Tulach
   97.58 - */
   97.59 -final class DelegatingStorage<Transaction> extends Object
   97.60 -implements Serializable, AbstractLookup.Storage<Transaction> {
   97.61 -    /** object to delegate to */
   97.62 -    private AbstractLookup.Storage<Transaction> delegate;
   97.63 -
   97.64 -    /** thread just accessing the storage */
   97.65 -    private Thread owner;
   97.66 -
   97.67 -    public DelegatingStorage(AbstractLookup.Storage<Transaction> d) {
   97.68 -        this.delegate = d;
   97.69 -        this.owner = Thread.currentThread();
   97.70 -    }
   97.71 -
   97.72 -    /** Never serialize yourself, always put there the delegate */
   97.73 -    public Object writeReplace() {
   97.74 -        return this.delegate;
   97.75 -    }
   97.76 -
   97.77 -    /** Method to check whether there is not multiple access from the same thread.
   97.78 -     */
   97.79 -    public void checkForTreeModification() {
   97.80 -        if (Thread.currentThread() == owner) {
   97.81 -            throw new AbstractLookup.ISE("You are trying to modify lookup from lookup query!"); // NOI18N
   97.82 -        }
   97.83 -    }
   97.84 -
   97.85 -    /** Checks whether we have simple behaviour or complex.
   97.86 -     */
   97.87 -    public static boolean isSimple(AbstractLookup.Storage s) {
   97.88 -        if (s instanceof DelegatingStorage) {
   97.89 -            return ((DelegatingStorage) s).delegate instanceof ArrayStorage;
   97.90 -        } else {
   97.91 -            return s instanceof ArrayStorage;
   97.92 -        }
   97.93 -    }
   97.94 -
   97.95 -    /** Exits from the owners ship of the storage.
   97.96 -     */
   97.97 -    public AbstractLookup.Storage<Transaction> exitDelegate() {
   97.98 -        if (Thread.currentThread() != owner) {
   97.99 -            throw new IllegalStateException("Onwer: " + owner + " caller: " + Thread.currentThread()); // NOI18N
  97.100 -        }
  97.101 -
  97.102 -        AbstractLookup.Storage<Transaction> d = delegate;
  97.103 -        delegate = null;
  97.104 -
  97.105 -        return d;
  97.106 -    }
  97.107 -
  97.108 -    public boolean add(AbstractLookup.Pair<?> item, Transaction transaction) {
  97.109 -        return delegate.add(item, transaction);
  97.110 -    }
  97.111 -
  97.112 -    public void remove(org.openide.util.lookup.AbstractLookup.Pair item, Transaction transaction) {
  97.113 -        delegate.remove(item, transaction);
  97.114 -    }
  97.115 -
  97.116 -    public void retainAll(Map retain, Transaction transaction) {
  97.117 -        delegate.retainAll(retain, transaction);
  97.118 -    }
  97.119 -
  97.120 -    /** A special method to change the backing storage.
  97.121 -     * In fact it is not much typesafe as it changes the
  97.122 -     * type of Transaction but we know that nobody is currently
  97.123 -     * holding a transaction object, so there cannot be inconsitencies.
  97.124 -     */
  97.125 -    @SuppressWarnings("unchecked")
  97.126 -    private void changeDelegate(InheritanceTree st) {
  97.127 -        delegate = (AbstractLookup.Storage<Transaction>)st;
  97.128 -    }
  97.129 -
  97.130 -    public Transaction beginTransaction(int ensure) {
  97.131 -        try {
  97.132 -            return delegate.beginTransaction(ensure);
  97.133 -        } catch (UnsupportedOperationException ex) {
  97.134 -            // let's convert to InheritanceTree
  97.135 -            ArrayStorage arr = (ArrayStorage) delegate;
  97.136 -            InheritanceTree inh = new InheritanceTree();
  97.137 -            changeDelegate(inh);
  97.138 -
  97.139 -            //
  97.140 -            // Copy content
  97.141 -            //
  97.142 -            Enumeration<Pair<Object>> en = arr.lookup(Object.class);
  97.143 -
  97.144 -            while (en.hasMoreElements()) {
  97.145 -                if (!inh.add(en.nextElement(), new ArrayList<Class>())) {
  97.146 -                    throw new IllegalStateException("All objects have to be accepted"); // NOI18N
  97.147 -                }
  97.148 -            }
  97.149 -
  97.150 -            //
  97.151 -            // Copy listeners
  97.152 -            //
  97.153 -            AbstractLookup.ReferenceToResult<?> ref = arr.cleanUpResult(null);
  97.154 -
  97.155 -            if (ref != null) {
  97.156 -                ref.cloneList(inh);
  97.157 -            }
  97.158 -
  97.159 -            // we have added the current content and now we can start transaction
  97.160 -            return delegate.beginTransaction(ensure);
  97.161 -        }
  97.162 -    }
  97.163 -
  97.164 -    public org.openide.util.lookup.AbstractLookup.ReferenceToResult cleanUpResult(
  97.165 -        org.openide.util.Lookup.Template templ
  97.166 -    ) {
  97.167 -        return delegate.cleanUpResult(templ);
  97.168 -    }
  97.169 -
  97.170 -    public void endTransaction(Transaction transaction, Set<AbstractLookup.R> modified) {
  97.171 -        delegate.endTransaction(transaction, modified);
  97.172 -    }
  97.173 -
  97.174 -    public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
  97.175 -        return delegate.lookup(clazz);
  97.176 -    }
  97.177 -
  97.178 -    public org.openide.util.lookup.AbstractLookup.ReferenceToResult registerReferenceToResult(
  97.179 -        org.openide.util.lookup.AbstractLookup.ReferenceToResult newRef
  97.180 -    ) {
  97.181 -        return delegate.registerReferenceToResult(newRef);
  97.182 -    }
  97.183 -}
    98.1 --- a/openide.util/src/org/openide/util/lookup/ExcludingLookup.java	Thu Dec 10 19:23:25 2009 -0500
    98.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.3 @@ -1,428 +0,0 @@
    98.4 -/*
    98.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    98.6 - *
    98.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    98.8 - *
    98.9 - * The contents of this file are subject to the terms of either the GNU
   98.10 - * General Public License Version 2 only ("GPL") or the Common
   98.11 - * Development and Distribution License("CDDL") (collectively, the
   98.12 - * "License"). You may not use this file except in compliance with the
   98.13 - * License. You can obtain a copy of the License at
   98.14 - * http://www.netbeans.org/cddl-gplv2.html
   98.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   98.16 - * specific language governing permissions and limitations under the
   98.17 - * License.  When distributing the software, include this License Header
   98.18 - * Notice in each file and include the License file at
   98.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   98.20 - * particular file as subject to the "Classpath" exception as provided
   98.21 - * by Sun in the GPL Version 2 section of the License file that
   98.22 - * accompanied this code. If applicable, add the following below the
   98.23 - * License Header, with the fields enclosed by brackets [] replaced by
   98.24 - * your own identifying information:
   98.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   98.26 - *
   98.27 - * Contributor(s):
   98.28 - *
   98.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   98.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   98.31 - * Microsystems, Inc. All Rights Reserved.
   98.32 - *
   98.33 - * If you wish your version of this file to be governed by only the CDDL
   98.34 - * or only the GPL Version 2, indicate your decision by adding
   98.35 - * "[Contributor] elects to include this software in this distribution
   98.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   98.37 - * single choice of license, a recipient has the option to distribute
   98.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   98.39 - * to extend the choice of license to its licensees as provided above.
   98.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   98.41 - * Version 2 license, then the option applies only if the new code is
   98.42 - * made subject to such option by the copyright holder.
   98.43 - */
   98.44 -package org.openide.util.lookup;
   98.45 -
   98.46 -import java.lang.ref.Reference;
   98.47 -import java.lang.ref.WeakReference;
   98.48 -import org.openide.util.Lookup;
   98.49 -import org.openide.util.LookupListener;
   98.50 -
   98.51 -import java.util.*;
   98.52 -import org.openide.util.LookupEvent;
   98.53 -
   98.54 -
   98.55 -/** Allows exclusion of certain instances from lookup.
   98.56 - *
   98.57 - * @author Jaroslav Tulach
   98.58 - */
   98.59 -final class ExcludingLookup extends org.openide.util.Lookup {
   98.60 -    /** the other lookup that we delegate to */
   98.61 -    private Lookup delegate;
   98.62 -
   98.63 -    /** classes to exclude (Class[]) or just one class (Class) */
   98.64 -    private Object classes;
   98.65 -
   98.66 -    /**
   98.67 -     * Creates new Result object with supplied instances parameter.
   98.68 -     * @param instances to be used to return from the lookup
   98.69 -     */
   98.70 -    ExcludingLookup(Lookup delegate, Class[] classes) {
   98.71 -        this.delegate = delegate;
   98.72 -
   98.73 -        for (Class c : classes) {
   98.74 -            if (c == null) {
   98.75 -                throw new NullPointerException();
   98.76 -            }
   98.77 -        }
   98.78 -        if (classes.length == 1) {
   98.79 -            this.classes = classes[0];
   98.80 -        } else {
   98.81 -            this.classes = classes;
   98.82 -        }
   98.83 -    }
   98.84 -
   98.85 -    @Override
   98.86 -    public String toString() {
   98.87 -        return "ExcludingLookup: " + delegate + " excludes: " + Arrays.asList(classes()); // NOI18N
   98.88 -    }
   98.89 -
   98.90 -    public <T> Result<T> lookup(Template<T> template) {
   98.91 -        if (template == null) {
   98.92 -            throw new NullPointerException();
   98.93 -        }
   98.94 -
   98.95 -        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
   98.96 -            // empty result
   98.97 -            return Lookup.EMPTY.lookup(template);
   98.98 -        }
   98.99 -
  98.100 -        return new R<T>(template.getType(), delegate.lookup(template));
  98.101 -    }
  98.102 -
  98.103 -    public <T> T lookup(Class<T> clazz) {
  98.104 -        if (areSubclassesOfThisClassAlwaysExcluded(clazz)) {
  98.105 -            return null;
  98.106 -        }
  98.107 -
  98.108 -        T res = delegate.lookup(clazz);
  98.109 -
  98.110 -        if (isObjectAccessible(clazz, res, 0)) {
  98.111 -            return res;
  98.112 -        } else {
  98.113 -            return null;
  98.114 -        }
  98.115 -    }
  98.116 -
  98.117 -    @Override
  98.118 -    public <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
  98.119 -        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
  98.120 -            return null;
  98.121 -        }
  98.122 -
  98.123 -        Lookup.Item<T> retValue = delegate.lookupItem(template);
  98.124 -
  98.125 -        if (isObjectAccessible(template.getType(), retValue, 2)) {
  98.126 -            return retValue;
  98.127 -        } else {
  98.128 -            return null;
  98.129 -        }
  98.130 -    }
  98.131 -
  98.132 -    /** @return true if the instance of class c shall never be returned from this lookup
  98.133 -     */
  98.134 -    private boolean areSubclassesOfThisClassAlwaysExcluded(Class<?> c) {
  98.135 -        Class<?>[] arr = classes();
  98.136 -
  98.137 -        for (int i = 0; i < arr.length; i++) {
  98.138 -            if (arr[i].isAssignableFrom(c)) {
  98.139 -                return true;
  98.140 -            }
  98.141 -        }
  98.142 -
  98.143 -        return false;
  98.144 -    }
  98.145 -
  98.146 -    /** Returns the array of classes this lookup filters.
  98.147 -     */
  98.148 -    final Class<?>[] classes() {
  98.149 -        if (classes instanceof Class[]) {
  98.150 -            return (Class[]) classes;
  98.151 -        } else {
  98.152 -            return new Class[] { (Class) classes };
  98.153 -        }
  98.154 -    }
  98.155 -
  98.156 -    /** Does a check whether two classes are accessible (in the super/sub class)
  98.157 -     * releation ship without walking thru any of the classes mentioned in the
  98.158 -     * barrier.
  98.159 -     */
  98.160 -    private static boolean isAccessible(Class<?>[] barriers, Class<?> from, Class<?> to) {
  98.161 -        if ((to == null) || !from.isAssignableFrom(to)) {
  98.162 -            // no way to reach each other by walking up
  98.163 -            return false;
  98.164 -        }
  98.165 -
  98.166 -        for (int i = 0; i < barriers.length; i++) {
  98.167 -            if (to == barriers[i]) {
  98.168 -                return false;
  98.169 -            }
  98.170 -        }
  98.171 -
  98.172 -        if (from == to) {
  98.173 -            return true;
  98.174 -        }
  98.175 -
  98.176 -        //
  98.177 -        // depth first search
  98.178 -        //
  98.179 -        if (isAccessible(barriers, from, to.getSuperclass())) {
  98.180 -            return true;
  98.181 -        }
  98.182 -
  98.183 -        Class[] interfaces = to.getInterfaces();
  98.184 -
  98.185 -        for (int i = 0; i < interfaces.length; i++) {
  98.186 -            if (isAccessible(barriers, from, interfaces[i])) {
  98.187 -                return true;
  98.188 -            }
  98.189 -        }
  98.190 -
  98.191 -        return false;
  98.192 -    }
  98.193 -
  98.194 -    /** based on type decides whether the class accepts or not anObject
  98.195 -     * @param from the base type of the query
  98.196 -     * @param to depending on value of type either Object, Class or Item
  98.197 -     * @param type 0,1,2 for Object, Class or Item
  98.198 -     * @return true if we can access the to from from by walking around the bariers
  98.199 -     */
  98.200 -    private final boolean isObjectAccessible(Class from, Object to, int type) {
  98.201 -        if (to == null) {
  98.202 -            return false;
  98.203 -        }
  98.204 -
  98.205 -        return isObjectAccessible(classes(), from, to, type);
  98.206 -    }
  98.207 -
  98.208 -    /** based on type decides whether the class accepts or not anObject
  98.209 -     * @param barriers classes to avoid when testing reachability
  98.210 -     * @param from the base type of the query
  98.211 -     * @param to depending on value of type either Object, Class or Item
  98.212 -     * @param type 0,1,2 for Object, Class or Item
  98.213 -     * @return true if we can access the to from from by walking around the bariers
  98.214 -     */
  98.215 -    static final boolean isObjectAccessible(Class[] barriers, Class from, Object to, int type) {
  98.216 -        if (to == null) {
  98.217 -            return false;
  98.218 -        }
  98.219 -
  98.220 -        switch (type) {
  98.221 -        case 0:
  98.222 -            return isAccessible(barriers, from, to.getClass());
  98.223 -
  98.224 -        case 1:
  98.225 -            return isAccessible(barriers, from, (Class) to);
  98.226 -
  98.227 -        case 2: {
  98.228 -            Item item = (Item) to;
  98.229 -
  98.230 -            return isAccessible(barriers, from, item.getType());
  98.231 -        }
  98.232 -
  98.233 -        default:
  98.234 -            throw new IllegalStateException("Type: " + type);
  98.235 -        }
  98.236 -    }
  98.237 -
  98.238 -    /** Filters collection accroding to set of given filters.
  98.239 -     */
  98.240 -    final <E, T extends Collection<E>> T filter(
  98.241 -        Class<?>[] arr, Class<?> from, T c, int type, T prototype
  98.242 -    ) {
  98.243 -        T ret = null;
  98.244 -
  98.245 -
  98.246 -// optimistic strategy expecting we will not need to filter
  98.247 -TWICE: 
  98.248 -        for (;;) {
  98.249 -            Iterator<E> it = c.iterator();
  98.250 -BIG: 
  98.251 -            while (it.hasNext()) {
  98.252 -                E res = it.next();
  98.253 -
  98.254 -                if (!isObjectAccessible(arr, from, res, type)) {
  98.255 -                    if (ret == null) {
  98.256 -                        // we need to restart the scanning again 
  98.257 -                        // as there is an active filter
  98.258 -                        ret = prototype;
  98.259 -                        continue TWICE;
  98.260 -                    }
  98.261 -
  98.262 -                    continue BIG;
  98.263 -                }
  98.264 -
  98.265 -                if (ret != null) {
  98.266 -                    // if we are running the second round from TWICE
  98.267 -                    ret.add(res);
  98.268 -                }
  98.269 -            }
  98.270 -
  98.271 -            // ok, processed
  98.272 -            break TWICE;
  98.273 -        }
  98.274 -
  98.275 -        return (ret != null) ? ret : c;
  98.276 -    }
  98.277 -
  98.278 -    /** Delegating result that filters unwanted items and instances.
  98.279 -     */
  98.280 -    private final class R<T> extends WaitableResult<T> implements LookupListener {
  98.281 -        private Result<T> result;
  98.282 -        private WeakResult<T> weak;
  98.283 -        private Object listeners;
  98.284 -        private Class<?> from;
  98.285 -
  98.286 -        R(Class<?> from, Result<T> delegate) {
  98.287 -            this.from = from;
  98.288 -            this.result = delegate;
  98.289 -            this.weak = new WeakResult<T>(this, delegate);
  98.290 -        }
  98.291 -
  98.292 -        protected void beforeLookup(Template t) {
  98.293 -            if (result instanceof WaitableResult) {
  98.294 -                ((WaitableResult) result).beforeLookup(t);
  98.295 -            }
  98.296 -        }
  98.297 -
  98.298 -        public void addLookupListener(LookupListener l) {
  98.299 -            boolean add;
  98.300 -
  98.301 -            synchronized (this) {
  98.302 -                listeners = AbstractLookup.modifyListenerList(true, l, listeners);
  98.303 -                add = listeners != null;
  98.304 -            }
  98.305 -
  98.306 -            if (add) {
  98.307 -                result.addLookupListener(weak);
  98.308 -            }
  98.309 -        }
  98.310 -
  98.311 -        public void removeLookupListener(LookupListener l) {
  98.312 -            boolean remove;
  98.313 -
  98.314 -            synchronized (this) {
  98.315 -                listeners = AbstractLookup.modifyListenerList(false, l, listeners);
  98.316 -                remove = listeners == null;
  98.317 -            }
  98.318 -
  98.319 -            if (remove) {
  98.320 -                result.removeLookupListener(weak);
  98.321 -            }
  98.322 -        }
  98.323 -
  98.324 -        public Collection<? extends T> allInstances() {
  98.325 -            return openCol(result.allInstances(), 0);
  98.326 -        }
  98.327 -
  98.328 -        private <S> Collection<S> openCol(Collection<S> c, int type) {
  98.329 -            return filter(classes(), from, c, type, new ArrayList<S>(c.size()));
  98.330 -        }
  98.331 -
  98.332 -        @Override
  98.333 -        public Set<Class<? extends T>> allClasses() {
  98.334 -            return filter(classes(), from, result.allClasses(), 1, new HashSet<Class<? extends T>>());
  98.335 -        }
  98.336 -
  98.337 -        @Override
  98.338 -        public Collection<? extends Item<T>> allItems() {
  98.339 -            return openCol(result.allItems(), 2);
  98.340 -        }
  98.341 -
  98.342 -        public void resultChanged(org.openide.util.LookupEvent ev) {
  98.343 -            if (ev.getSource() == result) {
  98.344 -                collectFires(null);
  98.345 -            }
  98.346 -        }
  98.347 -
  98.348 -        protected void collectFires(Collection<Object> evAndListeners) {
  98.349 -            LookupListener[] arr;
  98.350 -
  98.351 -            synchronized (this) {
  98.352 -                if (listeners == null) {
  98.353 -                    return;
  98.354 -                }
  98.355 -
  98.356 -                if (listeners instanceof LookupListener) {
  98.357 -                    arr = new LookupListener[] { (LookupListener) listeners };
  98.358 -                } else {
  98.359 -                    ArrayList<?> l = (ArrayList<?>) listeners;
  98.360 -                    arr = l.toArray(new LookupListener[l.size()]);
  98.361 -                }
  98.362 -            }
  98.363 -
  98.364 -            final LookupListener[] ll = arr;
  98.365 -            final org.openide.util.LookupEvent newev = new org.openide.util.LookupEvent(this);
  98.366 -            AbstractLookup.notifyListeners(ll, newev, evAndListeners);
  98.367 -        }
  98.368 -    } // end of R
  98.369 -    
  98.370 -    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
  98.371 -        private Lookup.Result source;
  98.372 -        private Reference<R<T>> result;
  98.373 -        
  98.374 -        public WeakResult(R<T> r, Lookup.Result<T> s) {
  98.375 -            this.result = new WeakReference<R<T>>(r);
  98.376 -            this.source = s;
  98.377 -        }
  98.378 -        
  98.379 -        protected void beforeLookup(Lookup.Template t) {
  98.380 -            R r = (R)result.get();
  98.381 -            if (r != null) {
  98.382 -                r.beforeLookup(t);
  98.383 -            } else {
  98.384 -                source.removeLookupListener(this);
  98.385 -            }
  98.386 -        }
  98.387 -
  98.388 -        protected void collectFires(Collection<Object> evAndListeners) {
  98.389 -            R<T> r = result.get();
  98.390 -            if (r != null) {
  98.391 -                r.collectFires(evAndListeners);
  98.392 -            } else {
  98.393 -                source.removeLookupListener(this);
  98.394 -            }
  98.395 -        }
  98.396 -
  98.397 -        public void addLookupListener(LookupListener l) {
  98.398 -            assert false;
  98.399 -        }
  98.400 -
  98.401 -        public void removeLookupListener(LookupListener l) {
  98.402 -            assert false;
  98.403 -        }
  98.404 -
  98.405 -        public Collection<T> allInstances() {
  98.406 -            assert false;
  98.407 -            return null;
  98.408 -        }
  98.409 -
  98.410 -        public void resultChanged(LookupEvent ev) {
  98.411 -            R r = (R)result.get();
  98.412 -            if (r != null) {
  98.413 -                r.resultChanged(ev);
  98.414 -            } else {
  98.415 -                source.removeLookupListener(this);
  98.416 -            }
  98.417 -        }
  98.418 -
  98.419 -        @Override
  98.420 -        public Collection<? extends Item<T>> allItems() {
  98.421 -            assert false;
  98.422 -            return null;
  98.423 -        }
  98.424 -
  98.425 -        @Override
  98.426 -        public Set<Class<? extends T>> allClasses() {
  98.427 -            assert false;
  98.428 -            return null;
  98.429 -        }
  98.430 -    } // end of WeakResult
  98.431 -}
    99.1 --- a/openide.util/src/org/openide/util/lookup/InheritanceTree.java	Thu Dec 10 19:23:25 2009 -0500
    99.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.3 @@ -1,1276 +0,0 @@
    99.4 -/*
    99.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    99.6 - *
    99.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    99.8 - *
    99.9 - * The contents of this file are subject to the terms of either the GNU
   99.10 - * General Public License Version 2 only ("GPL") or the Common
   99.11 - * Development and Distribution License("CDDL") (collectively, the
   99.12 - * "License"). You may not use this file except in compliance with the
   99.13 - * License. You can obtain a copy of the License at
   99.14 - * http://www.netbeans.org/cddl-gplv2.html
   99.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   99.16 - * specific language governing permissions and limitations under the
   99.17 - * License.  When distributing the software, include this License Header
   99.18 - * Notice in each file and include the License file at
   99.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   99.20 - * particular file as subject to the "Classpath" exception as provided
   99.21 - * by Sun in the GPL Version 2 section of the License file that
   99.22 - * accompanied this code. If applicable, add the following below the
   99.23 - * License Header, with the fields enclosed by brackets [] replaced by
   99.24 - * your own identifying information:
   99.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   99.26 - *
   99.27 - * Contributor(s):
   99.28 - *
   99.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   99.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   99.31 - * Microsystems, Inc. All Rights Reserved.
   99.32 - *
   99.33 - * If you wish your version of this file to be governed by only the CDDL
   99.34 - * or only the GPL Version 2, indicate your decision by adding
   99.35 - * "[Contributor] elects to include this software in this distribution
   99.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   99.37 - * single choice of license, a recipient has the option to distribute
   99.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   99.39 - * to extend the choice of license to its licensees as provided above.
   99.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   99.41 - * Version 2 license, then the option applies only if the new code is
   99.42 - * made subject to such option by the copyright holder.
   99.43 - */
   99.44 -package org.openide.util.lookup;
   99.45 -
   99.46 -import org.openide.util.Lookup;
   99.47 -import org.openide.util.lookup.AbstractLookup.Pair;
   99.48 -import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
   99.49 -import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
   99.50 -
   99.51 -import java.io.*;
   99.52 -
   99.53 -import java.lang.ref.WeakReference;
   99.54 -
   99.55 -import java.util.*;
   99.56 -
   99.57 -
   99.58 -/** A tree to represent classes with inheritance. Description of the
   99.59 - * data structure by Petr Nejedly:
   99.60 - * <P>
   99.61 - * So pretend I'm Lookup implementation. I've got a bunch of Items (e.g.
   99.62 - * setPairs() method),
   99.63 - * didn't do anything on them yet (no startup penalty) so I know nothing
   99.64 - * about them.
   99.65 - * Then I'll be asked for all instances implementing given interface or a
   99.66 - * class. I surely need
   99.67 - * to check all the Items now, as I don't know anything abou them. I surely
   99.68 - * don't want to call
   99.69 - * Item.getClass() as it will dismiss the whole effort. So all I have is
   99.70 - * Item.instanceOf()
   99.71 - * and I'll call it on every Item. I'll cache results, so the next time
   99.72 - * you'll ask me for
   99.73 - * the same interface/class, I'll answer immediatelly. But what if you ask
   99.74 - * me for another
   99.75 - * interface/class? I'll have to scan all Items for it again, unless I can
   99.76 - * be sure some
   99.77 - * of them can't implement it. The only source of this knowledge are the
   99.78 - * previous questions
   99.79 - * and my rulings on them. Here the algorithm have to be split into two
   99.80 - * paths. If you
   99.81 - * previously asked me for interfaces only, I'll have no hint for
   99.82 - * subsequent queries,
   99.83 - * but if you asked me for a class in history, and then for another class
   99.84 - * and these classes
   99.85 - * are not in inheritance relation (I can check hierarchy of lookup
   99.86 - * arguments, because
   99.87 - * they are already resolved/loaded) I can tell that those returned in
   99.88 - * previous query can't
   99.89 - * implement the newly asked class (they are in different hierarchy branch)
   99.90 - * and I need to
   99.91 - * ask less Items.
   99.92 - * <P>
   99.93 - * So if we use mostly classes for asking for services (and it is a trend
   99.94 - * to use
   99.95 - * abstract classes for this purpose in IDE anyway), this could be usable.
   99.96 - * <P>
   99.97 - * The data structure for separating the Items based on previous queries is
   99.98 - * simple
   99.99 - * tree, with every node tagged with one class. The tree's root is,
  99.100 - * naturally,
  99.101 - * java.lang.Object, is marked invited and initially contains all the
  99.102 - * Items.
  99.103 - * For every class query, the missing part of class hierarchy tree is
  99.104 - * created,
  99.105 - * the node of the class looked up is marked as invited and all Items from
  99.106 - * nearest
  99.107 - * invited parent (sperclass) are dragged to this node. The result are then
  99.108 - * all
  99.109 - * Items from this node and all the nodes deeper in hierarchy. Because it
  99.110 - * may
  99.111 - * be too complicated to walk through the children nodes, the results could
  99.112 - * be
  99.113 - * cached in the map.
  99.114 - * For interface lookup, there is a little hint in reality (interfaces
  99.115 - * and superinterfaces), but it would be harder to exploit it, so we could
  99.116 - * fall-back
  99.117 - * to walking through all the Items and cache results.
  99.118 - *
  99.119 - *
  99.120 - * @author  Jaroslav Tulach
  99.121 - */
  99.122 -final class InheritanceTree extends Object
  99.123 -implements Serializable, AbstractLookup.Storage<ArrayList<Class>> {
  99.124 -    private static final long serialVersionUID = 1L;
  99.125 -
  99.126 -    /** the root item (represents Object) */
  99.127 -    private transient Node object;
  99.128 -
  99.129 -    /** Map of queried interfaces.
  99.130 -     * <p>Type: <code>Map&lt;Class, (Collection&lt;AbstractLookup.Pair&gt; | AbstractLookup.Pair)&gt;</code>
  99.131 -     */
  99.132 -    private transient Map<Class,Object> interfaces;
  99.133 -
  99.134 -    /** Map (Class, ReferenceToResult) of all listeners that are waiting in
  99.135 -     * changes in class Class
  99.136 -     */
  99.137 -    private transient Map<Class,ReferenceToResult> reg;
  99.138 -
  99.139 -    /** Constructor
  99.140 -     */
  99.141 -    public InheritanceTree() {
  99.142 -        object = new Node(java.lang.Object.class);
  99.143 -    }
  99.144 -
  99.145 -    private void writeObject(ObjectOutputStream oos) throws IOException {
  99.146 -        oos.writeObject(object);
  99.147 -
  99.148 -        if (interfaces != null) {
  99.149 -            Iterator it = interfaces.entrySet().iterator();
  99.150 -
  99.151 -            while (it.hasNext()) {
  99.152 -                Map.Entry e = (Map.Entry) it.next();
  99.153 -                Class c = (Class) e.getKey();
  99.154 -                oos.writeObject(c.getName());
  99.155 -
  99.156 -                Object o = e.getValue();
  99.157 -
  99.158 -                if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
  99.159 -                    throw new ClassCastException(String.valueOf(o));
  99.160 -                }
  99.161 -
  99.162 -                oos.writeObject(o);
  99.163 -            }
  99.164 -        }
  99.165 -
  99.166 -        oos.writeObject(null);
  99.167 -    }
  99.168 -
  99.169 -    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
  99.170 -        object = (Node) ois.readObject();
  99.171 -        interfaces = new WeakHashMap<Class,Object>();
  99.172 -
  99.173 -        String clazz;
  99.174 -        ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
  99.175 -
  99.176 -        while ((clazz = (String) ois.readObject()) != null) {
  99.177 -            Object o = ois.readObject();
  99.178 -
  99.179 -            if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
  99.180 -                throw new ClassCastException(String.valueOf(o));
  99.181 -            }
  99.182 -
  99.183 -            Class c = Class.forName(clazz, false, l);
  99.184 -            interfaces.put(c, o);
  99.185 -        }
  99.186 -    }
  99.187 -
  99.188 -    /** Adds an item into the tree.
  99.189 -    * @param item to add
  99.190 -    * @return true if the Item has been added for the first time or false if some other
  99.191 -    *    item equal to this one already existed in the lookup
  99.192 -    */
  99.193 -    public boolean add(AbstractLookup.Pair<?> item, ArrayList<Class> affected) {
  99.194 -        Node node = registerClass(object, item);
  99.195 -
  99.196 -        affected.add(node.getType());
  99.197 -
  99.198 -        if (node.assignItem(this, item)) {
  99.199 -            // this is the first item added to n.items
  99.200 -            // ok, we have to test interfaces too
  99.201 -        } else {
  99.202 -            // equal item is already there => stop processing
  99.203 -            return false;
  99.204 -        }
  99.205 -
  99.206 -        boolean registeredAsInterface = registerInterface(item, affected);
  99.207 -
  99.208 -        return registeredAsInterface;
  99.209 -    }
  99.210 -
  99.211 -    /** Removes an item.
  99.212 -    */
  99.213 -    public void remove(AbstractLookup.Pair item, ArrayList<Class> affected) {
  99.214 -        Node n = removeClass(object, item);
  99.215 -
  99.216 -        if (n != null) {
  99.217 -            affected.add(n.getType());
  99.218 -        }
  99.219 -
  99.220 -        removeInterface(item, affected);
  99.221 -    }
  99.222 -
  99.223 -    /** Removes all items that are not present in the provided collection.
  99.224 -    * @param retain collection of Pairs to keep them in
  99.225 -    * @param notify set of Classes that has possibly changed
  99.226 -    */
  99.227 -    public void retainAll(Map retain, ArrayList<Class> notify) {
  99.228 -        retainAllInterface(retain, notify);
  99.229 -        retainAllClasses(object, retain, notify);
  99.230 -    }
  99.231 -
  99.232 -    /** Queries for instances of given class.
  99.233 -    * @param clazz the class to check
  99.234 -    * @return enumeration of Item
  99.235 -    * @see #unsorted
  99.236 -    */
  99.237 -    @SuppressWarnings("unchecked")
  99.238 -    public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
  99.239 -        if ((clazz != null) && clazz.isInterface()) {
  99.240 -            return (Enumeration)searchInterface(clazz);
  99.241 -        } else {
  99.242 -            return (Enumeration)searchClass(object, clazz);
  99.243 -        }
  99.244 -    }
  99.245 -
  99.246 -    /** A method to check whether the enumeration returned from
  99.247 -     * lookup method is sorted or is not
  99.248 -     * @param en enumeration to check
  99.249 -     * @return true if it is unsorted and needs to be sorted to find
  99.250 -     *   pair with smallest index
  99.251 -     */
  99.252 -    public static boolean unsorted(Enumeration en) {
  99.253 -        return en instanceof NeedsSortEnum;
  99.254 -    }
  99.255 -
  99.256 -    /** Prints debug messages.
  99.257 -     * @param out stream to output to
  99.258 -     * @param instances print also instances of the
  99.259 -     */
  99.260 -    public void print(java.io.PrintStream out, boolean instances) {
  99.261 -        printNode(object, "", out, instances); // NOI18N
  99.262 -    }
  99.263 -
  99.264 -    //
  99.265 -    // methods to work on classes which are not interfaces
  99.266 -    //
  99.267 -
  99.268 -    /** Searches the subtree and register the item where necessary.
  99.269 -    * @return the node that should contain the item
  99.270 -    */
  99.271 -    private static Node registerClass(Node n, AbstractLookup.Pair item) {
  99.272 -        if (!n.accepts(item)) {
  99.273 -            return null;
  99.274 -        }
  99.275 -
  99.276 -        if (n.children != null) {
  99.277 -            Iterator it = n.children.iterator();
  99.278 -
  99.279 -            for (;;) {
  99.280 -                Node ch = extractNode(it);
  99.281 -
  99.282 -                if (ch == null) {
  99.283 -                    break;
  99.284 -                }
  99.285 -
  99.286 -                Node result = registerClass(ch, item);
  99.287 -
  99.288 -                if (result != null) {
  99.289 -                    // it is in subclass, in case of classes, it cannot
  99.290 -                    // be any other class
  99.291 -                    return result;
  99.292 -                }
  99.293 -            }
  99.294 -        }
  99.295 -
  99.296 -        // ok, nobody of our subclasses wants the class, I'll take it
  99.297 -        return n;
  99.298 -    }
  99.299 -
  99.300 -    /** Removes the item from the tree of objects.
  99.301 -    * @return most narrow class that this item was removed from
  99.302 -    */
  99.303 -    private static Node removeClass(Node n, AbstractLookup.Pair item) {
  99.304 -        if (!n.accepts(item)) {
  99.305 -            return null;
  99.306 -        }
  99.307 -
  99.308 -        if ((n.items != null) && n.items.remove(item)) {
  99.309 -            // this node really contains the item
  99.310 -            return n;
  99.311 -        }
  99.312 -
  99.313 -        if (n.children != null) {
  99.314 -            Iterator it = n.children.iterator();
  99.315 -
  99.316 -            for (;;) {
  99.317 -                Node ch = extractNode(it);
  99.318 -
  99.319 -                if (ch == null) {
  99.320 -                    break;
  99.321 -                }
  99.322 -
  99.323 -                Node result = removeClass(ch, item);
  99.324 -
  99.325 -                // If the children node was emptied, remove it if possible.
  99.326 -                if (((ch.items == null) || ch.items.isEmpty()) && ((ch.children == null) || ch.children.isEmpty())) {
  99.327 -                    it.remove();
  99.328 -                }
  99.329 -
  99.330 -                if (result != null) {
  99.331 -                    // it is in subclass, in case of classes, it cannot
  99.332 -                    // be any other class
  99.333 -                    return result;
  99.334 -                }
  99.335 -            }
  99.336 -        }
  99.337 -
  99.338 -        // nobody found
  99.339 -        return null;
  99.340 -    }
  99.341 -
  99.342 -    /** Finds a node that represents a class.
  99.343 -    * @param n node to search from
  99.344 -    * @param clazz the clazz to find
  99.345 -    * @return node that represents clazz in the tree or null if the clazz is not
  99.346 -    *    represented under the node n
  99.347 -    */
  99.348 -    private Node classToNode(final Node n, final Class<?> clazz) {
  99.349 -        if (!n.accepts(clazz)) {
  99.350 -            // nothing from us
  99.351 -            return null;
  99.352 -        }
  99.353 -
  99.354 -        if (n.getType() == clazz) {
  99.355 -            // we have found what we need
  99.356 -            return n;
  99.357 -        }
  99.358 -
  99.359 -        if (n.children != null) {
  99.360 -            // have to proceed to children
  99.361 -            Iterator it = n.children.iterator();
  99.362 -
  99.363 -            for (;;) {
  99.364 -                final Node ch = extractNode(it);
  99.365 -
  99.366 -                if (ch == null) {
  99.367 -                    break;
  99.368 -                }
  99.369 -
  99.370 -                Node found = classToNode(ch, clazz);
  99.371 -
  99.372 -                if ((found != null) && ch.deserialized()) {
  99.373 -                    class VerifyJob implements AbstractLookup.ISE.Job {
  99.374 -                        private AbstractLookup.Pair<?>[] pairs;
  99.375 -                        private boolean[] answers;
  99.376 -
  99.377 -                        public VerifyJob(Collection<Pair> items) {
  99.378 -                            if (items != null) {
  99.379 -                                pairs = items.toArray(new AbstractLookup.Pair[0]);
  99.380 -                            }
  99.381 -                        }
  99.382 -
  99.383 -                        public void before() {
  99.384 -                            // make sure the node is converted into deserialized state
  99.385 -                            ch.deserialized();
  99.386 -
  99.387 -                            if (pairs != null) {
  99.388 -                                answers = new boolean[pairs.length];
  99.389 -
  99.390 -                                for (int i = 0; i < pairs.length; i++) {
  99.391 -                                    answers[i] = pairs[i].instanceOf(clazz);
  99.392 -                                }
  99.393 -                            }
  99.394 -                        }
  99.395 -
  99.396 -                        public void inside() {
  99.397 -                            if (pairs != null) {
  99.398 -                                for (int i = 0; i < pairs.length; i++) {
  99.399 -                                    if (answers[i]) {
  99.400 -                                        ch.assignItem(InheritanceTree.this, pairs[i]);
  99.401 -                                        n.items.remove(pairs[i]);
  99.402 -                                    }
  99.403 -                                }
  99.404 -                            }
  99.405 -
  99.406 -                            if (n.children != null) {
  99.407 -                                // consolidate all nodes that represent the same class
  99.408 -                                HashMap<Class,Node> nodes = new HashMap<Class,Node>(n.children.size() * 3);
  99.409 -
  99.410 -                                Iterator child = n.children.iterator();
  99.411 -
  99.412 -                                while (child.hasNext()) {
  99.413 -                                    Node node = extractNode(child);
  99.414 -                                    if (node == null) {
  99.415 -                                        continue;
  99.416 -                                    }
  99.417 -                                    Node prev = nodes.put(node.getType(), node);
  99.418 -
  99.419 -                                    if (prev != null) {
  99.420 -                                        child.remove();
  99.421 -                                        nodes.put(node.getType(), prev);
  99.422 -
  99.423 -                                        // mark as being deserialized
  99.424 -                                        prev.markDeserialized();
  99.425 -
  99.426 -                                        if (prev.children == null) {
  99.427 -                                            prev.children = node.children;
  99.428 -                                        } else {
  99.429 -                                            if (node.children != null) {
  99.430 -                                                prev.children.addAll(node.children);
  99.431 -                                            }
  99.432 -                                        }
  99.433 -
  99.434 -                                        if (node.items != null) {
  99.435 -                                            Iterator items = node.items.iterator();
  99.436 -
  99.437 -                                            while (items.hasNext()) {
  99.438 -                                                AbstractLookup.Pair item = (AbstractLookup.Pair) items.next();
  99.439 -                                                prev.assignItem(InheritanceTree.this, item);
  99.440 -                                            }
  99.441 -                                        }
  99.442 -                                    }
  99.443 -                                }
  99.444 -                            }
  99.445 -                        }
  99.446 -                    }
  99.447 -
  99.448 -                    VerifyJob verify = new VerifyJob(n.items);
  99.449 -
  99.450 -                    try {
  99.451 -                        verify.before();
  99.452 -                    } catch (AbstractLookup.ISE ex) {
  99.453 -                        // mark deserialized again
  99.454 -                        ch.markDeserialized();
  99.455 -                        ex.registerJob(verify);
  99.456 -                        throw ex;
  99.457 -                    }
  99.458 -
  99.459 -                    verify.inside();
  99.460 -
  99.461 -                    found = classToNode(ch, clazz);
  99.462 -                }
  99.463 -
  99.464 -                if (found != null) {
  99.465 -                    // class found in one of subnodes
  99.466 -                    return found;
  99.467 -                }
  99.468 -            }
  99.469 -        }
  99.470 -
  99.471 -        class TwoJobs implements AbstractLookup.ISE.Job {
  99.472 -            private AbstractLookup.Pair[] pairs;
  99.473 -            private boolean[] answers;
  99.474 -            private Node newNode;
  99.475 -
  99.476 -            public void before() {
  99.477 -                // have to create new subnode and possibly reparent one of my own
  99.478 -                // but all changes can be done only if we will not be interrupted from
  99.479 -                // outside - e.g. instanceOf methods will not throw exception
  99.480 -                // first of all let's compute the answers to method instanceOf
  99.481 -                AbstractLookup.Pair[] arr = null;
  99.482 -                boolean[] boolArr = null;
  99.483 -
  99.484 -                if (n.items != null) {
  99.485 -                    arr = new AbstractLookup.Pair[n.items.size()];
  99.486 -                    boolArr = new boolean[n.items.size()];
  99.487 -
  99.488 -                    int i = 0;
  99.489 -                    Iterator<Pair> it = n.items.iterator();
  99.490 -
  99.491 -                    while (it.hasNext()) {
  99.492 -                        AbstractLookup.Pair<?> item = it.next();
  99.493 -                        arr[i] = item;
  99.494 -                        boolArr[i] = item.instanceOf(clazz);
  99.495 -                        i++;
  99.496 -                    }
  99.497 -                }
  99.498 -
  99.499 -                pairs = arr;
  99.500 -                answers = boolArr;
  99.501 -            }
  99.502 -
  99.503 -            public void inside() {
  99.504 -                // test if the query has not chagned since
  99.505 -                if (pairs != null) {
  99.506 -                    if (!Arrays.equals(n.items.toArray(), pairs)) {
  99.507 -                        // ok, let try once more
  99.508 -                        return;
  99.509 -                    }
  99.510 -                }
  99.511 -
  99.512 -                internal();
  99.513 -            }
  99.514 -
  99.515 -            public void internal() {
  99.516 -                ArrayList<Node> reparent = null;
  99.517 -
  99.518 -                if (n.children == null) {
  99.519 -                    n.children = new ArrayList<Node>();
  99.520 -                } else {
  99.521 -                    // scan thru all my nodes if some of them are not a subclass
  99.522 -                    // of clazz => then they would need to become child of newNode
  99.523 -                    Iterator it = n.children.iterator();
  99.524 -
  99.525 -                    for (;;) {
  99.526 -                        Node r = extractNode(it);
  99.527 -
  99.528 -                        if (r == null) {
  99.529 -                            break;
  99.530 -                        }
  99.531 -
  99.532 -                        if (clazz.isAssignableFrom(r.getType())) {
  99.533 -                            if (reparent == null) {
  99.534 -                                reparent = new ArrayList<Node>();
  99.535 -                            }
  99.536 -
  99.537 -                            reparent.add(r);
  99.538 -                            it.remove();
  99.539 -                        }
  99.540 -                    }
  99.541 -                }
  99.542 -
  99.543 -                newNode = new Node(clazz);
  99.544 -                n.children.add(newNode);
  99.545 -
  99.546 -                if (reparent != null) {
  99.547 -                    // reassing reparent node as a child of newNode
  99.548 -                    newNode.children = reparent;
  99.549 -                }
  99.550 -
  99.551 -                // now take all my items that are instances of that class and
  99.552 -                // reasign them
  99.553 -                if (n.items != null) {
  99.554 -                    Iterator it = n.items.iterator();
  99.555 -                    int i = 0;
  99.556 -
  99.557 -                    while (it.hasNext()) {
  99.558 -                        AbstractLookup.Pair item = (AbstractLookup.Pair) it.next();
  99.559 -
  99.560 -                        if (answers[i]) { // answers[i] is precomputed value of item.instanceOf (clazz))
  99.561 -                            it.remove();
  99.562 -                            newNode.assignItem(InheritanceTree.this, pairs[i]);
  99.563 -                        }
  99.564 -
  99.565 -                        i++;
  99.566 -                    }
  99.567 -                }
  99.568 -            }
  99.569 -        }
  99.570 -
  99.571 -        TwoJobs j = new TwoJobs();
  99.572 -
  99.573 -        try {
  99.574 -            j.before();
  99.575 -        } catch (AbstractLookup.ISE ex) {
  99.576 -            // ok, it is not possible to call instanceOf now, let's 
  99.577 -            // schedule it for later
  99.578 -            // so register recovery job 
  99.579 -            ex.registerJob(j);
  99.580 -            throw ex;
  99.581 -        }
  99.582 -
  99.583 -        j.internal();
  99.584 -
  99.585 -        // newNode represents my clazz
  99.586 -        return j.newNode;
  99.587 -    }
  99.588 -
  99.589 -    /** Search for a requested class.
  99.590 -    * @return enumeration of Pair
  99.591 -    */
  99.592 -    private Enumeration<Pair> searchClass(Node n, Class<?> clazz) {
  99.593 -        if (clazz != null) {
  99.594 -            n = classToNode(n, clazz);
  99.595 -        }
  99.596 -
  99.597 -        if (n == null) {
  99.598 -            // not for us
  99.599 -            return emptyEn();
  99.600 -        } else {
  99.601 -            return nodeToEnum(n);
  99.602 -        }
  99.603 -    }
  99.604 -
  99.605 -    /** Retains all classes. Removes nodes which items and children are emptied, works
  99.606 -     * recursivelly from specified root node.
  99.607 -     * @param node root node from which to start to process the tree
  99.608 -     * @param retain a map from (Item, AbstractLookup.Info) that describes which items to retain
  99.609 -     *    and witch integer to assign them
  99.610 -     * @param notify collection of classes will be changed
  99.611 -     * @return <code>true<code> if some items were changed and node items and children are emptied,
  99.612 -     * those nodes, excluding root, will be removed from tree */
  99.613 -    private boolean retainAllClasses(Node node, Map retain, Collection<Class> notify) {
  99.614 -        boolean retained = false;
  99.615 -
  99.616 -        if ((node.items != null) && (retain != null)) {
  99.617 -            Iterator<Pair> it = node.items.iterator();
  99.618 -
  99.619 -            while (it.hasNext()) {
  99.620 -                AbstractLookup.Pair<?> item = it.next();
  99.621 -                AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(item);
  99.622 -
  99.623 -                if (n == null) {
  99.624 -                    // remove this item, it should not be there
  99.625 -                    it.remove();
  99.626 -                    retained = true;
  99.627 -                } else {
  99.628 -                    // change the index
  99.629 -                    if (item.getIndex() != n.index) {
  99.630 -                        item.setIndex(null, n.index);
  99.631 -
  99.632 -                        //                        notify.addAll ((ArrayList)n.transaction);
  99.633 -                    }
  99.634 -                }
  99.635 -            }
  99.636 -
  99.637 -            if (retained && (notify != null)) {
  99.638 -                // type of this node has been changed
  99.639 -                notify.add(node.getType());
  99.640 -            }
  99.641 -        }
  99.642 -
  99.643 -        if (node.children != null) {
  99.644 -            for (Iterator it = node.children.iterator();;) {
  99.645 -                Node ch = extractNode(it);
  99.646 -
  99.647 -                if (ch == null) {
  99.648 -                    break;
  99.649 -                }
  99.650 -
  99.651 -                boolean result = retainAllClasses(ch, retain, notify);
  99.652 -
  99.653 -                if (result) {
  99.654 -                    // The children node was emptied and has no children -> remove it.
  99.655 -                    it.remove();
  99.656 -                }
  99.657 -            }
  99.658 -        }
  99.659 -
  99.660 -        return retained && node.items.isEmpty() && ((node.children == null) || node.children.isEmpty());
  99.661 -    }
  99.662 -
  99.663 -    /** A method that creates enumeration of all items under given node.
  99.664 -     *
  99.665 -     * @param n node to create enumeration for
  99.666 -     * @return enumeration of Pairs
  99.667 -     */
  99.668 -    private static Enumeration<Pair> nodeToEnum(Node n) {
  99.669 -        if (n.children == null) {
  99.670 -            // create a simple enumeration because we do not have children
  99.671 -            Enumeration<Pair> e;
  99.672 -            if (n.items == null) {
  99.673 -                e = emptyEn();
  99.674 -            } else {
  99.675 -                e = Collections.enumeration(n.items);
  99.676 -            }
  99.677 -            return e;
  99.678 -        }
  99.679 -
  99.680 -        // create enumeration of Items
  99.681 -        return new NeedsSortEnum(n);
  99.682 -    }
  99.683 -
  99.684 -    //
  99.685 -    // Methods to work on interfaces
  99.686 -    // 
  99.687 -
  99.688 -    /** Registers an item with interfaces.
  99.689 -    * @param item item to register
  99.690 -    * @param affected list of classes that were affected
  99.691 -    * @return false if similar item has already been registered
  99.692 -    */
  99.693 -    @SuppressWarnings("unchecked")
  99.694 -    private boolean registerInterface(AbstractLookup.Pair<?> item, Collection<Class> affected) {
  99.695 -        if (interfaces == null) {
  99.696 -            return true;
  99.697 -        }
  99.698 -
  99.699 -        Iterator<Map.Entry<Class,Object>> it = interfaces.entrySet().iterator();
  99.700 -
  99.701 -        while (it.hasNext()) {
  99.702 -            Map.Entry<Class,Object> entry = it.next();
  99.703 -            Class<?> iface = entry.getKey();
  99.704 -
  99.705 -            if (item.instanceOf(iface)) {
  99.706 -                Object value = entry.getValue();
  99.707 -
  99.708 -                if (value instanceof Collection) {
  99.709 -                    Collection<Object> set = (Collection<Object>) value;
  99.710 -
  99.711 -                    if (!set.add(item)) {
  99.712 -                        // item is already there, probably (if everything is correct) is registered in 
  99.713 -                        // all other ifaces too, so stop additional testing
  99.714 -                        return false;
  99.715 -                    }
  99.716 -                } else {
  99.717 -                    // there is just one pair right now
  99.718 -                    if (value.equals(item)) {
  99.719 -                        // item is there => stop processing (same as above)
  99.720 -                        return false;
  99.721 -                    }
  99.722 -
  99.723 -                    // otherwise replace the single item with ArrayList
  99.724 -                    ArrayList<Object> ll = new ArrayList<Object>(3);
  99.725 -                    ll.add(value);
  99.726 -                    ll.add(item);
  99.727 -                    entry.setValue(ll);
  99.728 -                }
  99.729 -
  99.730 -                affected.add(iface);
  99.731 -            }
  99.732 -        }
  99.733 -
  99.734 -        return true;
  99.735 -    }
  99.736 -
  99.737 -    /** Removes interface.
  99.738 -    * @param item item to register
  99.739 -    * @param affected list of classes that were affected
  99.740 -    */
  99.741 -    @SuppressWarnings("unchecked")
  99.742 -    private void removeInterface(AbstractLookup.Pair item, Collection affected) {
  99.743 -        if (interfaces == null) {
  99.744 -            return;
  99.745 -        }
  99.746 -
  99.747 -        Iterator it = interfaces.entrySet().iterator();
  99.748 -
  99.749 -        while (it.hasNext()) {
  99.750 -            Map.Entry entry = (Map.Entry) it.next();
  99.751 -            Object value = entry.getValue();
  99.752 -
  99.753 -            if (value instanceof Collection) {
  99.754 -                Collection set = (Collection) value;
  99.755 -
  99.756 -                if (set.remove(item)) {
  99.757 -                    if (set.size() == 1) {
  99.758 -                        // if there is just one item remaining change to single item mode
  99.759 -                        entry.setValue(set.iterator().next());
  99.760 -                    }
  99.761 -
  99.762 -                    // adds the Class the item was register to into affected
  99.763 -                    affected.add(entry.getKey());
  99.764 -                }
  99.765 -            } else {
  99.766 -                // single item value
  99.767 -                if (value.equals(item)) {
  99.768 -                    // Emptied -> remove.
  99.769 -                    it.remove();
  99.770 -
  99.771 -                    affected.add(entry.getKey());
  99.772 -                }
  99.773 -            }
  99.774 -        }
  99.775 -    }
  99.776 -
  99.777 -    /** Retains some items.
  99.778 -    * @param retainItems items to retain and their mapping to index numbers
  99.779 -    *    (AbstractLookup.Pair -> AbstractLookup.Info)
  99.780 -    * @param affected list of classes that were affected
  99.781 -    */
  99.782 -    @SuppressWarnings("unchecked")
  99.783 -    private void retainAllInterface(Map retainItems, Collection affected) {
  99.784 -        if (interfaces == null) {
  99.785 -            return;
  99.786 -        }
  99.787 -
  99.788 -        Iterator it = interfaces.entrySet().iterator();
  99.789 -
  99.790 -        while (it.hasNext()) {
  99.791 -            Map.Entry entry = (Map.Entry) it.next();
  99.792 -            Object value = entry.getValue();
  99.793 -
  99.794 -            HashMap<?,?> retain = new HashMap(retainItems);
  99.795 -
  99.796 -            Iterator elems;
  99.797 -            boolean multi = value instanceof Collection;
  99.798 -
  99.799 -            if (multi) {
  99.800 -                // collection mode
  99.801 -                elems = ((Collection) value).iterator();
  99.802 -            } else {
  99.803 -                // single item mode
  99.804 -                elems = Collections.singleton(value).iterator();
  99.805 -            }
  99.806 -
  99.807 -            boolean changed = false;
  99.808 -            boolean reordered = false;
  99.809 -
  99.810 -            while (elems.hasNext()) {
  99.811 -                AbstractLookup.Pair p = (AbstractLookup.Pair) elems.next();
  99.812 -
  99.813 -                AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(p);
  99.814 -
  99.815 -                if (n == null) {
  99.816 -                    if (multi) {
  99.817 -                        // remove it
  99.818 -                        elems.remove();
  99.819 -                    }
  99.820 -
  99.821 -                    changed = true;
  99.822 -                } else {
  99.823 -                    if (p.getIndex() != n.index) {
  99.824 -                        // improve the index
  99.825 -                        p.setIndex(null, n.index);
  99.826 -
  99.827 -                        //                    affected.addAll ((ArrayList)n.transaction);
  99.828 -                        reordered = true;
  99.829 -                    }
  99.830 -                }
  99.831 -            }
  99.832 -
  99.833 -            if (reordered && value instanceof List) {
  99.834 -                // if reordered, than update the order in the collection
  99.835 -                List l = (List) value;
  99.836 -                Collections.sort(l, ALPairComparator.DEFAULT);
  99.837 -            }
  99.838 -
  99.839 -            if (changed) {
  99.840 -                if (multi) {
  99.841 -                    Collection c = (Collection) value;
  99.842 -
  99.843 -                    if (c.size() == 1) {
  99.844 -                        // back to single item mode
  99.845 -                        entry.setValue(c.iterator().next());
  99.846 -                    }
  99.847 -                } else {
  99.848 -                    // remove in single mode => remove completely
  99.849 -                    it.remove();
  99.850 -                }
  99.851 -
  99.852 -                // adds the Class the item was register to into affected
  99.853 -                affected.add(entry.getKey());
  99.854 -            }
  99.855 -        }
  99.856 -    }
  99.857 -
  99.858 -    /** Searches for a clazz between interfaces.
  99.859 -    * @param clazz class to search for
  99.860 -    * @return enumeration of Items
  99.861 -    */
  99.862 -    @SuppressWarnings("unchecked")
  99.863 -    private Enumeration<Pair> searchInterface(final Class<?> clazz) {
  99.864 -        if (interfaces == null) {
  99.865 -            // first call for interface, only initialize
  99.866 -            interfaces = new WeakHashMap();
  99.867 -        }
  99.868 -
  99.869 -        Object obj = interfaces.get(clazz);
  99.870 -
  99.871 -        if (obj == null) {
  99.872 -            // set of items
  99.873 -            AbstractLookup.Pair one = null;
  99.874 -            ArrayList items = null;
  99.875 -
  99.876 -            Enumeration en = lookup(Object.class);
  99.877 -
  99.878 -            while (en.hasMoreElements()) {
  99.879 -                AbstractLookup.Pair it = (AbstractLookup.Pair) en.nextElement();
  99.880 -
  99.881 -                if (it.instanceOf(clazz)) {
  99.882 -                    // ok, this item implements given clazz
  99.883 -                    if (one == null) {
  99.884 -                        one = it;
  99.885 -                    } else {
  99.886 -                        if (items == null) {
  99.887 -                            items = new ArrayList(3);
  99.888 -                            items.add(one);
  99.889 -                        }
  99.890 -
  99.891 -                        items.add(it);
  99.892 -                    }
  99.893 -                }
  99.894 -            }
  99.895 -
  99.896 -            if ((items == null) && (one != null)) {
  99.897 -                // single item mode
  99.898 -                interfaces.put(clazz, one);
  99.899 -
  99.900 -                return singletonEn(one);
  99.901 -            } else {
  99.902 -                if (items == null) {
  99.903 -                    items = new ArrayList(2);
  99.904 -                }
  99.905 -
  99.906 -                interfaces.put(clazz, items);
  99.907 -
  99.908 -                return Collections.enumeration(items);
  99.909 -            }
  99.910 -        } else {
  99.911 -            if (obj instanceof Collection) {
  99.912 -                return Collections.enumeration((Collection) obj);
  99.913 -            } else {
  99.914 -                // single item mode
  99.915 -                return singletonEn((Pair)obj);
  99.916 -            }
  99.917 -        }
  99.918 -    }
  99.919 -
  99.920 -    /** Extracts a node from an iterator, returning null if no next element found
  99.921 -     */
  99.922 -    private static Node extractNode(Iterator it) {
  99.923 -        while (it.hasNext()) {
  99.924 -            Node n = (Node) it.next();
  99.925 -
  99.926 -            if (n.get() == null) {
  99.927 -                it.remove();
  99.928 -            } else {
  99.929 -                return n;
  99.930 -            }
  99.931 -        }
  99.932 -
  99.933 -        return null;
  99.934 -    }
  99.935 -
  99.936 -    /** Prints debug info about the node.
  99.937 -     * @param n node to print
  99.938 -     * @param sp spaces to add
  99.939 -     * @param out where
  99.940 -     * @param instances print also instances
  99.941 -     */
  99.942 -    private static void printNode(Node n, String sp, java.io.PrintStream out, boolean instances) {
  99.943 -        int i;
  99.944 -        Iterator it;
  99.945 -
  99.946 -        Class type = n.getType();
  99.947 -
  99.948 -        out.print(sp);
  99.949 -        out.println("Node for: " + type + "\t" + ((type == null) ? null : type.getClassLoader())); // NOI18N
  99.950 -
  99.951 -        if (n.items != null) {
  99.952 -            i = 0;
  99.953 -            it = new ArrayList<Pair>(n.items).iterator();
  99.954 -
  99.955 -            while (it.hasNext()) {
  99.956 -                AbstractLookup.Pair p = (AbstractLookup.Pair) it.next();
  99.957 -                out.print(sp);
  99.958 -                out.print("  item (" + i++ + "): ");
  99.959 -                out.print(p); // NOI18N
  99.960 -                out.print(" id: " + Integer.toHexString(System.identityHashCode(p))); // NOI18N
  99.961 -                out.print(" index: "); // NOI18N
  99.962 -                out.print(p.getIndex());
  99.963 -
  99.964 -                if (instances) {
  99.965 -                    out.print(" I: " + p.getInstance());
  99.966 -                }
  99.967 -
  99.968 -                out.println();
  99.969 -            }
  99.970 -        }
  99.971 -
  99.972 -        if (n.children != null) {
  99.973 -            i = 0;
  99.974 -            it = n.children.iterator();
  99.975 -
  99.976 -            while (it.hasNext()) {
  99.977 -                Node ch = (Node) it.next();
  99.978 -                printNode(ch, sp + "  ", out, instances); // NOI18N
  99.979 -            }
  99.980 -        }
  99.981 -    }
  99.982 -
  99.983 -    public ReferenceToResult registerReferenceToResult(ReferenceToResult<?> newRef) {
  99.984 -        if (reg == null) {
  99.985 -            reg = new HashMap<Class,ReferenceToResult>();
  99.986 -        }
  99.987 -
  99.988 -        Class<? extends Object> clazz = newRef.template.getType();
  99.989 -
  99.990 -        // initialize the data structures if not yet
  99.991 -        lookup(clazz);
  99.992 -
  99.993 -        // newRef will be the new head of the list
  99.994 -        return reg.put(clazz, newRef);
  99.995 -    }
  99.996 -
  99.997 -    public ReferenceToResult cleanUpResult(Lookup.Template templ) {
  99.998 -        collectListeners(null, templ.getType());
  99.999 -
 99.1000 -        return (reg == null) ? null : reg.get(templ.getType());
 99.1001 -    }
 99.1002 -
 99.1003 -    public ArrayList<Class> beginTransaction(int ensure) {
 99.1004 -        return new ArrayList<Class>();
 99.1005 -    }
 99.1006 -
 99.1007 -    public void endTransaction(ArrayList<Class> list, Set<AbstractLookup.R> allAffectedResults) {
 99.1008 -        if (list.size() == 1) {
 99.1009 -            // probably the most common case
 99.1010 -            collectListeners(allAffectedResults, list.get(0));
 99.1011 -        } else {
 99.1012 -            Iterator it = list.iterator();
 99.1013 -
 99.1014 -            while (it.hasNext()) {
 99.1015 -                collectListeners(allAffectedResults, (Class) it.next());
 99.1016 -            }
 99.1017 -        }
 99.1018 -    }
 99.1019 -
 99.1020 -    /** Notifies all listeners that are interested in changes in this class.
 99.1021 -     * Should be called from synchronized places.
 99.1022 -     * @param allAffectedResults adds Results into this set
 99.1023 -     * @param c the class that has changed
 99.1024 -     */
 99.1025 -    private void collectListeners(Set<AbstractLookup.R> allAffectedResults, Class c) {
 99.1026 -        if (reg == null) {
 99.1027 -            return;
 99.1028 -        }
 99.1029 -
 99.1030 -        while (c != null) {
 99.1031 -            ReferenceToResult first = reg.get(c);
 99.1032 -            ReferenceIterator it = new ReferenceIterator(first);
 99.1033 -
 99.1034 -            while (it.next()) {
 99.1035 -                AbstractLookup.R result = it.current().getResult();
 99.1036 -
 99.1037 -                if (allAffectedResults != null) {
 99.1038 -                    // add result
 99.1039 -                    allAffectedResults.add(result);
 99.1040 -                }
 99.1041 -            }
 99.1042 -
 99.1043 -            if (first != it.first()) {
 99.1044 -                if (it.first() == null) {
 99.1045 -                    // we do not need have more results on this object
 99.1046 -                    reg.remove(c);
 99.1047 -                } else {
 99.1048 -                    // move the head of the list
 99.1049 -                    reg.put(c, it.first());
 99.1050 -                }
 99.1051 -            }
 99.1052 -
 99.1053 -            c = c.getSuperclass();
 99.1054 -        }
 99.1055 -
 99.1056 -        if (reg.isEmpty()) {
 99.1057 -            // clean up the list of all results if we do not need them anymore
 99.1058 -            reg = null;
 99.1059 -        }
 99.1060 -    }
 99.1061 -
 99.1062 -    /** Node in the tree.
 99.1063 -    */
 99.1064 -    static final class Node extends WeakReference<Class> implements Serializable {
 99.1065 -        static final long serialVersionUID = 3L;
 99.1066 -
 99.1067 -        /** children nodes */
 99.1068 -        public ArrayList<Node> children;
 99.1069 -
 99.1070 -        /** list of items assigned to this node (suspect to be subclasses) */
 99.1071 -        public Collection<Pair> items;
 99.1072 -
 99.1073 -        /** Constructor.
 99.1074 -        */
 99.1075 -        public Node(Class clazz) {
 99.1076 -            super(clazz);
 99.1077 -        }
 99.1078 -
 99.1079 -        /** Returns true if the object was deserialized also clears the serialized flag.
 99.1080 -         * @return true if so.
 99.1081 -         */
 99.1082 -        public boolean deserialized() {
 99.1083 -            if ((items == null) || items instanceof LinkedHashSet) {
 99.1084 -                return false;
 99.1085 -            }
 99.1086 -
 99.1087 -            if (items.isEmpty()) {
 99.1088 -                items = null;
 99.1089 -            } else {
 99.1090 -                items = new LinkedHashSet<Pair>(items);
 99.1091 -            }
 99.1092 -
 99.1093 -            return true;
 99.1094 -        }
 99.1095 -
 99.1096 -        /** Marks this item as being deserialized.
 99.1097 -         */
 99.1098 -        public void markDeserialized() {
 99.1099 -            if (items == null || items == Collections.EMPTY_LIST) {
 99.1100 -                items = Collections.emptyList();
 99.1101 -            } else {
 99.1102 -                items = Collections.synchronizedCollection(items);
 99.1103 -            }
 99.1104 -        }
 99.1105 -
 99.1106 -        /** Getter for the type associated with this node.
 99.1107 -         */
 99.1108 -        public Class<?> getType() {
 99.1109 -            Class<?> c = get();
 99.1110 -
 99.1111 -            // if  garbage collected, then return a garbage
 99.1112 -            return (c == null) ? Void.TYPE : c;
 99.1113 -        }
 99.1114 -
 99.1115 -        /** Checks whether a node can represent an class.
 99.1116 -        */
 99.1117 -        public boolean accepts(Class<?> clazz) {
 99.1118 -            if (getType() == Object.class) {
 99.1119 -                return true;
 99.1120 -            }
 99.1121 -
 99.1122 -            return getType().isAssignableFrom(clazz);
 99.1123 -        }
 99.1124 -
 99.1125 -        /** Checks whether item is instance of this node.
 99.1126 -        */
 99.1127 -        public boolean accepts(AbstractLookup.Pair<?> item) {
 99.1128 -            if (getType() == Object.class) {
 99.1129 -                // Object.class
 99.1130 -                return true;
 99.1131 -            }
 99.1132 -
 99.1133 -            return item.instanceOf(getType());
 99.1134 -        }
 99.1135 -
 99.1136 -        /** Assings an item to this node.
 99.1137 -        * @param item the item
 99.1138 -        * @return true if item has been added as new
 99.1139 -        */
 99.1140 -        public boolean assignItem(InheritanceTree tree, AbstractLookup.Pair<?> item) {
 99.1141 -            if ((items == null) || (items == Collections.EMPTY_LIST)) {
 99.1142 -                items = new LinkedHashSet<Pair>();
 99.1143 -                items.add(item);
 99.1144 -
 99.1145 -                return true;
 99.1146 -            }
 99.1147 -
 99.1148 -            if (items.contains(item)) {
 99.1149 -                Iterator<Pair> it = items.iterator();
 99.1150 -                Pair old;
 99.1151 -                for (;;) {
 99.1152 -                    old = it.next();
 99.1153 -                    if (item.equals(old)) {
 99.1154 -                        break;
 99.1155 -                    }
 99.1156 -                }
 99.1157 -
 99.1158 -                if (old != item) {
 99.1159 -                    // replace the items there
 99.1160 -                    item.setIndex(tree, old.getIndex());
 99.1161 -                }
 99.1162 -
 99.1163 -                it.remove();
 99.1164 -                items.add(item);
 99.1165 -
 99.1166 -                return false;
 99.1167 -            }
 99.1168 -
 99.1169 -            items.add(item);
 99.1170 -
 99.1171 -            return true;
 99.1172 -        }
 99.1173 -
 99.1174 -        private Object writeReplace() {
 99.1175 -            return new R(this);
 99.1176 -        }
 99.1177 -
 99.1178 -        @Override
 99.1179 -        public String toString() {
 99.1180 -            return "Node for " + get();
 99.1181 -        }
 99.1182 -    }
 99.1183 -     // End of class Node.
 99.1184 -
 99.1185 -    private static final class R implements Serializable {
 99.1186 -        static final long serialVersionUID = 1L;
 99.1187 -        private static ClassLoader l;
 99.1188 -        private String clazzName;
 99.1189 -        private transient Class<?> clazz;
 99.1190 -        private ArrayList<Node> children;
 99.1191 -        private Collection<Pair> items;
 99.1192 -
 99.1193 -        public R(Node n) {
 99.1194 -            this.clazzName = n.getType().getName();
 99.1195 -            this.children = n.children;
 99.1196 -
 99.1197 -            if (n.items instanceof LinkedHashSet || (n.items == null)) {
 99.1198 -                this.items = n.items;
 99.1199 -            } else {
 99.1200 -                this.items = new LinkedHashSet<Pair>(n.items);
 99.1201 -            }
 99.1202 -        }
 99.1203 -
 99.1204 -        private void readObject(ObjectInputStream ois)
 99.1205 -        throws IOException, ClassNotFoundException {
 99.1206 -            ois.defaultReadObject();
 99.1207 -
 99.1208 -            if (l == null) {
 99.1209 -                l = Lookup.getDefault().lookup(ClassLoader.class);
 99.1210 -            }
 99.1211 -
 99.1212 -            clazz = Class.forName(clazzName, false, l);
 99.1213 -        }
 99.1214 -
 99.1215 -        private Object readResolve() throws ObjectStreamException {
 99.1216 -            Node n = new Node(clazz);
 99.1217 -            n.children = children;
 99.1218 -            n.items = items;
 99.1219 -            n.markDeserialized();
 99.1220 -
 99.1221 -            return n;
 99.1222 -        }
 99.1223 -    }
 99.1224 -     // end of R
 99.1225 -
 99.1226 -    static Enumeration<Object> arrayEn(Object[] object) {
 99.1227 -        return Collections.enumeration(Arrays.asList(object));
 99.1228 -    }
 99.1229 -    static <T> Enumeration<T> singletonEn(T object) {
 99.1230 -        return Collections.enumeration(Collections.singleton(object));
 99.1231 -    }
 99.1232 -    static <T> Enumeration<T> emptyEn() {
 99.1233 -        return Collections.enumeration(Collections.<T>emptyList());
 99.1234 -    }
 99.1235 -
 99.1236 -    /** Just a marker class to be able to do instanceof and find out
 99.1237 -     * that this enumeration is not sorted
 99.1238 -     */
 99.1239 -    private static final class NeedsSortEnum extends LinkedList<Node>
 99.1240 -    implements Enumeration<Pair> {
 99.1241 -        private Enumeration<Pair> en;
 99.1242 -
 99.1243 -        public NeedsSortEnum(Node n) {
 99.1244 -            add(n);
 99.1245 -        }
 99.1246 -
 99.1247 -        private boolean ensureNext() {
 99.1248 -            for (;;) {
 99.1249 -                if (en != null && en.hasMoreElements()) {
 99.1250 -                    return true;
 99.1251 -                }
 99.1252 -                if (isEmpty()) {
 99.1253 -                    return false;
 99.1254 -                }
 99.1255 -
 99.1256 -                Node n2 = poll();
 99.1257 -                if (n2.children != null) {
 99.1258 -                    addAll(n2.children);
 99.1259 -                }
 99.1260 -
 99.1261 -                if (n2.items != null && !n2.items.isEmpty()) {
 99.1262 -                    en = Collections.enumeration(n2.items);
 99.1263 -                }
 99.1264 -            }
 99.1265 -        }
 99.1266 -
 99.1267 -        public boolean hasMoreElements() {
 99.1268 -            return ensureNext();
 99.1269 -        }
 99.1270 -
 99.1271 -        public Pair nextElement() {
 99.1272 -            if (!ensureNext()) {
 99.1273 -                throw new NoSuchElementException();
 99.1274 -            }
 99.1275 -            return en.nextElement();
 99.1276 -        }
 99.1277 -    }
 99.1278 -     // end of NeedsSortEnum
 99.1279 -}
   100.1 --- a/openide.util/src/org/openide/util/lookup/InstanceContent.java	Thu Dec 10 19:23:25 2009 -0500
   100.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.3 @@ -1,378 +0,0 @@
   100.4 -/*
   100.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   100.6 - *
   100.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   100.8 - *
   100.9 - * The contents of this file are subject to the terms of either the GNU
  100.10 - * General Public License Version 2 only ("GPL") or the Common
  100.11 - * Development and Distribution License("CDDL") (collectively, the
  100.12 - * "License"). You may not use this file except in compliance with the
  100.13 - * License. You can obtain a copy of the License at
  100.14 - * http://www.netbeans.org/cddl-gplv2.html
  100.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  100.16 - * specific language governing permissions and limitations under the
  100.17 - * License.  When distributing the software, include this License Header
  100.18 - * Notice in each file and include the License file at
  100.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  100.20 - * particular file as subject to the "Classpath" exception as provided
  100.21 - * by Sun in the GPL Version 2 section of the License file that
  100.22 - * accompanied this code. If applicable, add the following below the
  100.23 - * License Header, with the fields enclosed by brackets [] replaced by
  100.24 - * your own identifying information:
  100.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  100.26 - *
  100.27 - * Contributor(s):
  100.28 - *
  100.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  100.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  100.31 - * Microsystems, Inc. All Rights Reserved.
  100.32 - *
  100.33 - * If you wish your version of this file to be governed by only the CDDL
  100.34 - * or only the GPL Version 2, indicate your decision by adding
  100.35 - * "[Contributor] elects to include this software in this distribution
  100.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  100.37 - * single choice of license, a recipient has the option to distribute
  100.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  100.39 - * to extend the choice of license to its licensees as provided above.
  100.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  100.41 - * Version 2 license, then the option applies only if the new code is
  100.42 - * made subject to such option by the copyright holder.
  100.43 - */
  100.44 -package org.openide.util.lookup;
  100.45 -
  100.46 -import org.openide.util.lookup.AbstractLookup.Pair;
  100.47 -
  100.48 -import java.lang.ref.WeakReference;
  100.49 -
  100.50 -import java.util.*;
  100.51 -import java.util.concurrent.Executor;
  100.52 -import org.openide.util.Lookup.Item;
  100.53 -
  100.54 -
  100.55 -/** A special content implementation that can be passed to AbstractLookup
  100.56 - * and provides methods for registration of instances and lazy instances.
  100.57 - * <PRE>
  100.58 - *      InstanceContent ic = new InstanceContent ();
  100.59 - *      AbstractLookup al = new AbstractLookup (ic);
  100.60 - *
  100.61 - *      ic.add (new Object ());
  100.62 - *      ic.add (new Dimension (...));
  100.63 - *
  100.64 - *      Dimension theDim = (Dimension)al.lookup (Dimension.class);
  100.65 - * </PRE>
  100.66 - *
  100.67 - * @author  Jaroslav Tulach
  100.68 - *
  100.69 - * @since 1.25
  100.70 - */
  100.71 -public final class InstanceContent extends AbstractLookup.Content {
  100.72 -    /**
  100.73 -     * Create a new, empty content.
  100.74 -     */
  100.75 -    public InstanceContent() {
  100.76 -    }
  100.77 -
  100.78 -    /** Creates a content associated with an executor to handle dispatch
  100.79 -     * of changes.
  100.80 -     * @param notifyIn the executor to notify changes in
  100.81 -     * @since  7.16
  100.82 -     */
  100.83 -    public InstanceContent(Executor notifyIn) {
  100.84 -        super(notifyIn);
  100.85 -    }
  100.86 -    /** The method to add instance to the lookup with.
  100.87 -     * @param inst instance
  100.88 -     */
  100.89 -    public final void add(Object inst) {
  100.90 -        addPair(new SimpleItem<Object>(inst));
  100.91 -    }
  100.92 -
  100.93 -    /** Adds a convertible instance into the lookup. The <code>inst</code>
  100.94 -     * argument is just a key, not the actual value to appear in the lookup.
  100.95 -     * The value will be created on demand, later when it is really needed
  100.96 -     * by calling <code>convertor</code> methods.
  100.97 -     * <p>
  100.98 -     * This method is useful to delay creation of heavy weight objects.
  100.99 -     * Instead just register lightweight key and a convertor.
 100.100 -     * <p>
 100.101 -     * To remove registered object from lookup use {@link #remove(java.lang.Object, org.openide.util.lookup.InstanceContent.Convertor)}
 100.102 -     * with the same arguments.
 100.103 -     *
 100.104 -     * @param inst instance
 100.105 -     * @param conv convertor which postponing an instantiation,
 100.106 -     * if <code>conv==null</code> then the instance is registered directly.
 100.107 -     */
 100.108 -    public final <T,R> void add(T inst, Convertor<T,R> conv) {
 100.109 -        addPair(new ConvertingItem<T,R>(inst, conv));
 100.110 -    }
 100.111 -
 100.112 -    /** Remove instance.
 100.113 -     * @param inst instance
 100.114 -     */
 100.115 -    public final void remove(Object inst) {
 100.116 -        removePair(new SimpleItem<Object>(inst));
 100.117 -    }
 100.118 -
 100.119 -    /** Remove instance added with a convertor.
 100.120 -     * @param inst instance
 100.121 -     * @param conv convertor, if <code>conv==null</code> it is same like
 100.122 -     * remove(Object)
 100.123 -     */
 100.124 -    public final <T,R> void remove(T inst, Convertor<T,R> conv) {
 100.125 -        removePair(new ConvertingItem<T,R>(inst, conv));
 100.126 -    }
 100.127 -
 100.128 -    /** Changes all pairs in the lookup to new values. Converts collection of
 100.129 -     * instances to collection of pairs.
 100.130 -     * @param col the collection of (Item) objects
 100.131 -     * @param conv the convertor to use or null
 100.132 -     */
 100.133 -    public final <T,R> void set(Collection<T> col, Convertor<T,R> conv) {
 100.134 -        ArrayList<Pair<?>> l = new ArrayList<Pair<?>>(col.size());
 100.135 -        Iterator<T> it = col.iterator();
 100.136 -
 100.137 -        if (conv == null) {
 100.138 -            while (it.hasNext()) {
 100.139 -                l.add(new SimpleItem<T>(it.next()));
 100.140 -            }
 100.141 -        } else {
 100.142 -            while (it.hasNext()) {
 100.143 -                l.add(new ConvertingItem<T,R>(it.next(), conv));
 100.144 -            }
 100.145 -        }
 100.146 -
 100.147 -        setPairs(l);
 100.148 -    }
 100.149 -
 100.150 -    /** Convertor postpones an instantiation of an object.
 100.151 -     * @since 1.25
 100.152 -     */
 100.153 -    public static interface Convertor<T,R> {
 100.154 -        /** Convert obj to other object. There is no need to implement
 100.155 -         * cache mechanism. It is provided by
 100.156 -         * {@link Item#getInstance()} method itself. However the
 100.157 -         * method can be called more than once because instance is held
 100.158 -         * just by weak reference.
 100.159 -         *
 100.160 -         * @param obj the registered object
 100.161 -         * @return the object converted from this object
 100.162 -         */
 100.163 -        public R convert(T obj);
 100.164 -
 100.165 -        /** Return type of converted object. Accessible via
 100.166 -         * {@link Item#getType()}
 100.167 -         * @param obj the registered object
 100.168 -         * @return the class that will be produced from this object (class or
 100.169 -         *      superclass of convert (obj))
 100.170 -         */
 100.171 -        public Class<? extends R> type(T obj);
 100.172 -
 100.173 -        /** Computes the ID of the resulted object. Accessible via
 100.174 -         * {@link Item#getId()}.
 100.175 -         * @param obj the registered object
 100.176 -         * @return the ID for the object
 100.177 -         */
 100.178 -        public String id(T obj);
 100.179 -
 100.180 -        /** The human presentable name for the object. Accessible via
 100.181 -         * {@link Item#getDisplayName()}.
 100.182 -         * @param obj the registered object
 100.183 -         * @return the name representing the object for the user
 100.184 -         */
 100.185 -        public String displayName(T obj);
 100.186 -    }
 100.187 -
 100.188 -    /** Instance of one item representing an object.
 100.189 -     */
 100.190 -    final static class SimpleItem<T> extends Pair<T> {
 100.191 -        private T obj;
 100.192 -
 100.193 -        /** Create an item.
 100.194 -         * @obj object to register
 100.195 -         */
 100.196 -        public SimpleItem(T obj) {
 100.197 -            if (obj == null) {
 100.198 -                throw new NullPointerException();
 100.199 -            }
 100.200 -            this.obj = obj;
 100.201 -        }
 100.202 -
 100.203 -        /** Tests whether this item can produce object
 100.204 -         * of class c.
 100.205 -         */
 100.206 -        public boolean instanceOf(Class<?> c) {
 100.207 -            return c.isInstance(obj);
 100.208 -        }
 100.209 -
 100.210 -        /** Get instance of registered object. If convertor is specified then
 100.211 -         *  method InstanceLookup.Convertor.convertor is used and weak reference
 100.212 -         * to converted object is saved.
 100.213 -         * @return the instance of the object.
 100.214 -         */
 100.215 -        public T getInstance() {
 100.216 -            return obj;
 100.217 -        }
 100.218 -
 100.219 -        @Override
 100.220 -        public boolean equals(Object o) {
 100.221 -            if (o instanceof SimpleItem) {
 100.222 -                return obj.equals(((SimpleItem) o).obj);
 100.223 -            } else {
 100.224 -                return false;
 100.225 -            }
 100.226 -        }
 100.227 -
 100.228 -        @Override
 100.229 -        public int hashCode() {
 100.230 -            return obj.hashCode();
 100.231 -        }
 100.232 -
 100.233 -        /** An identity of the item.
 100.234 -         * @return string representing the item, that can be used for
 100.235 -         *   persistance purposes to locate the same item next time
 100.236 -         */
 100.237 -        public String getId() {
 100.238 -            return "IL[" + obj.toString(); // NOI18N
 100.239 -        }
 100.240 -
 100.241 -        /** Getter for display name of the item.
 100.242 -         */
 100.243 -        public String getDisplayName() {
 100.244 -            return obj.toString();
 100.245 -        }
 100.246 -
 100.247 -        /** Method that can test whether an instance of a class has been created
 100.248 -         * by this item.
 100.249 -         *
 100.250 -         * @param obj the instance
 100.251 -         * @return if the item has already create an instance and it is the same
 100.252 -         *  as obj.
 100.253 -         */
 100.254 -        protected boolean creatorOf(Object obj) {
 100.255 -            return obj == this.obj;
 100.256 -        }
 100.257 -
 100.258 -        /** The class of this item.
 100.259 -         * @return the correct class
 100.260 -         */
 100.261 -        @SuppressWarnings("unchecked")
 100.262 -        public Class<? extends T> getType() {
 100.263 -            return (Class<? extends T>)obj.getClass();
 100.264 -        }
 100.265 -    }
 100.266 -     // end of SimpleItem
 100.267 -
 100.268 -    /** Instance of one item registered in the map.
 100.269 -     */
 100.270 -    final static class ConvertingItem<T,R> extends Pair<R> {
 100.271 -        /** registered object */
 100.272 -        private T obj;
 100.273 -
 100.274 -        /** Reference to converted object. */
 100.275 -        private WeakReference<R> ref;
 100.276 -
 100.277 -        /** convertor to use */
 100.278 -        private Convertor<? super T,R> conv;
 100.279 -
 100.280 -        /** Create an item.
 100.281 -         * @obj object to register
 100.282 -         * @conv a convertor, can be <code>null</code>.
 100.283 -         */
 100.284 -        public ConvertingItem(T obj, Convertor<? super T,R> conv) {
 100.285 -            this.obj = obj;
 100.286 -            this.conv = conv;
 100.287 -        }
 100.288 -
 100.289 -        /** Tests whether this item can produce object
 100.290 -         * of class c.
 100.291 -         */
 100.292 -        public boolean instanceOf(Class<?> c) {
 100.293 -            return c.isAssignableFrom(getType());
 100.294 -        }
 100.295 -
 100.296 -        /** Returns converted object or null if obj has not been converted yet
 100.297 -         * or reference was cleared by garbage collector.
 100.298 -         */
 100.299 -        private R getConverted() {
 100.300 -            if (ref == null) {
 100.301 -                return null;
 100.302 -            }
 100.303 -
 100.304 -            return ref.get();
 100.305 -        }
 100.306 -
 100.307 -        /** Get instance of registered object. If convertor is specified then
 100.308 -         *  method InstanceLookup.Convertor.convertor is used and weak reference
 100.309 -         * to converted object is saved.
 100.310 -         * @return the instance of the object.
 100.311 -         */
 100.312 -        public synchronized R getInstance() {
 100.313 -            R converted = getConverted();
 100.314 -
 100.315 -            if (converted == null) {
 100.316 -                converted = conv.convert(obj);
 100.317 -                ref = new WeakReference<R>(converted);
 100.318 -            }
 100.319 -
 100.320 -            return converted;
 100.321 -        }
 100.322 -
 100.323 -        @Override
 100.324 -        public boolean equals(Object o) {
 100.325 -            if (o instanceof ConvertingItem) {
 100.326 -                return obj.equals(((ConvertingItem) o).obj);
 100.327 -            } else {
 100.328 -                return false;
 100.329 -            }
 100.330 -        }
 100.331 -
 100.332 -        @Override
 100.333 -        public int hashCode() {
 100.334 -            return obj.hashCode();
 100.335 -        }
 100.336 -
 100.337 -        /** An identity of the item.
 100.338 -         * @return string representing the item, that can be used for
 100.339 -         *   persistance purposes to locate the same item next time
 100.340 -         */
 100.341 -        public String getId() {
 100.342 -            return conv.id(obj);
 100.343 -        }
 100.344 -
 100.345 -        /** Getter for display name of the item.
 100.346 -         */
 100.347 -        public String getDisplayName() {
 100.348 -            return conv.displayName(obj);
 100.349 -        }
 100.350 -
 100.351 -        /** Method that can test whether an instance of a class has been created
 100.352 -         * by this item.
 100.353 -         *
 100.354 -         * @param obj the instance
 100.355 -         * @return if the item has already create an instance and it is the same
 100.356 -         *  as obj.
 100.357 -         */
 100.358 -        protected boolean creatorOf(Object obj) {
 100.359 -            if (conv == null) {
 100.360 -                return obj == this.obj;
 100.361 -            } else {
 100.362 -                return obj == getConverted();
 100.363 -            }
 100.364 -        }
 100.365 -
 100.366 -        /** The class of this item.
 100.367 -         * @return the correct class
 100.368 -         */
 100.369 -        @SuppressWarnings("unchecked")
 100.370 -        public Class<? extends R> getType() {
 100.371 -            R converted = getConverted();
 100.372 -
 100.373 -            if (converted == null) {
 100.374 -                return conv.type(obj);
 100.375 -            }
 100.376 -
 100.377 -            return (Class<? extends R>)converted.getClass();
 100.378 -        }
 100.379 -    }
 100.380 -     // end of ConvertingItem
 100.381 -}
   101.1 --- a/openide.util/src/org/openide/util/lookup/Lookups.java	Thu Dec 10 19:23:25 2009 -0500
   101.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.3 @@ -1,317 +0,0 @@
   101.4 -/*
   101.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   101.6 - *
   101.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   101.8 - *
   101.9 - * The contents of this file are subject to the terms of either the GNU
  101.10 - * General Public License Version 2 only ("GPL") or the Common
  101.11 - * Development and Distribution License("CDDL") (collectively, the
  101.12 - * "License"). You may not use this file except in compliance with the
  101.13 - * License. You can obtain a copy of the License at
  101.14 - * http://www.netbeans.org/cddl-gplv2.html
  101.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  101.16 - * specific language governing permissions and limitations under the
  101.17 - * License.  When distributing the software, include this License Header
  101.18 - * Notice in each file and include the License file at
  101.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  101.20 - * particular file as subject to the "Classpath" exception as provided
  101.21 - * by Sun in the GPL Version 2 section of the License file that
  101.22 - * accompanied this code. If applicable, add the following below the
  101.23 - * License Header, with the fields enclosed by brackets [] replaced by
  101.24 - * your own identifying information:
  101.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  101.26 - *
  101.27 - * Contributor(s):
  101.28 - *
  101.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  101.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
  101.31 - * Microsystems, Inc. All Rights Reserved.
  101.32 - *
  101.33 - * If you wish your version of this file to be governed by only the CDDL
  101.34 - * or only the GPL Version 2, indicate your decision by adding
  101.35 - * "[Contributor] elects to include this software in this distribution
  101.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  101.37 - * single choice of license, a recipient has the option to distribute
  101.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  101.39 - * to extend the choice of license to its licensees as provided above.
  101.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  101.41 - * Version 2 license, then the option applies only if the new code is
  101.42 - * made subject to such option by the copyright holder.
  101.43 - */
  101.44 -
  101.45 -package org.openide.util.lookup;
  101.46 -
  101.47 -import java.util.Arrays;
  101.48 -import org.netbeans.modules.openide.util.NamedServicesProvider;
  101.49 -import org.openide.util.Lookup;
  101.50 -
  101.51 -/**
  101.52 - * Static factory methods for creating common lookup implementations.
  101.53 - *
  101.54 - * @author David Strupl
  101.55 - * @since 2.21
  101.56 - */
  101.57 -public class Lookups {
  101.58 -
  101.59 -    /** static methods only */
  101.60 -    private Lookups() {}
  101.61 -
  101.62 -    /**
  101.63 -     * Creates a singleton lookup. It means lookup that contains only
  101.64 -     * one object specified via the supplied parameter. The lookup will
  101.65 -     * either return the object or null if the supplied template does
  101.66 -     * not match the class. If the specified argument is null the method
  101.67 -     * will end with NullPointerException.
  101.68 -     * @return Fully initialized lookup object ready to use
  101.69 -     * @throws NullPointerException if the supplied argument is null
  101.70 -     * @since 2.21
  101.71 -     */
  101.72 -    public static Lookup singleton(Object objectToLookup) {
  101.73 -        if (objectToLookup == null) {
  101.74 -            throw new NullPointerException();
  101.75 -        }
  101.76 -
  101.77 -        return new SingletonLookup(objectToLookup);
  101.78 -    }
  101.79 -
  101.80 -    /**
  101.81 -     * Creates a lookup that contains an array of objects specified via the
  101.82 -     * parameter. The resulting lookup is fixed in the following sense: it
  101.83 -     * contains only fixed set of objects passed in by the array parameter.
  101.84 -     * Its contents never changes so registering listeners on such lookup
  101.85 -     * does not have any observable effect (the listeners are never called).
  101.86 -     *
  101.87 -     * @param objectsToLookup list of objects to include
  101.88 -     * @return Fully initialized lookup object ready to use
  101.89 -     * @throws NullPointerException if the supplied argument is null
  101.90 -     * @since 2.21
  101.91 -     *
  101.92 -     */
  101.93 -    public static Lookup fixed(Object... objectsToLookup) {
  101.94 -        if (objectsToLookup == null) {
  101.95 -            throw new NullPointerException();
  101.96 -        }
  101.97 -
  101.98 -        if (objectsToLookup.length == 0) {
  101.99 -            return Lookup.EMPTY;
 101.100 -        }
 101.101 -
 101.102 -        if (objectsToLookup.length == 1) {
 101.103 -            return singleton(objectsToLookup[0]);
 101.104 -        }
 101.105 -
 101.106 -        return new SimpleLookup(Arrays.asList(objectsToLookup));
 101.107 -    }
 101.108 -
 101.109 -    /**
 101.110 -     * Creates a lookup that contains an array of objects specified via the
 101.111 -     * parameter. The resulting lookup is fixed in the following sense: it
 101.112 -     * contains only fixed set of objects passed in by the array parameter.
 101.113 -     * The objects returned from this lookup are converted to real objects
 101.114 -     * before they are returned by the lookup.
 101.115 -     * Its contents never changes so registering listeners on such lookup
 101.116 -     * does not have any observable effect (the listeners are never called).
 101.117 -     *
 101.118 -     * @return Fully initialized lookup object ready to use
 101.119 -     * @throws NullPointerException if the any of the arguments is null
 101.120 -     * @since 2.21
 101.121 -     *
 101.122 -     */
 101.123 -    public static <T,R> Lookup fixed(T[] keys, InstanceContent.Convertor<? super T,R> convertor) {
 101.124 -        if (keys == null) {
 101.125 -            throw new NullPointerException();
 101.126 -        }
 101.127 -
 101.128 -        if (convertor == null) {
 101.129 -            throw new NullPointerException();
 101.130 -        }
 101.131 -
 101.132 -        return new SimpleLookup(Arrays.asList(keys), convertor);
 101.133 -    }
 101.134 -
 101.135 -    /** Creates a lookup that delegates to another one but that one can change
 101.136 -     * from time to time. The returned lookup checks every time somebody calls
 101.137 -     * <code>lookup</code> or <code>lookupItem</code> method whether the
 101.138 -     * provider still returns the same lookup. If not, it updates state of
 101.139 -     * all {@link org.openide.util.Lookup.Result}s 
 101.140 -     * that it created (and that still exists).
 101.141 -     * <P>
 101.142 -     * The user of this method has to implement its provider's <code>getLookup</code>
 101.143 -     * method (must be thread safe and fast, will be called often and from any thread)
 101.144 -     * pass it to this method and use the returned lookup. Whenever the user
 101.145 -     * changes the return value from the <code>getLookup</code> method and wants
 101.146 -     * to notify listeners on the lookup about that it should trigger the event
 101.147 -     * firing, for example by calling <code>lookup.lookup (Object.class)</code>
 101.148 -     * directly on the lookup returned by this method
 101.149 -     * that forces a check of the return value of {@link org.openide.util.Lookup.Provider#getLookup}</code>.
 101.150 -     *
 101.151 -     * @param provider the provider that returns a lookup to delegate to
 101.152 -     * @return lookup delegating to the lookup returned by the provider
 101.153 -     * @since 3.9
 101.154 -     */
 101.155 -    public static Lookup proxy(Lookup.Provider provider) {
 101.156 -        return new SimpleProxyLookup(provider);
 101.157 -    }
 101.158 -
 101.159 -    /** Returns a lookup that implements the JDK1.3 JAR services mechanism and delegates
 101.160 -     * to META-INF/services/name.of.class files.
 101.161 -     * <p>Some extensions to the JAR services specification are implemented:
 101.162 -     * <ol>
 101.163 -     * <li>An entry may be followed by a line of the form <code>#position=<i>integer</i></code>
 101.164 -     *     to specify ordering. (Smaller numbers first, entries with unspecified position last.)
 101.165 -     * <li>A line of the form <code>#-<i>classname</i></code> suppresses an entry registered
 101.166 -     *     in another file, so can be used to supersede one implementation with another.
 101.167 -     * </ol>
 101.168 -     * <p>Note: It is not dynamic - so if you need to change the classloader or JARs,
 101.169 -     * wrap it in a {@link ProxyLookup} and change the delegate when necessary.
 101.170 -     * Existing instances will be kept if the implementation classes are unchanged,
 101.171 -     * so there is "stability" in doing this provided some parent loaders are the same
 101.172 -     * as the previous ones.
 101.173 -     * @since 3.35
 101.174 -     * @see ServiceProvider
 101.175 -     */
 101.176 -    public static Lookup metaInfServices(ClassLoader classLoader) {
 101.177 -        return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N
 101.178 -    }
 101.179 -
 101.180 -    /** Returns a lookup that behaves exactly like {@link #metaInfServices(ClassLoader)}
 101.181 -     * except that it does not read data from <code>META-INF/services/</code>, but instead
 101.182 -     * from the specified prefix.
 101.183 -     * @param classLoader class loader to use for loading
 101.184 -     * @param prefix prefix to prepend to the class name when searching
 101.185 -     * @since 7.9
 101.186 -     */
 101.187 -    public static Lookup metaInfServices(ClassLoader classLoader, String prefix) {
 101.188 -        return new MetaInfServicesLookup(classLoader, prefix);
 101.189 -    }
 101.190 -    
 101.191 -    /** Creates a <q>named</q> lookup.
 101.192 -     * It is a lookup identified by a given path.
 101.193 -     * Two lookups with the same path should have the same content.
 101.194 -     * <p>It is expected that each <q>named</q> lookup
 101.195 -     * will contain a superset of what would be created by:
 101.196 -     * <code>{@linkplain #metaInfServices(ClassLoader,String) metaInfServices}(theRightLoader, "META-INF/namedservices/" + path + "/")</code>
 101.197 -     *
 101.198 -     * <p class="nonnormative">Various environments can add their own
 101.199 -     * extensions to its content. As such
 101.200 -     * {@link Lookups#forPath(java.lang.String)} can combine lookups
 101.201 -     * from several sources. In current NetBeans Runtime Container, two lookups are used:
 101.202 -     * </p>
 101.203 -     * <ul class="nonnormative">
 101.204 -     * <li><code>Lookups.metaInfServices("META-INF/namedservices/" + path)</code></li>
 101.205 -     * <li><code>org.openide.loaders.FolderLookup(path)</code></li>
 101.206 -     * </ul>
 101.207 -     * <p class="nonnormative">
 101.208 -     * Please note that these lookups differ in the way they inspect sub-folders.
 101.209 -     * The first lookup just returns instances from the given path, ignoring
 101.210 -     * sub-folders, the second one retrieves instances from the whole sub-tree.
 101.211 -     * </p>
 101.212 -     * <p>
 101.213 -     * Read more about the <a href="../doc-files/api.html#folderlookup">usage of this method</a>.
 101.214 -     * 
 101.215 -     * @param path the path identifying the lookup, e.g. <code>Projects/Actions</code>
 101.216 -     * @return lookup associated with this path
 101.217 -     * @since 7.9
 101.218 -     */
 101.219 -    public static Lookup forPath(String path) {
 101.220 -        return NamedServicesProvider.find(path);
 101.221 -    }
 101.222 -    
 101.223 -    /** Creates a lookup that wraps another one and filters out instances
 101.224 -     * of specified classes. If you have a lookup and
 101.225 -     * you want to remove all instances of ActionMap you can use:
 101.226 -     * <pre>
 101.227 -     * l = Lookups.exclude(lookup, ActionMap.class);
 101.228 -     * </pre>
 101.229 -     * Then anybody who asks for <code>l.lookup(ActionMap.class)</code> or
 101.230 -     * subclass will get <code>null</code>. Even if the original lookup contains the
 101.231 -     * value.
 101.232 -     * To create empty lookup (well, just an example, otherwise use {@link Lookup#EMPTY}) one could use:
 101.233 -     * <pre>
 101.234 -     * Lookup.exclude(anyLookup, Object.class);
 101.235 -     * </pre>
 101.236 -     * as any instance in any lookup is of type Object and thus would be excluded.
 101.237 -     * <p>
 101.238 -     * The complete behavior can be described as <code>classes</code> being
 101.239 -     * a barrier. For an object not to be excluded, there has to be an inheritance
 101.240 -     * path between the queried class and the actual class of the instance,
 101.241 -     * that is not blocked by any of the excluded classes:
 101.242 -     * <pre>
 101.243 -     * interface A {}
 101.244 -     * interface B {}
 101.245 -     * class C implements A, B {}
 101.246 -     * Object c = new C();
 101.247 -     * Lookup l1 = Lookups.singleton(c);
 101.248 -     * Lookup l2 = Lookups.exclude(l1, A.class);
 101.249 -     * assertNull("A is directly excluded", l2.lookup(A.class));
 101.250 -     * assertEquals("Returns C as A.class is not between B and C", c, l2.lookup(B.class));
 101.251 -     * </pre>
 101.252 -     * For more info check the
 101.253 -     * <a href="http://hg.netbeans.org/main-golden/annotate/4883eaeda744/openide.util/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java">
 101.254 -     * excluding lookup tests</a> and the discussion in issue
 101.255 -     * <a href="http://openide.netbeans.org/issues/show_bug.cgi?id=53058">53058</a>.
 101.256 -     *
 101.257 -     * @param lookup the original lookup that should be filtered
 101.258 -     * @param classes array of classes those instances should be excluded
 101.259 -     * @since 5.4
 101.260 -     */
 101.261 -    public static Lookup exclude(Lookup lookup, Class... classes) {
 101.262 -        return new ExcludingLookup(lookup, classes);
 101.263 -    }
 101.264 -
 101.265 -    /** Creates <code>Lookup.Item</code> representing the instance passed in.
 101.266 -     *
 101.267 -     * @param instance the object for which Lookup.Item should be creted
 101.268 -     * @param id unique identification of the object, for details see {@link org.openide.util.Lookup.Item#getId},
 101.269 -     * can be <code>null</code>
 101.270 -     * @return lookup item representing instance
 101.271 -     * @since 4.8
 101.272 -     */
 101.273 -    public static <T> Lookup.Item<T> lookupItem(T instance, String id) {
 101.274 -        return new LookupItem<T>(instance, id);
 101.275 -    }
 101.276 -
 101.277 -    private static class LookupItem<T> extends Lookup.Item<T> {
 101.278 -        private String id;
 101.279 -        private T instance;
 101.280 -
 101.281 -        public LookupItem(T instance) {
 101.282 -            this(instance, null);
 101.283 -        }
 101.284 -
 101.285 -        public LookupItem(T instance, String id) {
 101.286 -            this.id = id;
 101.287 -            this.instance = instance;
 101.288 -        }
 101.289 -
 101.290 -        public String getDisplayName() {
 101.291 -            return getId();
 101.292 -        }
 101.293 -
 101.294 -        public String getId() {
 101.295 -            return (id == null) ? instance.toString() : id;
 101.296 -        }
 101.297 -
 101.298 -        public T getInstance() {
 101.299 -            return instance;
 101.300 -        }
 101.301 -
 101.302 -        @SuppressWarnings("unchecked")
 101.303 -        public Class<? extends T> getType() {
 101.304 -            return (Class<? extends T>)instance.getClass();
 101.305 -        }
 101.306 -
 101.307 -        public @Override boolean equals(Object object) {
 101.308 -            if (object instanceof LookupItem) {
 101.309 -                return instance == ((LookupItem) object).getInstance();
 101.310 -            }
 101.311 -
 101.312 -            return false;
 101.313 -        }
 101.314 -
 101.315 -        public @Override int hashCode() {
 101.316 -            return instance.hashCode();
 101.317 -        }
 101.318 -    }
 101.319 -     // End of LookupItem class
 101.320 -}
   102.1 --- a/openide.util/src/org/openide/util/lookup/MetaInfServicesLookup.java	Thu Dec 10 19:23:25 2009 -0500
   102.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.3 @@ -1,559 +0,0 @@
   102.4 -/*
   102.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   102.6 - *
   102.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   102.8 - *
   102.9 - * The contents of this file are subject to the terms of either the GNU
  102.10 - * General Public License Version 2 only ("GPL") or the Common
  102.11 - * Development and Distribution License("CDDL") (collectively, the
  102.12 - * "License"). You may not use this file except in compliance with the
  102.13 - * License. You can obtain a copy of the License at
  102.14 - * http://www.netbeans.org/cddl-gplv2.html
  102.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  102.16 - * specific language governing permissions and limitations under the
  102.17 - * License.  When distributing the software, include this License Header
  102.18 - * Notice in each file and include the License file at
  102.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  102.20 - * particular file as subject to the "Classpath" exception as provided
  102.21 - * by Sun in the GPL Version 2 section of the License file that
  102.22 - * accompanied this code. If applicable, add the following below the
  102.23 - * License Header, with the fields enclosed by brackets [] replaced by
  102.24 - * your own identifying information:
  102.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  102.26 - *
  102.27 - * Contributor(s):
  102.28 - *
  102.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  102.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  102.31 - * Microsystems, Inc. All Rights Reserved.
  102.32 - *
  102.33 - * If you wish your version of this file to be governed by only the CDDL
  102.34 - * or only the GPL Version 2, indicate your decision by adding
  102.35 - * "[Contributor] elects to include this software in this distribution
  102.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  102.37 - * single choice of license, a recipient has the option to distribute
  102.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  102.39 - * to extend the choice of license to its licensees as provided above.
  102.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  102.41 - * Version 2 license, then the option applies only if the new code is
  102.42 - * made subject to such option by the copyright holder.
  102.43 - */
  102.44 -
  102.45 -package org.openide.util.lookup;
  102.46 -
  102.47 -import java.io.BufferedReader;
  102.48 -import java.io.IOException;
  102.49 -import java.io.InputStream;
  102.50 -import java.io.InputStreamReader;
  102.51 -import java.lang.ref.Reference;
  102.52 -import java.lang.ref.WeakReference;
  102.53 -import java.lang.reflect.Method;
  102.54 -import java.net.URL;
  102.55 -import java.util.ArrayList;
  102.56 -import java.util.Collection;
  102.57 -import java.util.Enumeration;
  102.58 -import java.util.HashSet;
  102.59 -import java.util.LinkedHashSet;
  102.60 -import java.util.List;
  102.61 -import java.util.Map;
  102.62 -import java.util.WeakHashMap;
  102.63 -import java.util.logging.Level;
  102.64 -import java.util.logging.Logger;
  102.65 -import org.openide.util.Lookup;
  102.66 -import org.openide.util.RequestProcessor;
  102.67 -
  102.68 -/**
  102.69 - * @author Jaroslav Tulach, Jesse Glick
  102.70 - * @see Lookups#metaInfServices(ClassLoader,String)
  102.71 - * @see "#14722"
  102.72 - */
  102.73 -final class MetaInfServicesLookup extends AbstractLookup {
  102.74 -
  102.75 -    private static final Logger LOGGER = Logger.getLogger(MetaInfServicesLookup.class.getName());
  102.76 -    static final RequestProcessor RP = new RequestProcessor(MetaInfServicesLookup.class.getName(), 1);
  102.77 -    private static int knownInstancesCount;
  102.78 -    private static final List<Reference<Object>> knownInstances;
  102.79 -    static {
  102.80 -        knownInstances = new ArrayList<Reference<Object>>();
  102.81 -        for (int i = 0; i < 512; i++) {
  102.82 -            knownInstances.add(null);
  102.83 -        }
  102.84 -    }
  102.85 -
  102.86 -    /** A set of all requested classes.
  102.87 -     * Note that classes that we actually succeeded on can never be removed
  102.88 -     * from here because we hold a strong reference to the loader.
  102.89 -     * However we also hold classes which are definitely not loadable by
  102.90 -     * our loader.
  102.91 -     */
  102.92 -    private final Map<Class,Object> classes = new WeakHashMap<Class,Object>();
  102.93 -
  102.94 -    /** class loader to use */
  102.95 -    private final ClassLoader loader;
  102.96 -    /** prefix to prepend */
  102.97 -    private final String prefix;
  102.98 -
  102.99 -    /** Create a lookup reading from a specified classloader.
 102.100 -     */
 102.101 -    public MetaInfServicesLookup(ClassLoader loader, String prefix) {
 102.102 -        this.loader = loader;
 102.103 -        this.prefix = prefix;
 102.104 -
 102.105 -        LOGGER.log(Level.FINE, "Created: {0}", this);
 102.106 -    }
 102.107 -
 102.108 -    @Override
 102.109 -    public String toString() {
 102.110 -        return "MetaInfServicesLookup[" + loader + "]"; // NOI18N
 102.111 -    }
 102.112 -
 102.113 -    /* Tries to load appropriate resources from manifest files.
 102.114 -     */
 102.115 -    @Override
 102.116 -    protected final void beforeLookup(Lookup.Template t) {
 102.117 -        Class c = t.getType();
 102.118 -
 102.119 -        Collection<AbstractLookup.Pair<?>> toAdd = null;
 102.120 -        synchronized (this) {
 102.121 -            if (classes.get(c) == null) { // NOI18N
 102.122 -                toAdd = new ArrayList<Pair<?>>();
 102.123 -            } else {
 102.124 -                // ok, nothing needs to be done
 102.125 -                return;
 102.126 -            }
 102.127 -        }
 102.128 -        if (toAdd != null) {
 102.129 -            search(c, toAdd);
 102.130 -        }
 102.131 -        synchronized (this) {
 102.132 -            if (classes.put(c, "") == null) { // NOI18N
 102.133 -                // Added new class, search for it.
 102.134 -                LinkedHashSet<AbstractLookup.Pair<?>> arr = getPairsAsLHS();
 102.135 -                arr.addAll(toAdd);
 102.136 -                setPairs(arr, RP);
 102.137 -            }
 102.138 -        }
 102.139 -    }
 102.140 -
 102.141 -    /** Finds all pairs and adds them to the collection.
 102.142 -     *
 102.143 -     * @param clazz class to find
 102.144 -     * @param result collection to add Pair to
 102.145 -     */
 102.146 -    private void search(Class<?> clazz, Collection<AbstractLookup.Pair<?>> result) {
 102.147 -        if (LOGGER.isLoggable(Level.FINER)) {
 102.148 -            LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this);
 102.149 -        }
 102.150 -
 102.151 -        String res = prefix + clazz.getName(); // NOI18N
 102.152 -        Enumeration<URL> en;
 102.153 -
 102.154 -        try {
 102.155 -            en = loader.getResources(res);
 102.156 -        } catch (IOException ioe) {
 102.157 -            // do not use ErrorManager because we are in the startup code
 102.158 -            // and ErrorManager might not be ready
 102.159 -            ioe.printStackTrace();
 102.160 -
 102.161 -            return;
 102.162 -        }
 102.163 -
 102.164 -        // Do not create multiple instances in case more than one JAR
 102.165 -        // has the same entry in it (and they load to the same class).
 102.166 -        // Probably would not happen, assuming JARs only list classes
 102.167 -        // they own, but just in case...
 102.168 -        List<Item> foundClasses = new ArrayList<Item>();
 102.169 -        Collection<Class> removeClasses = new ArrayList<Class>();
 102.170 -
 102.171 -        boolean foundOne = false;
 102.172 -
 102.173 -        while (en.hasMoreElements()) {
 102.174 -            if (!foundOne) {
 102.175 -                foundOne = true;
 102.176 -
 102.177 -                // Double-check that in fact we can load the *interface* class.
 102.178 -                // For example, say class I is defined in two JARs, J1 and J2.
 102.179 -                // There is also an implementation M1 defined in J1, and another
 102.180 -                // implementation M2 defined in J2.
 102.181 -                // Classloaders C1 and C2 are made from J1 and J2.
 102.182 -                // A MetaInfServicesLookup is made from C1. Then the user asks to
 102.183 -                // lookup I as loaded from C2. J1 has the services line and lists
 102.184 -                // M1, and we can in fact make it. However it is not of the desired
 102.185 -                // type to be looked up. Don't do this check, which could be expensive,
 102.186 -                // unless we expect to be getting some results, however.
 102.187 -                Class realMcCoy = null;
 102.188 -
 102.189 -                try {
 102.190 -                    realMcCoy = loader.loadClass(clazz.getName());
 102.191 -                } catch (ClassNotFoundException cnfe) {
 102.192 -                    // our loader does not know about it, OK
 102.193 -                }
 102.194 -
 102.195 -                if (realMcCoy != clazz) {
 102.196 -                    // Either the interface class is not available at all in our loader,
 102.197 -                    // or it is not the same version as we expected. Don't provide results.
 102.198 -                    if (LOGGER.isLoggable(Level.WARNING)) {
 102.199 -                        if (realMcCoy != null) {
 102.200 -                            LOGGER.log(Level.WARNING,
 102.201 -                                clazz.getName() + " is not the real McCoy! Actually found it in " +
 102.202 -                                realMcCoy.getClassLoader()
 102.203 -                            ); // NOI18N
 102.204 -                        } else {
 102.205 -                            LOGGER.log(Level.WARNING, clazz.getName() + " could not be found in " + loader); // NOI18N
 102.206 -                        }
 102.207 -                    }
 102.208 -
 102.209 -                    return;
 102.210 -                }
 102.211 -            }
 102.212 -
 102.213 -            URL url = en.nextElement();
 102.214 -            Item currentItem = null;
 102.215 -
 102.216 -            try {
 102.217 -                InputStream is = url.openStream();
 102.218 -
 102.219 -                try {
 102.220 -                    BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N
 102.221 -
 102.222 -                    while (true) {
 102.223 -                        String line = reader.readLine();
 102.224 -
 102.225 -                        if (line == null) {
 102.226 -                            break;
 102.227 -                        }
 102.228 -
 102.229 -                        line = line.trim();
 102.230 -
 102.231 -                        // is it position attribute?
 102.232 -                        if (line.startsWith("#position=")) {
 102.233 -                            if (currentItem == null) {
 102.234 -                                LOGGER.log(Level.WARNING, "Found line '{0}' in {1} but there is no item to associate it with", new Object[] {line, url});
 102.235 -                                continue;
 102.236 -                            }
 102.237 -
 102.238 -                            try {
 102.239 -                                currentItem.position = Integer.parseInt(line.substring(10));
 102.240 -                            } catch (NumberFormatException e) {
 102.241 -                                // do not use ErrorManager because we are in the startup code
 102.242 -                                // and ErrorManager might not be ready
 102.243 -                                e.printStackTrace();
 102.244 -                            }
 102.245 -                        }
 102.246 -
 102.247 -                        if (currentItem != null) {
 102.248 -                            insertItem(currentItem, foundClasses);
 102.249 -                            currentItem = null;
 102.250 -                        }
 102.251 -
 102.252 -                        // Ignore blank lines and comments.
 102.253 -                        if (line.length() == 0) {
 102.254 -                            continue;
 102.255 -                        }
 102.256 -
 102.257 -                        boolean remove = false;
 102.258 -
 102.259 -                        if (line.charAt(0) == '#') {
 102.260 -                            if ((line.length() == 1) || (line.charAt(1) != '-')) {
 102.261 -                                continue;
 102.262 -                            }
 102.263 -
 102.264 -                            // line starting with #- is a sign to remove that class from lookup
 102.265 -                            remove = true;
 102.266 -                            line = line.substring(2);
 102.267 -                        }
 102.268 -
 102.269 -                        Class inst = null;
 102.270 -
 102.271 -                        try {
 102.272 -                            // Most lines are fully-qualified class names.
 102.273 -                            inst = Class.forName(line, false, loader);
 102.274 -                        } catch (ClassNotFoundException cnfe) {
 102.275 -                            if (remove) {
 102.276 -                                // if we are removing somthing and the something
 102.277 -                                // cannot be found it is ok to do nothing
 102.278 -                                continue;
 102.279 -                            } else {
 102.280 -                                // but if we are not removing just rethrow
 102.281 -                                throw cnfe;
 102.282 -                            }
 102.283 -                        }
 102.284 -
 102.285 -                        if (!clazz.isAssignableFrom(inst)) {
 102.286 -                            throw new ClassNotFoundException(clazzToString(inst) + " not a subclass of " + clazzToString(clazz)); // NOI18N
 102.287 -                        }
 102.288 -
 102.289 -                        if (remove) {
 102.290 -                            removeClasses.add(inst);
 102.291 -                        } else {
 102.292 -                            // create new item here, but do not put it into
 102.293 -                            // foundClasses array yet because following line
 102.294 -                            // might specify its position
 102.295 -                            currentItem = new Item();
 102.296 -                            currentItem.clazz = inst;
 102.297 -                        }
 102.298 -                    }
 102.299 -
 102.300 -                    if (currentItem != null) {
 102.301 -                        insertItem(currentItem, foundClasses);
 102.302 -                        currentItem = null;
 102.303 -                    }
 102.304 -                } finally {
 102.305 -                    is.close();
 102.306 -                }
 102.307 -            } catch (ClassNotFoundException ex) {
 102.308 -                LOGGER.log(Level.WARNING, null, ex);
 102.309 -            } catch (IOException ex) {
 102.310 -                LOGGER.log(Level.WARNING, null, ex);
 102.311 -            }
 102.312 -        }
 102.313 -
 102.314 -        LOGGER.log(Level.FINER, "Found impls of {0}: {1} and removed: {2} from: {3}", new Object[] {clazz.getName(), foundClasses, removeClasses, this});
 102.315 -
 102.316 -        foundClasses.removeAll(removeClasses);
 102.317 -
 102.318 -        for (Item item : foundClasses) {
 102.319 -            if (removeClasses.contains(item.clazz)) {
 102.320 -                continue;
 102.321 -            }
 102.322 -
 102.323 -            result.add(new P(item.clazz));
 102.324 -        }
 102.325 -    }
 102.326 -    private static String clazzToString(Class clazz) {
 102.327 -        return clazz.getName() + "@" + clazz.getClassLoader() + ":" + clazz.getProtectionDomain().getCodeSource().getLocation(); // NOI18N
 102.328 -    }
 102.329 -
 102.330 -    /**
 102.331 -     * Insert item to the list according to item.position value.
 102.332 -     */
 102.333 -    private void insertItem(Item item, List<Item> list) {
 102.334 -        // no position? -> add it to the end
 102.335 -        if (item.position == -1) {
 102.336 -            list.add(item);
 102.337 -
 102.338 -            return;
 102.339 -        }
 102.340 -
 102.341 -        int index = -1;
 102.342 -        for (Item i : list) {
 102.343 -            index++;
 102.344 -
 102.345 -            if (i.position == -1) {
 102.346 -                list.add(index, item);
 102.347 -
 102.348 -                return;
 102.349 -            } else {
 102.350 -                if (i.position > item.position) {
 102.351 -                    list.add(index, item);
 102.352 -
 102.353 -                    return;
 102.354 -                }
 102.355 -            }
 102.356 -        }
 102.357 -
 102.358 -        list.add(item);
 102.359 -    }
 102.360 -
 102.361 -    private static class Item {
 102.362 -        private Class clazz;
 102.363 -        private int position = -1;
 102.364 -        @Override
 102.365 -        public String toString() {
 102.366 -            return "MetaInfServicesLookup.Item[" + clazz.getName() + "]"; // NOI18N
 102.367 -        }
 102.368 -    }
 102.369 -
 102.370 -    /** Pair that holds name of a class and maybe the instance.
 102.371 -     */
 102.372 -    private static final class P extends AbstractLookup.Pair<Object> {
 102.373 -        /** May be one of three things:
 102.374 -         * 1. The implementation class which was named in the services file.
 102.375 -         * 2. An instance of it.
 102.376 -         * 3. Null, if creation of the instance resulted in an error.
 102.377 -         */
 102.378 -        private Object object;
 102.379 -
 102.380 -        public P(Class<?> clazz) {
 102.381 -            this.object = clazz;
 102.382 -        }
 102.383 -
 102.384 -        /** Finds the class.
 102.385 -         */
 102.386 -        private Class<? extends Object> clazz() {
 102.387 -            Object o = object;
 102.388 -
 102.389 -            if (o instanceof Class) {
 102.390 -                return (Class<? extends Object>) o;
 102.391 -            } else if (o != null) {
 102.392 -                return o.getClass();
 102.393 -            } else {
 102.394 -                // Broken.
 102.395 -                return Object.class;
 102.396 -            }
 102.397 -        }
 102.398 -
 102.399 -        @Override
 102.400 -        public boolean equals(Object o) {
 102.401 -            if (o instanceof P) {
 102.402 -                return ((P) o).clazz().equals(clazz());
 102.403 -            }
 102.404 -
 102.405 -            return false;
 102.406 -        }
 102.407 -
 102.408 -        @Override
 102.409 -        public int hashCode() {
 102.410 -            return clazz().hashCode();
 102.411 -        }
 102.412 -
 102.413 -        protected boolean instanceOf(Class<?> c) {
 102.414 -            return c.isAssignableFrom(clazz());
 102.415 -        }
 102.416 -
 102.417 -        public Class<?> getType() {
 102.418 -            return clazz();
 102.419 -        }
 102.420 -
 102.421 -        public Object getInstance() {
 102.422 -            Object o = object; // keeping local copy to avoid another
 102.423 -
 102.424 -            // thread to modify it under my hands
 102.425 -            if (o instanceof Class) {
 102.426 -                synchronized (o) { // o is Class and we will not create 
 102.427 -                                   // 2 instances of the same class
 102.428 -
 102.429 -                    try {
 102.430 -                        Class<?> c = ((Class) o);
 102.431 -                        o = null;
 102.432 -
 102.433 -                        synchronized (knownInstances) { // guards only the static cache
 102.434 -                            int size = knownInstances.size();
 102.435 -                            int index = c.hashCode() % size;
 102.436 -                            for (int i = 0; i < size; i++) {
 102.437 -                                Reference<Object> ref = knownInstances.get(index);
 102.438 -                                Object obj = ref == null ? null : ref.get();
 102.439 -                                if (obj == null) {
 102.440 -                                    break;
 102.441 -                                }
 102.442 -                                if (c == obj.getClass()) {
 102.443 -                                    o = obj;
 102.444 -                                    break;
 102.445 -                                }
 102.446 -                                if (++index == size) {
 102.447 -                                    index = 0;
 102.448 -                                }
 102.449 -                            }
 102.450 -                        }
 102.451 -
 102.452 -                        if (o == null) {
 102.453 -                            o = createInstance(c);
 102.454 -
 102.455 -                            synchronized (knownInstances) { // guards only the static cache
 102.456 -                                hashPut(o);
 102.457 -
 102.458 -                                int size = knownInstances.size();
 102.459 -                                if (knownInstancesCount > size * 2 / 3) {
 102.460 -                                    LOGGER.log(Level.CONFIG, "Cache of size {0} is 2/3 full. Rehashing.", size);
 102.461 -                                    HashSet<Reference<Object>> all = new HashSet<Reference<Object>>();
 102.462 -                                    all.addAll(knownInstances);
 102.463 -                                    for (int i = 0; i < size; i++) {
 102.464 -                                        knownInstances.set(i, null);
 102.465 -                                    }
 102.466 -                                    for (int i = 0; i < size; i++) {
 102.467 -                                        knownInstances.add(null);
 102.468 -                                    }
 102.469 -                                    knownInstancesCount = 0;
 102.470 -                                    for (Reference<Object> r : all) {
 102.471 -                                        if (r == null) {
 102.472 -                                            continue;
 102.473 -                                        }
 102.474 -                                        Object instance = r.get();
 102.475 -                                        if (instance == null) {
 102.476 -                                            continue;
 102.477 -                                        }
 102.478 -                                        hashPut(instance);
 102.479 -                                    }
 102.480 -                                }
 102.481 -
 102.482 -                            }
 102.483 -                        }
 102.484 -
 102.485 -                        // Do not assign to instance var unless there is a complete synch
 102.486 -                        // block between the newInstance and this line. Otherwise we could
 102.487 -                        // be assigning a half-constructed instance that another thread
 102.488 -                        // could see and return immediately.
 102.489 -                        object = o;
 102.490 -                    } catch (Exception ex) {
 102.491 -                        LOGGER.log(Level.WARNING, "Cannot create " + object, ex);
 102.492 -                        object = null;
 102.493 -                    } catch (ExceptionInInitializerError x) { // #174055
 102.494 -                        LOGGER.log(Level.WARNING, "Cannot create " + object, x);
 102.495 -                        object = null;
 102.496 -                    }
 102.497 -                }
 102.498 -            }
 102.499 -
 102.500 -            return object;
 102.501 -        }
 102.502 -
 102.503 -        public String getDisplayName() {
 102.504 -            return clazz().getName();
 102.505 -        }
 102.506 -
 102.507 -        public String getId() {
 102.508 -            return clazz().getName();
 102.509 -        }
 102.510 -
 102.511 -        protected boolean creatorOf(Object obj) {
 102.512 -            return obj == object;
 102.513 -        }
 102.514 -
 102.515 -        private static void hashPut(Object o) {
 102.516 -            Class<?> c = o.getClass();
 102.517 -            int size = knownInstances.size();
 102.518 -            int index = c.hashCode() % size;
 102.519 -            for (int i = 0; i < size; i++) {
 102.520 -                Reference<Object> ref = knownInstances.get(index);
 102.521 -                Object obj = ref == null ? null : ref.get();
 102.522 -                if (obj == null) {
 102.523 -                    knownInstances.set(index, new WeakReference<Object>(o));
 102.524 -                    knownInstancesCount++;
 102.525 -                    break;
 102.526 -                }
 102.527 -                if (++index == size) {
 102.528 -                    index = 0;
 102.529 -                }
 102.530 -            }
 102.531 -        }
 102.532 -
 102.533 -        private static boolean findSharedClassObjectSkip;
 102.534 -        private static Method findSharedClassObject;
 102.535 -        /** Basically does c.newInstance(), however the method is complicated
 102.536 -         * with a special behaviour for old and almost obsoleted NetBeans
 102.537 -         * class: SharedClassObject.
 102.538 -         */
 102.539 -        private static Object createInstance(Class<?> c) throws InstantiationException, IllegalAccessException {
 102.540 -            if (!findSharedClassObjectSkip) {
 102.541 -                try {
 102.542 -                    if (findSharedClassObject == null) {
 102.543 -                        Class<?> sco;
 102.544 -                        try {
 102.545 -                            sco = Class.forName("org.openide.util.SharedClassObject"); // NOI18N
 102.546 -                        } catch (ClassNotFoundException ex) {
 102.547 -                            findSharedClassObjectSkip = true;
 102.548 -                            return c.newInstance();
 102.549 -                        }
 102.550 -                        findSharedClassObject = sco.getMethod("findObject", Class.class, boolean.class);
 102.551 -                    }
 102.552 -                    if (findSharedClassObject.getReturnType().isAssignableFrom(c)) {
 102.553 -                        return findSharedClassObject.invoke(null, c, true);
 102.554 -                    }
 102.555 -                } catch (Exception problem) {
 102.556 -                    throw (InstantiationException)new InstantiationException(problem.getMessage()).initCause(problem);
 102.557 -                }
 102.558 -            }
 102.559 -            return c.newInstance();
 102.560 -        }
 102.561 -    }
 102.562 -}
   103.1 --- a/openide.util/src/org/openide/util/lookup/ProxyLookup.java	Thu Dec 10 19:23:25 2009 -0500
   103.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.3 @@ -1,980 +0,0 @@
   103.4 -/*
   103.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   103.6 - *
   103.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   103.8 - *
   103.9 - * The contents of this file are subject to the terms of either the GNU
  103.10 - * General Public License Version 2 only ("GPL") or the Common
  103.11 - * Development and Distribution License("CDDL") (collectively, the
  103.12 - * "License"). You may not use this file except in compliance with the
  103.13 - * License. You can obtain a copy of the License at
  103.14 - * http://www.netbeans.org/cddl-gplv2.html
  103.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  103.16 - * specific language governing permissions and limitations under the
  103.17 - * License.  When distributing the software, include this License Header
  103.18 - * Notice in each file and include the License file at
  103.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  103.20 - * particular file as subject to the "Classpath" exception as provided
  103.21 - * by Sun in the GPL Version 2 section of the License file that
  103.22 - * accompanied this code. If applicable, add the following below the
  103.23 - * License Header, with the fields enclosed by brackets [] replaced by
  103.24 - * your own identifying information:
  103.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  103.26 - *
  103.27 - * Contributor(s):
  103.28 - *
  103.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  103.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  103.31 - * Microsystems, Inc. All Rights Reserved.
  103.32 - *
  103.33 - * If you wish your version of this file to be governed by only the CDDL
  103.34 - * or only the GPL Version 2, indicate your decision by adding
  103.35 - * "[Contributor] elects to include this software in this distribution
  103.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  103.37 - * single choice of license, a recipient has the option to distribute
  103.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  103.39 - * to extend the choice of license to its licensees as provided above.
  103.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  103.41 - * Version 2 license, then the option applies only if the new code is
  103.42 - * made subject to such option by the copyright holder.
  103.43 - */
  103.44 -
  103.45 -package org.openide.util.lookup;
  103.46 -
  103.47 -import java.lang.ref.Reference;
  103.48 -import java.lang.ref.WeakReference;
  103.49 -import java.util.ArrayList;
  103.50 -import java.util.Arrays;
  103.51 -import java.util.Collection;
  103.52 -import java.util.Collections;
  103.53 -import java.util.HashMap;
  103.54 -import java.util.HashSet;
  103.55 -import java.util.IdentityHashMap;
  103.56 -import java.util.Iterator;
  103.57 -import java.util.List;
  103.58 -import java.util.Map;
  103.59 -import java.util.Map.Entry;
  103.60 -import java.util.Set;
  103.61 -import java.util.concurrent.Executor;
  103.62 -import javax.swing.event.EventListenerList;
  103.63 -import org.openide.util.Lookup;
  103.64 -import org.openide.util.LookupEvent;
  103.65 -import org.openide.util.LookupListener;
  103.66 -
  103.67 -/** Implementation of lookup that can delegate to others.
  103.68 - *
  103.69 - * @author  Jaroslav Tulach
  103.70 - * @since 1.9
  103.71 - */
  103.72 -public class ProxyLookup extends Lookup {
  103.73 -    /** data representing the state of the lookup */
  103.74 -    private ImmutableInternalData data;
  103.75 -
  103.76 -    /** Create a proxy to some other lookups.
  103.77 -     * @param lookups the initial delegates
  103.78 -     */
  103.79 -    public ProxyLookup(Lookup... lookups) {
  103.80 -        data = ImmutableInternalData.EMPTY.setLookupsNoFire(lookups, true);
  103.81 -    }
  103.82 -
  103.83 -    /**
  103.84 -     * Create a lookup initially proxying to no others.
  103.85 -     * Permits serializable subclasses.
  103.86 -     * @since 3.27
  103.87 -     */
  103.88 -    protected ProxyLookup() {
  103.89 -        data = ImmutableInternalData.EMPTY;
  103.90 -    }
  103.91 -
  103.92 -    @Override
  103.93 -    public synchronized String toString() {
  103.94 -        return "ProxyLookup(class=" + getClass() + ")->" + Arrays.asList(getData().getLookups(false)); // NOI18N
  103.95 -    }
  103.96 -
  103.97 -    /** Getter for the delegates.
  103.98 -    * @return the array of lookups we delegate to
  103.99 -    * @since 1.19
 103.100 -    */
 103.101 -    protected final Lookup[] getLookups() {
 103.102 -        synchronized (ProxyLookup.this) {
 103.103 -            return getData().getLookups(true);
 103.104 -        }
 103.105 -    }
 103.106 -
 103.107 -    private Set<Lookup> identityHashSet(Collection<Lookup> current) {
 103.108 -        Map<Lookup,Void> map = new IdentityHashMap<Lookup, Void>();
 103.109 -        for (Lookup lookup : current) {
 103.110 -            map.put(lookup, null);
 103.111 -        }
 103.112 -        return map.keySet();
 103.113 -    }
 103.114 -    
 103.115 -    /**
 103.116 -     * Changes the delegates.
 103.117 -     *
 103.118 -     * @param lookups the new lookups to delegate to
 103.119 -     * @since 1.19 protected
 103.120 -     */
 103.121 -    protected final void setLookups(Lookup... lookups) {
 103.122 -        setLookups(null, lookups);
 103.123 -    }
 103.124 -    
 103.125 -    /**
 103.126 -     * Changes the delegates immediatelly, notifies the listeners in provided
 103.127 -     * executor, potentially later.
 103.128 -     *
 103.129 -     * @param lookups the new lookups to delegate to
 103.130 -     * @param notifyIn executor to deliver the notification to listeners or null
 103.131 -     * @since 7.16
 103.132 -     */
 103.133 -    protected final void setLookups(Executor notifyIn, Lookup... lookups) {
 103.134 -        Collection<Reference<R>> arr;
 103.135 -        Set<Lookup> newL;
 103.136 -        Set<Lookup> current;
 103.137 -        Lookup[] old;
 103.138 -        
 103.139 -        Map<Result,LookupListener> toRemove = new IdentityHashMap<Lookup.Result, LookupListener>();
 103.140 -        Map<Result,LookupListener> toAdd = new IdentityHashMap<Lookup.Result, LookupListener>();
 103.141 -        
 103.142 -        ImmutableInternalData orig;
 103.143 -        synchronized (ProxyLookup.this) {
 103.144 -            orig = getData();
 103.145 -            ImmutableInternalData newData = getData().setLookupsNoFire(lookups, false);
 103.146 -            if (newData == getData()) {
 103.147 -                return;
 103.148 -            }
 103.149 -            arr = setData(newData, lookups, toAdd, toRemove);
 103.150 -        }
 103.151 -        
 103.152 -        // better to do this later than in synchronized block
 103.153 -        for (Map.Entry<Result, LookupListener> e : toRemove.entrySet()) {
 103.154 -            e.getKey().removeLookupListener(e.getValue());
 103.155 -        }
 103.156 -        for (Map.Entry<Result, LookupListener> e : toAdd.entrySet()) {
 103.157 -            e.getKey().addLookupListener(e.getValue());
 103.158 -        }
 103.159 -
 103.160 -
 103.161 -        // this cannot be done from the synchronized block
 103.162 -        final ArrayList<Object> evAndListeners = new ArrayList<Object>();
 103.163 -        for (Reference<R> ref : arr) {
 103.164 -            R<?> r = ref.get();
 103.165 -            if (r != null) {
 103.166 -                r.collectFires(evAndListeners);
 103.167 -            }
 103.168 -        }
 103.169 -        
 103.170 -        class Notify implements Runnable {
 103.171 -            public void run() {
 103.172 -                Iterator it = evAndListeners.iterator();
 103.173 -                while (it.hasNext()) {
 103.174 -                    LookupEvent ev = (LookupEvent)it.next();
 103.175 -                    LookupListener l = (LookupListener)it.next();
 103.176 -                    l.resultChanged(ev);
 103.177 -                }
 103.178 -            }
 103.179 -        }
 103.180 -        Notify n = new Notify();
 103.181 -        if (notifyIn == null) {
 103.182 -            n.run();
 103.183 -        } else {
 103.184 -            notifyIn.execute(n);
 103.185 -        }
 103.186 -    }
 103.187 -
 103.188 -    /** Notifies subclasses that a query is about to be processed.
 103.189 -     * Subclasses can update its state before the actual processing
 103.190 -     * begins. It is allowed to call <code>setLookups</code> method
 103.191 -     * to change/update the set of objects the proxy delegates to.
 103.192 -     *
 103.193 -     * @param template the template of the query
 103.194 -     * @since 1.31
 103.195 -     */
 103.196 -    protected void beforeLookup(Template<?> template) {
 103.197 -    }
 103.198 -
 103.199 -    public final <T> T lookup(Class<T> clazz) {
 103.200 -        beforeLookup(new Template<T>(clazz));
 103.201 -
 103.202 -        Lookup[] tmpLkps;
 103.203 -        synchronized (ProxyLookup.this) {
 103.204 -            tmpLkps = getData().getLookups(false);
 103.205 -        }
 103.206 -
 103.207 -        for (int i = 0; i < tmpLkps.length; i++) {
 103.208 -            T o = tmpLkps[i].lookup(clazz);
 103.209 -
 103.210 -            if (o != null) {
 103.211 -                return o;
 103.212 -            }
 103.213 -        }
 103.214 -
 103.215 -        return null;
 103.216 -    }
 103.217 -
 103.218 -    @Override
 103.219 -    public final <T> Item<T> lookupItem(Template<T> template) {
 103.220 -        beforeLookup(template);
 103.221 -
 103.222 -        Lookup[] tmpLkps; 
 103.223 -        synchronized (ProxyLookup.this) {
 103.224 -            tmpLkps = getData().getLookups(false);
 103.225 -        }
 103.226 -
 103.227 -        for (int i = 0; i < tmpLkps.length; i++) {
 103.228 -            Item<T> o = tmpLkps[i].lookupItem(template);
 103.229 -
 103.230 -            if (o != null) {
 103.231 -                return o;
 103.232 -            }
 103.233 -        }
 103.234 -
 103.235 -        return null;
 103.236 -    }
 103.237 -
 103.238 -    @SuppressWarnings("unchecked")
 103.239 -    private static <T> R<T> convertResult(R r) {
 103.240 -        return (R<T>)r;
 103.241 -    }
 103.242 -
 103.243 -    public final <T> Result<T> lookup(Lookup.Template<T> template) {
 103.244 -        synchronized (ProxyLookup.this) {
 103.245 -            ImmutableInternalData[] res = { null };
 103.246 -            R<T> newR = getData().findResult(this, res, template);
 103.247 -            setData(res[0], getData().getLookups(false), null, null);
 103.248 -            return newR;
 103.249 -        }
 103.250 -    }
 103.251 -
 103.252 -    /** Unregisters a template from the has map.
 103.253 -     */
 103.254 -    private final void unregisterTemplate(Template<?> template) {
 103.255 -        synchronized (ProxyLookup.this) {
 103.256 -            ImmutableInternalData id = getData();
 103.257 -            if (id == null) {
 103.258 -                return;
 103.259 -            }
 103.260 -            setData(id.removeTemplate(this, template), getData().getLookups(false), null, null);
 103.261 -        }
 103.262 -    }
 103.263 -
 103.264 -    private ImmutableInternalData getData() {
 103.265 -        assert Thread.holdsLock(this);
 103.266 -        return data;
 103.267 -    }
 103.268 -
 103.269 -    private Collection<Reference<R>> setData(
 103.270 -        ImmutableInternalData newData, Lookup[] current, 
 103.271 -        Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
 103.272 -    ) {
 103.273 -        assert Thread.holdsLock(ProxyLookup.this);
 103.274 -        assert newData != null;
 103.275 -        
 103.276 -        ImmutableInternalData previous = this.getData();
 103.277 -        
 103.278 -        if (previous == newData) {
 103.279 -            return Collections.emptyList();
 103.280 -        }
 103.281 -
 103.282 -        if (newData.isEmpty()) {
 103.283 -            this.setData(newData);
 103.284 -            // no affected results => exit
 103.285 -            return Collections.emptyList();
 103.286 -        }
 103.287 -
 103.288 -        Collection<Reference<R>> arr = newData.references();
 103.289 -
 103.290 -        Set<Lookup> removed = identityHashSet(previous.getLookupsList());
 103.291 -        Set<Lookup> currentSet = identityHashSet(Arrays.asList(current));
 103.292 -        Set<Lookup> newL = identityHashSet(currentSet);
 103.293 -        removed.removeAll(currentSet); // current contains just those lookups that have disappeared
 103.294 -        newL.removeAll(previous.getLookupsList()); // really new lookups
 103.295 -
 103.296 -        for (Reference<R> ref : arr) {
 103.297 -            R<?> r = ref.get();
 103.298 -            if (r != null) {
 103.299 -                r.lookupChange(newData, current, previous, newL, removed, toAdd, toRemove);
 103.300 -                if (this.getData() != previous) {
 103.301 -                    // the data were changed by an re-entrant call
 103.302 -                    // skip any other change processing, as it is not needed
 103.303 -                    // anymore
 103.304 -                }
 103.305 -            }
 103.306 -        }
 103.307 -                for (Reference<R> ref : arr) {
 103.308 -            R<?> r = ref.get();
 103.309 -            if (r != null) {
 103.310 -                r.data = newData;
 103.311 -            }
 103.312 -        }
 103.313 -        this.setData(newData);
 103.314 -        return arr;
 103.315 -    }
 103.316 -
 103.317 -    private void setData(ImmutableInternalData data) {
 103.318 -        this.data = data;
 103.319 -    }
 103.320 -
 103.321 -    /** Result of a lookup request. Allows access to single object
 103.322 -     * that was found (not too useful) and also to all objects found
 103.323 -     * (more useful).
 103.324 -     */
 103.325 -    private static final class R<T> extends WaitableResult<T> {
 103.326 -        /** weak listener & result */
 103.327 -        private final WeakResult<T> weakL;
 103.328 -        
 103.329 -        /** list of listeners added */
 103.330 -        private javax.swing.event.EventListenerList listeners;
 103.331 -
 103.332 -        /** collection of Objects */
 103.333 -        private Collection[] cache;
 103.334 -
 103.335 -        
 103.336 -        /** associated lookup */
 103.337 -        private ImmutableInternalData data;
 103.338 -
 103.339 -        /** Constructor.
 103.340 -         */
 103.341 -        public R(ProxyLookup proxy, Lookup.Template<T> t) {
 103.342 -            this.weakL = new WeakResult<T>(proxy, this, t);
 103.343 -        }
 103.344 -        
 103.345 -        private ProxyLookup proxy() {
 103.346 -            return weakL.result.proxy;
 103.347 -        }
 103.348 -
 103.349 -        @SuppressWarnings("unchecked")
 103.350 -        private Result<T>[] newResults(int len) {
 103.351 -            return new Result[len];
 103.352 -        }
 103.353 -        
 103.354 -        @Override
 103.355 -        protected void finalize() {
 103.356 -            weakL.result.run();
 103.357 -        }
 103.358 -
 103.359 -        /** initializes the results
 103.360 -         */
 103.361 -        private Result<T>[] initResults() {
 103.362 -            BIG_LOOP: for (;;) {
 103.363 -                Lookup[] myLkps;
 103.364 -                ImmutableInternalData current;
 103.365 -                synchronized (proxy()) {
 103.366 -                    if (weakL.getResults() != null) {
 103.367 -                        return weakL.getResults();
 103.368 -                    }
 103.369 -                    myLkps = data.getLookups(false);
 103.370 -                    current = data;
 103.371 -                }
 103.372 -
 103.373 -                Result<T>[] arr = newResults(myLkps.length);
 103.374 -
 103.375 -                for (int i = 0; i < arr.length; i++) {
 103.376 -                    arr[i] = myLkps[i].lookup(weakL.result.template);
 103.377 -                }
 103.378 -
 103.379 -                synchronized (proxy()) {
 103.380 -                    if (current != data) {
 103.381 -                        continue;
 103.382 -                    }
 103.383 -                    
 103.384 -                    Lookup[] currentLkps = data.getLookups(false);
 103.385 -                    if (currentLkps.length != myLkps.length) {
 103.386 -                        continue BIG_LOOP;
 103.387 -                    }
 103.388 -                    for (int i = 0; i < currentLkps.length; i++) {
 103.389 -                        if (currentLkps[i] != myLkps[i]) {
 103.390 -                            continue BIG_LOOP;
 103.391 -                        }
 103.392 -                    }
 103.393 -                    
 103.394 -                    // some other thread might compute the result mean while. 
 103.395 -                    // if not finish the computation yourself
 103.396 -                    if (weakL.getResults() != null) {
 103.397 -                        return weakL.getResults();
 103.398 -                    }
 103.399 -
 103.400 -                    weakL.setResults(arr);
 103.401 -                }
 103.402 -                for (int i = 0; i < arr.length; i++) {
 103.403 -                    arr[i].addLookupListener(weakL);
 103.404 -                }
 103.405 -                return arr;
 103.406 -            }
 103.407 -        }
 103.408 -
 103.409 -        /** Called when there is a change in the list of proxied lookups.
 103.410 -         * @param added set of added lookups
 103.411 -         * @param remove set of removed lookups
 103.412 -         * @param current array of current lookups
 103.413 -         */
 103.414 -        final void lookupChange(
 103.415 -            ImmutableInternalData newData, Lookup[] current, ImmutableInternalData oldData,
 103.416 -            Set<Lookup> added, Set<Lookup> removed,
 103.417 -            Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
 103.418 -        ) {
 103.419 -            if (weakL.getResults() == null) {
 103.420 -                // not computed yet, do not need to do anything
 103.421 -                return;
 103.422 -            }
 103.423 -
 103.424 -            Lookup[] old = oldData.getLookups(false);
 103.425 -
 103.426 -            // map (Lookup, Lookup.Result)
 103.427 -            Map<Lookup,Result<T>> map = new IdentityHashMap<Lookup,Result<T>>(old.length * 2);
 103.428 -
 103.429 -            for (int i = 0; i < old.length; i++) {
 103.430 -                if (removed.contains(old[i])) {
 103.431 -                    // removed lookup
 103.432 -                    if (toRemove != null) {
 103.433 -                        toRemove.put(weakL.getResults()[i], weakL);
 103.434 -                    }
 103.435 -                } else {
 103.436 -                    // remember the association
 103.437 -                    map.put(old[i], weakL.getResults()[i]);
 103.438 -                }
 103.439 -            }
 103.440 -
 103.441 -            Lookup.Result<T>[] arr = newResults(current.length);
 103.442 -
 103.443 -            for (int i = 0; i < current.length; i++) {
 103.444 -                if (added.contains(current[i])) {
 103.445 -                    // new lookup
 103.446 -                    arr[i] = current[i].lookup(weakL.result.template);
 103.447 -                    if (toAdd != null) {
 103.448 -                        toAdd.put(arr[i], weakL);
 103.449 -                    }
 103.450 -                } else {
 103.451 -                    // old lookup
 103.452 -                    arr[i] = map.get(current[i]);
 103.453 -
 103.454 -                    if (arr[i] == null) {
 103.455 -                        // assert
 103.456 -                        throw new IllegalStateException();
 103.457 -                    }
 103.458 -                }
 103.459 -            }
 103.460 -
 103.461 -            // remember the new results
 103.462 -            weakL.setResults(arr);
 103.463 -        }
 103.464 -
 103.465 -        /** Just delegates.
 103.466 -         */
 103.467 -        public void addLookupListener(LookupListener l) {
 103.468 -            synchronized (proxy()) {
 103.469 -                if (listeners == null) {
 103.470 -                    listeners = new EventListenerList();
 103.471 -                }
 103.472 -            }
 103.473 -
 103.474 -            listeners.add(LookupListener.class, l);
 103.475 -            initResults();
 103.476 -        }
 103.477 -
 103.478 -        /** Just delegates.
 103.479 -         */
 103.480 -        public void removeLookupListener(LookupListener l) {
 103.481 -            if (listeners != null) {
 103.482 -                listeners.remove(LookupListener.class, l);
 103.483 -            }
 103.484 -        }
 103.485 -
 103.486 -        /** Access to all instances in the result.
 103.487 -         * @return collection of all instances
 103.488 -         */
 103.489 -        @SuppressWarnings("unchecked")
 103.490 -        public java.util.Collection<T> allInstances() {
 103.491 -            return computeResult(0);
 103.492 -        }
 103.493 -
 103.494 -        /** Classes of all results. Set of the most concreate classes
 103.495 -         * that are registered in the system.
 103.496 -         * @return set of Class objects
 103.497 -         */
 103.498 -        @SuppressWarnings("unchecked")
 103.499 -        @Override
 103.500 -        public java.util.Set<Class<? extends T>> allClasses() {
 103.501 -            return (java.util.Set<Class<? extends T>>) computeResult(1);
 103.502 -        }
 103.503 -
 103.504 -        /** All registered items. The collection of all pairs of
 103.505 -         * ii and their classes.
 103.506 -         * @return collection of Lookup.Item
 103.507 -         */
 103.508 -        @SuppressWarnings("unchecked")
 103.509 -        @Override
 103.510 -        public java.util.Collection<? extends Item<T>> allItems() {
 103.511 -            return computeResult(2);
 103.512 -        }
 103.513 -
 103.514 -        /** Computes results from proxied lookups.
 103.515 -         * @param indexToCache 0 = allInstances, 1 = allClasses, 2 = allItems
 103.516 -         * @return the collection or set of the objects
 103.517 -         */
 103.518 -        private java.util.Collection computeResult(int indexToCache) {
 103.519 -            // results to use
 103.520 -            Lookup.Result<T>[] arr = myBeforeLookup();
 103.521 -
 103.522 -            // if the call to beforeLookup resulted in deletion of caches
 103.523 -            synchronized (proxy()) {
 103.524 -                Collection[] cc = getCache();
 103.525 -                if (cc != null && cc != NO_CACHE) {
 103.526 -                    Collection result = cc[indexToCache];
 103.527 -                    if (result != null) {
 103.528 -                        return result;
 103.529 -                    }
 103.530 -                }
 103.531 -            }
 103.532 -
 103.533 -            // initialize the collection to hold result
 103.534 -            Collection<Object> compute;
 103.535 -            Collection<Object> ret;
 103.536 -
 103.537 -            if (indexToCache == 1) {
 103.538 -                HashSet<Object> s = new HashSet<Object>();
 103.539 -                compute = s;
 103.540 -                ret = Collections.unmodifiableSet(s);
 103.541 -            } else {
 103.542 -                List<Object> l = new ArrayList<Object>(arr.length * 2);
 103.543 -                compute = l;
 103.544 -                ret = Collections.unmodifiableList(l);
 103.545 -            }
 103.546 -
 103.547 -            // fill the collection
 103.548 -            for (int i = 0; i < arr.length; i++) {
 103.549 -                switch (indexToCache) {
 103.550 -                case 0:
 103.551 -                    compute.addAll(arr[i].allInstances());
 103.552 -                    break;
 103.553 -                case 1:
 103.554 -                    compute.addAll(arr[i].allClasses());
 103.555 -                    break;
 103.556 -                case 2:
 103.557 -                    compute.addAll(arr[i].allItems());
 103.558 -                    break;
 103.559 -                default:
 103.560 -                    assert false : "Wrong index: " + indexToCache;
 103.561 -                }
 103.562 -            }
 103.563 -            
 103.564 -            
 103.565 -
 103.566 -            synchronized (proxy()) {
 103.567 -                Collection[] cc = getCache();
 103.568 -                if (cc == null || cc == NO_CACHE) {
 103.569 -                    // initialize the cache to indicate this result is in use
 103.570 -                    setCache(cc = new Collection[3]);
 103.571 -                }
 103.572 -                
 103.573 -                if (arr == weakL.getResults()) {
 103.574 -                    // updates the results, if the results have not been
 103.575 -                    // changed during the computation of allInstances
 103.576 -                    cc[indexToCache] = ret;
 103.577 -                }
 103.578 -            }
 103.579 -
 103.580 -            return ret;
 103.581 -        }
 103.582 -
 103.583 -        /** When the result changes, fire the event.
 103.584 -         */
 103.585 -        public void resultChanged(LookupEvent ev) {
 103.586 -            collectFires(null);
 103.587 -        }
 103.588 -        
 103.589 -        protected void collectFires(Collection<Object> evAndListeners) {
 103.590 -            boolean modified = true;
 103.591 -
 103.592 -            try {
 103.593 -                // clear cached instances
 103.594 -                Collection oldItems;
 103.595 -                Collection oldInstances;
 103.596 -                synchronized (proxy()) {
 103.597 -                    final Collection[] cc = getCache();
 103.598 -                    if (cc == NO_CACHE) {
 103.599 -                        return;
 103.600 -                    }
 103.601 -
 103.602 -                    oldInstances = cc == null ? null : cc[0];
 103.603 -                    oldItems = cc == null ? null : cc[2];
 103.604 -
 103.605 -
 103.606 -                    if (listeners == null || listeners.getListenerCount() == 0) {
 103.607 -                        // clear the cache
 103.608 -                        setCache(new Collection[3]);
 103.609 -                        return;
 103.610 -                    }
 103.611 -
 103.612 -                    // ignore events if they arrive as a result of call to allItems
 103.613 -                    // or allInstances, bellow...
 103.614 -                    setCache(NO_CACHE);
 103.615 -                }
 103.616 -
 103.617 -                if (oldItems != null) {
 103.618 -                    Collection newItems = allItems();
 103.619 -                    if (oldItems.equals(newItems)) {
 103.620 -                        modified = false;
 103.621 -                    }
 103.622 -                } else {
 103.623 -                    if (oldInstances != null) {
 103.624 -                        Collection newInstances = allInstances();
 103.625 -                        if (oldInstances.equals(newInstances)) {
 103.626 -                            modified = false;
 103.627 -                        }
 103.628 -                    } else {
 103.629 -                        synchronized (proxy()) {
 103.630 -                            if (getCache() == NO_CACHE) {
 103.631 -                                // we have to initialize the cache
 103.632 -                                // to show that the result has been initialized
 103.633 -                                setCache(new Collection[3]);
 103.634 -                            }
 103.635 -                        }
 103.636 -                    }
 103.637 -                }
 103.638 -            } finally {
 103.639 -                synchronized (proxy()) {
 103.640 -                    if (getCache() == NO_CACHE) {
 103.641 -                        setCache(null);
 103.642 -                    }
 103.643 -                }
 103.644 -            }
 103.645 -            
 103.646 -            if (modified) {
 103.647 -                LookupEvent ev = new LookupEvent(this);
 103.648 -                AbstractLookup.notifyListeners(listeners.getListenerList(), ev, evAndListeners);
 103.649 -            }
 103.650 -        }
 103.651 -
 103.652 -        /** Implementation of my before lookup.
 103.653 -         * @return results to work on.
 103.654 -         */
 103.655 -        private Lookup.Result<T>[] myBeforeLookup() {
 103.656 -            Template<T> template = weakL.result.template;
 103.657 -            
 103.658 -            proxy().beforeLookup(template);
 103.659 -
 103.660 -            Lookup.Result<T>[] arr = initResults();
 103.661 -
 103.662 -            // invoke update on the results
 103.663 -            for (int i = 0; i < arr.length; i++) {
 103.664 -                if (arr[i] instanceof WaitableResult) {
 103.665 -                    WaitableResult w = (WaitableResult) arr[i];
 103.666 -                    w.beforeLookup(template);
 103.667 -                }
 103.668 -            }
 103.669 -
 103.670 -            return arr;
 103.671 -        }
 103.672 -
 103.673 -        /** Used by proxy results to synchronize before lookup.
 103.674 -         */
 103.675 -        protected void beforeLookup(Lookup.Template t) {
 103.676 -            if (t.getType() == weakL.result.template.getType()) {
 103.677 -                myBeforeLookup();
 103.678 -            }
 103.679 -        }
 103.680 -
 103.681 -        private Collection[] getCache() {
 103.682 -            return cache;
 103.683 -        }
 103.684 -
 103.685 -        private void setCache(Collection[] cache) {
 103.686 -            assert Thread.holdsLock(proxy());
 103.687 -            this.cache = cache;
 103.688 -        }
 103.689 -        private static final Collection[] NO_CACHE = new Collection[0];
 103.690 -    }
 103.691 -    private static final class WeakRef<T> extends WeakReference<R> implements Runnable {
 103.692 -        final WeakResult<T> result;
 103.693 -        final ProxyLookup proxy;
 103.694 -        final Template<T> template;
 103.695 -        
 103.696 -        public WeakRef(R r, WeakResult<T> result, ProxyLookup proxy, Template<T> template) {
 103.697 -            super(r);
 103.698 -            this.result = result;
 103.699 -            this.template = template;
 103.700 -            this.proxy = proxy;
 103.701 -        }
 103.702 -
 103.703 -        public void run() {
 103.704 -            result.removeListeners();
 103.705 -            proxy.unregisterTemplate(template);
 103.706 -        }
 103.707 -    }
 103.708 -    
 103.709 -    
 103.710 -    private static final class WeakResult<T> extends WaitableResult<T> implements LookupListener, Runnable {
 103.711 -        /** all results */
 103.712 -        private Lookup.Result<T>[] results;
 103.713 -        private final WeakRef<T> result;
 103.714 -        
 103.715 -        public WeakResult(ProxyLookup proxy, R r, Template<T> t) {
 103.716 -            this.result = new WeakRef<T>(r, this, proxy, t);
 103.717 -        }
 103.718 -        
 103.719 -        final void removeListeners() {
 103.720 -            Lookup.Result<T>[] arr = this.getResults();
 103.721 -            if (arr == null) {
 103.722 -                return;
 103.723 -            }
 103.724 -
 103.725 -            for(int i = 0; i < arr.length; i++) {
 103.726 -                arr[i].removeLookupListener(this);
 103.727 -            }
 103.728 -        }
 103.729 -
 103.730 -        protected void beforeLookup(Lookup.Template t) {
 103.731 -            R r = result.get();
 103.732 -            if (r != null) {
 103.733 -                r.beforeLookup(t);
 103.734 -            } else {
 103.735 -                removeListeners();
 103.736 -            }
 103.737 -        }
 103.738 -
 103.739 -        protected void collectFires(Collection<Object> evAndListeners) {
 103.740 -            R<?> r = result.get();
 103.741 -            if (r != null) {
 103.742 -                r.collectFires(evAndListeners);
 103.743 -            } else {
 103.744 -                removeListeners();
 103.745 -            }
 103.746 -        }
 103.747 -
 103.748 -        public void addLookupListener(LookupListener l) {
 103.749 -            assert false;
 103.750 -        }
 103.751 -
 103.752 -        public void removeLookupListener(LookupListener l) {
 103.753 -            assert false;
 103.754 -        }
 103.755 -
 103.756 -        public Collection<T> allInstances() {
 103.757 -            assert false;
 103.758 -            return null;
 103.759 -        }
 103.760 -
 103.761 -        public void resultChanged(LookupEvent ev) {
 103.762 -            R r = result.get();
 103.763 -            if (r != null) {
 103.764 -                r.resultChanged(ev);
 103.765 -            } else {
 103.766 -                removeListeners();
 103.767 -            }
 103.768 -        }
 103.769 -
 103.770 -        @Override
 103.771 -        public Collection<? extends Item<T>> allItems() {
 103.772 -            assert false;
 103.773 -            return null;
 103.774 -        }
 103.775 -
 103.776 -        @Override
 103.777 -        public Set<Class<? extends T>> allClasses() {
 103.778 -            assert false;
 103.779 -            return null;
 103.780 -        }
 103.781 -
 103.782 -        public void run() {
 103.783 -            removeListeners();
 103.784 -        }
 103.785 -
 103.786 -        private Lookup.Result<T>[] getResults() {
 103.787 -            return results;
 103.788 -        }
 103.789 -
 103.790 -        private void setResults(Lookup.Result<T>[] results) {
 103.791 -            this.results = results;
 103.792 -        }
 103.793 -    } // end of WeakResult
 103.794 -    
 103.795 -    static abstract class ImmutableInternalData extends Object {
 103.796 -        static final ImmutableInternalData EMPTY = new EmptyInternalData();
 103.797 -        static final Lookup[] EMPTY_ARR = new Lookup[0];
 103.798 -
 103.799 -        
 103.800 -        protected ImmutableInternalData() {
 103.801 -        }
 103.802 -        
 103.803 -        public static ImmutableInternalData create(Object lkp, Map<Template, Reference<R>> results) {
 103.804 -            if (results.size() == 0 && lkp == EMPTY_ARR) {
 103.805 -                return EMPTY;
 103.806 -            }
 103.807 -            if (results.size() == 1) {
 103.808 -                Entry<Template,Reference<R>> e = results.entrySet().iterator().next();
 103.809 -                return new SingleInternalData(lkp, e.getKey(), e.getValue());
 103.810 -            }
 103.811 -            
 103.812 -            return new RealInternalData(lkp, results);
 103.813 -        }
 103.814 -
 103.815 -        protected abstract boolean isEmpty();
 103.816 -        protected abstract Map<Template, Reference<R>> getResults();
 103.817 -        protected abstract Object getRawLookups();
 103.818 -
 103.819 -        final Collection<Reference<R>> references() {
 103.820 -            return getResults().values();
 103.821 -        }
 103.822 -        
 103.823 -        final <T> ImmutableInternalData removeTemplate(ProxyLookup proxy, Template<T> template) {
 103.824 -            if (getResults().containsKey(template)) {
 103.825 -                HashMap<Template,Reference<R>> c = new HashMap<Template, Reference<ProxyLookup.R>>(getResults());
 103.826 -                Reference<R> ref = c.remove(template);
 103.827 -                if (ref != null && ref.get() != null) {
 103.828 -                    // seems like there is a reference to a result for this template
 103.829 -                    // thta is still alive
 103.830 -                    return this;
 103.831 -                }
 103.832 -                return create(getRawLookups(), c);
 103.833 -            } else {
 103.834 -                return this;
 103.835 -            }
 103.836 -        }
 103.837 -        
 103.838 -        <T> R<T> findResult(ProxyLookup proxy, ImmutableInternalData[] newData, Template<T> template) {
 103.839 -            assert Thread.holdsLock(proxy);
 103.840 -            
 103.841 -            Map<Template,Reference<R>> map = getResults();
 103.842 -            
 103.843 -            Reference<R> ref = map.get(template);
 103.844 -            R r = (ref == null) ? null : ref.get();
 103.845 -
 103.846 -            if (r != null) {
 103.847 -                newData[0] = this;
 103.848 -                return convertResult(r);
 103.849 -            }
 103.850 -            
 103.851 -            HashMap<Template, Reference<R>> res = new HashMap<Template, Reference<R>>(map);
 103.852 -            R<T> newR = new R<T>(proxy, template);
 103.853 -            res.put(template, new java.lang.ref.SoftReference<R>(newR));
 103.854 -            newR.data = newData[0] = create(getRawLookups(), res);
 103.855 -            return newR;
 103.856 -        }
 103.857 -        final ImmutableInternalData setLookupsNoFire(Lookup[] lookups, boolean skipCheck) {
 103.858 -            Object l;
 103.859 -            
 103.860 -            if (!skipCheck) {
 103.861 -                Lookup[] previous = getLookups(false);
 103.862 -                if (previous == lookups) {
 103.863 -                    return this;
 103.864 -                }
 103.865 -            
 103.866 -                if (previous.length == lookups.length) {
 103.867 -                    int same = 0;
 103.868 -                    for (int i = 0; i < previous.length; i++) {
 103.869 -                        if (lookups[i] != previous[i]) {
 103.870 -                            break;
 103.871 -                        }
 103.872 -                        same++;
 103.873 -                    }
 103.874 -                    if (same == previous.length) {
 103.875 -                        return this;
 103.876 -                    }
 103.877 -                }
 103.878 -            }
 103.879 -            
 103.880 -            if (lookups.length == 1) {
 103.881 -                l = lookups[0];
 103.882 -                assert l != null : "Cannot assign null delegate";
 103.883 -            } else {
 103.884 -                if (lookups.length == 0) {
 103.885 -                    l = EMPTY_ARR;
 103.886 -                } else {
 103.887 -                    l = lookups.clone();
 103.888 -                }
 103.889 -            }
 103.890 -            
 103.891 -            if (isEmpty() && l == EMPTY_ARR) {
 103.892 -                return this;
 103.893 -            }
 103.894 -            
 103.895 -            return create(l, getResults());
 103.896 -        }
 103.897 -        final Lookup[] getLookups(boolean clone) {
 103.898 -            Object l = this.getRawLookups();
 103.899 -            if (l instanceof Lookup) {
 103.900 -                return new Lookup[] { (Lookup)l };
 103.901 -            } else {
 103.902 -                Lookup[] arr = (Lookup[])l;
 103.903 -                if (clone) {
 103.904 -                    arr = arr.clone();
 103.905 -                }
 103.906 -                return arr;
 103.907 -            }
 103.908 -        }
 103.909 -        final List<Lookup> getLookupsList() {
 103.910 -            return Arrays.asList(getLookups(false));            
 103.911 -        }
 103.912 -
 103.913 -    } // end of ImmutableInternalData
 103.914 -    
 103.915 -    private static final class SingleInternalData extends ImmutableInternalData {
 103.916 -        /** lookups to delegate to (either Lookup or array of Lookups) */
 103.917 -        private final Object lookups;
 103.918 -        private final Template template;
 103.919 -        private final Reference<ProxyLookup.R> result;
 103.920 -                
 103.921 -        public SingleInternalData(Object lookups, Template<?> template, Reference<ProxyLookup.R> result) {
 103.922 -            this.lookups = lookups;
 103.923 -            this.template = template;
 103.924 -            this.result = result;
 103.925 -        }
 103.926 -
 103.927 -        protected final boolean isEmpty() {
 103.928 -            return false;
 103.929 -        }
 103.930 -
 103.931 -        protected Map<Template, Reference<R>> getResults() {
 103.932 -            return Collections.singletonMap(template, result);
 103.933 -        }
 103.934 -        
 103.935 -        protected Object getRawLookups() {
 103.936 -            return lookups;
 103.937 -        }
 103.938 -    }
 103.939 -    private static final class RealInternalData extends ImmutableInternalData {
 103.940 -        /** lookups to delegate to (either Lookup or array of Lookups) */
 103.941 -        private final Object lookups;
 103.942 -
 103.943 -        /** map of templates to currently active results */
 103.944 -        private final Map<Template,Reference<R>> results;
 103.945 -
 103.946 -        public RealInternalData(Object lookups, Map<Template, Reference<ProxyLookup.R>> results) {
 103.947 -            this.results = results;
 103.948 -            this.lookups = lookups;
 103.949 -        }
 103.950 -
 103.951 -        protected final boolean isEmpty() {
 103.952 -            return false;
 103.953 -        }
 103.954 -
 103.955 -        protected Map<Template, Reference<R>> getResults() {
 103.956 -            boolean strict = false;
 103.957 -            assert strict = true;
 103.958 -            return strict ? Collections.unmodifiableMap(results) : results;
 103.959 -        }
 103.960 -        
 103.961 -        protected Object getRawLookups() {
 103.962 -            return lookups;
 103.963 -        }
 103.964 -    }
 103.965 -    
 103.966 -    private static final class EmptyInternalData extends ImmutableInternalData {
 103.967 -        EmptyInternalData() {
 103.968 -        }
 103.969 -
 103.970 -        protected final boolean isEmpty() {
 103.971 -            return true;
 103.972 -        }
 103.973 -
 103.974 -        protected Map<Template, Reference<R>> getResults() {
 103.975 -            return Collections.emptyMap();
 103.976 -        }
 103.977 -
 103.978 -        @Override
 103.979 -        protected Object getRawLookups() {
 103.980 -            return EMPTY_ARR;
 103.981 -        }
 103.982 -    } // end of EmptyInternalData
 103.983 -}
   104.1 --- a/openide.util/src/org/openide/util/lookup/ServiceProvider.java	Thu Dec 10 19:23:25 2009 -0500
   104.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.3 @@ -1,102 +0,0 @@
   104.4 -/*
   104.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   104.6 - *
   104.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
   104.8 - *
   104.9 - * The contents of this file are subject to the terms of either the GNU
  104.10 - * General Public License Version 2 only ("GPL") or the Common
  104.11 - * Development and Distribution License("CDDL") (collectively, the
  104.12 - * "License"). You may not use this file except in compliance with the
  104.13 - * License. You can obtain a copy of the License at
  104.14 - * http://www.netbeans.org/cddl-gplv2.html
  104.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  104.16 - * specific language governing permissions and limitations under the
  104.17 - * License.  When distributing the software, include this License Header
  104.18 - * Notice in each file and include the License file at
  104.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  104.20 - * particular file as subject to the "Classpath" exception as provided
  104.21 - * by Sun in the GPL Version 2 section of the License file that
  104.22 - * accompanied this code. If applicable, add the following below the
  104.23 - * License Header, with the fields enclosed by brackets [] replaced by
  104.24 - * your own identifying information:
  104.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  104.26 - *
  104.27 - * If you wish your version of this file to be governed by only the CDDL
  104.28 - * or only the GPL Version 2, indicate your decision by adding
  104.29 - * "[Contributor] elects to include this software in this distribution
  104.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  104.31 - * single choice of license, a recipient has the option to distribute
  104.32 - * your version of this file under either the CDDL, the GPL Version 2 or
  104.33 - * to extend the choice of license to its licensees as provided above.
  104.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  104.35 - * Version 2 license, then the option applies only if the new code is
  104.36 - * made subject to such option by the copyright holder.
  104.37 - *
  104.38 - * Contributor(s):
  104.39 - *
  104.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  104.41 - */
  104.42 -
  104.43 -package org.openide.util.lookup;
  104.44 -
  104.45 -import java.lang.annotation.ElementType;
  104.46 -import java.lang.annotation.Retention;
  104.47 -import java.lang.annotation.RetentionPolicy;
  104.48 -import java.lang.annotation.Target;
  104.49 -import org.openide.util.Lookup;
  104.50 -
  104.51 -/**
  104.52 - * Declarative registration of a singleton service provider.
  104.53 - * By marking an implementation class with this annotation,
  104.54 - * you automatically register that implementation, normally in {@link Lookup#getDefault}.
  104.55 - * The class must be public and have a public no-argument constructor.
  104.56 - * <p>Example of usage:
  104.57 - * <pre>
  104.58 - * package my.module;
  104.59 - * import org.netbeans.spi.whatever.Thing;
  104.60 - * import org.openide.util.lookup.ServiceProvider;
  104.61 - * &#64;ServiceProvider(service=Thing.class)
  104.62 - * public class MyThing implements Thing {...}
  104.63 - * </pre>
  104.64 - * <p>would result in a resource file <code>META-INF/services/org.netbeans.spi.whatever.Thing</code>
  104.65 - * containing the single line of text: <code>my.module.MyThing</code>
  104.66 - * @see Lookups#metaInfServices(ClassLoader)
  104.67 - * @since org.openide.util 7.20
  104.68 - */
  104.69 -@Retention(RetentionPolicy.SOURCE)
  104.70 -@Target(ElementType.TYPE)
  104.71 -public @interface ServiceProvider {
  104.72 -
  104.73 -    /**
  104.74 -     * The interface (or abstract class) to register this implementation under.
  104.75 -     * It is an error if the implementation class is not in fact assignable to the interface.
  104.76 -     * <p>If you need to register one class under multiple interfaces, use {@link ServiceProviders}.
  104.77 -     * <p>Requests to look up the specified interface should result in this implementation.
  104.78 -     * Requests for any other types may or may not result in this implementation even if the
  104.79 -     * implementation is assignable to those types.
  104.80 -     */
  104.81 -    Class<?> service();
  104.82 -
  104.83 -    /**
  104.84 -     * An optional position in which to register this service relative to others.
  104.85 -     * Lower-numbered services are returned in the lookup result first.
  104.86 -     * Services with no specified position are returned last.
  104.87 -     */
  104.88 -    int position() default Integer.MAX_VALUE;
  104.89 -
  104.90 -    /**
  104.91 -     * An optional list of implementations (given as fully-qualified class names) which this implementation supersedes.
  104.92 -     * If specified, those implementations will not be loaded even if they were registered.
  104.93 -     * Useful on occasion to cancel a generic implementation and replace it with a more advanced one.
  104.94 -     */
  104.95 -    String[] supersedes() default {};
  104.96 -
  104.97 -    /**
  104.98 -     * An optional path to register this implementation in.
  104.99 -     * For example, <code>Projects/sometype/Nodes</code> could be used.
 104.100 -     * This style of registration would be recognized by {@link Lookups#forPath}
 104.101 -     * rather than {@link Lookup#getDefault}.
 104.102 -     */
 104.103 -    String path() default "";
 104.104 -
 104.105 -}
   105.1 --- a/openide.util/src/org/openide/util/lookup/ServiceProviders.java	Thu Dec 10 19:23:25 2009 -0500
   105.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.3 @@ -1,60 +0,0 @@
   105.4 -/*
   105.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   105.6 - *
   105.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
   105.8 - *
   105.9 - * The contents of this file are subject to the terms of either the GNU
  105.10 - * General Public License Version 2 only ("GPL") or the Common
  105.11 - * Development and Distribution License("CDDL") (collectively, the
  105.12 - * "License"). You may not use this file except in compliance with the
  105.13 - * License. You can obtain a copy of the License at
  105.14 - * http://www.netbeans.org/cddl-gplv2.html
  105.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  105.16 - * specific language governing permissions and limitations under the
  105.17 - * License.  When distributing the software, include this License Header
  105.18 - * Notice in each file and include the License file at
  105.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  105.20 - * particular file as subject to the "Classpath" exception as provided
  105.21 - * by Sun in the GPL Version 2 section of the License file that
  105.22 - * accompanied this code. If applicable, add the following below the
  105.23 - * License Header, with the fields enclosed by brackets [] replaced by
  105.24 - * your own identifying information:
  105.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  105.26 - *
  105.27 - * If you wish your version of this file to be governed by only the CDDL
  105.28 - * or only the GPL Version 2, indicate your decision by adding
  105.29 - * "[Contributor] elects to include this software in this distribution
  105.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  105.31 - * single choice of license, a recipient has the option to distribute
  105.32 - * your version of this file under either the CDDL, the GPL Version 2 or
  105.33 - * to extend the choice of license to its licensees as provided above.
  105.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  105.35 - * Version 2 license, then the option applies only if the new code is
  105.36 - * made subject to such option by the copyright holder.
  105.37 - *
  105.38 - * Contributor(s):
  105.39 - *
  105.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  105.41 - */
  105.42 -
  105.43 -package org.openide.util.lookup;
  105.44 -
  105.45 -import java.lang.annotation.ElementType;
  105.46 -import java.lang.annotation.Retention;
  105.47 -import java.lang.annotation.RetentionPolicy;
  105.48 -import java.lang.annotation.Target;
  105.49 -
  105.50 -/**
  105.51 - * Similar to {@link ServiceProvider} but permits multiple registrations of one class.
  105.52 - * @since org.openide.util 7.20
  105.53 - */
  105.54 -@Retention(RetentionPolicy.SOURCE)
  105.55 -@Target(ElementType.TYPE)
  105.56 -public @interface ServiceProviders {
  105.57 -
  105.58 -    /**
  105.59 -     * List of service provider registrations.
  105.60 -     */
  105.61 -    ServiceProvider[] value();
  105.62 -
  105.63 -}
   106.1 --- a/openide.util/src/org/openide/util/lookup/SimpleLookup.java	Thu Dec 10 19:23:25 2009 -0500
   106.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.3 @@ -1,250 +0,0 @@
   106.4 -/*
   106.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   106.6 - *
   106.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   106.8 - *
   106.9 - * The contents of this file are subject to the terms of either the GNU
  106.10 - * General Public License Version 2 only ("GPL") or the Common
  106.11 - * Development and Distribution License("CDDL") (collectively, the
  106.12 - * "License"). You may not use this file except in compliance with the
  106.13 - * License. You can obtain a copy of the License at
  106.14 - * http://www.netbeans.org/cddl-gplv2.html
  106.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  106.16 - * specific language governing permissions and limitations under the
  106.17 - * License.  When distributing the software, include this License Header
  106.18 - * Notice in each file and include the License file at
  106.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  106.20 - * particular file as subject to the "Classpath" exception as provided
  106.21 - * by Sun in the GPL Version 2 section of the License file that
  106.22 - * accompanied this code. If applicable, add the following below the
  106.23 - * License Header, with the fields enclosed by brackets [] replaced by
  106.24 - * your own identifying information:
  106.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  106.26 - *
  106.27 - * Contributor(s):
  106.28 - *
  106.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  106.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  106.31 - * Microsystems, Inc. All Rights Reserved.
  106.32 - *
  106.33 - * If you wish your version of this file to be governed by only the CDDL
  106.34 - * or only the GPL Version 2, indicate your decision by adding
  106.35 - * "[Contributor] elects to include this software in this distribution
  106.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  106.37 - * single choice of license, a recipient has the option to distribute
  106.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  106.39 - * to extend the choice of license to its licensees as provided above.
  106.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  106.41 - * Version 2 license, then the option applies only if the new code is
  106.42 - * made subject to such option by the copyright holder.
  106.43 - */
  106.44 -package org.openide.util.lookup;
  106.45 -
  106.46 -import org.openide.util.Lookup;
  106.47 -import org.openide.util.LookupListener;
  106.48 -
  106.49 -import java.util.*;
  106.50 -
  106.51 -
  106.52 -/**
  106.53 - * Simple lookup implementation. It can be used to create temporary lookups
  106.54 - * that do not change over time. The result stores references to all objects
  106.55 - * passed in the constructor. Those objecst are the only ones returned as
  106.56 - * result.
  106.57 - * @author David Strupl
  106.58 - */
  106.59 -class SimpleLookup extends org.openide.util.Lookup {
  106.60 -    /** This variable is initialized in constructor and thus null
  106.61 -     * value is not allowed as its value. */
  106.62 -    private Collection<Item<?>> allItems;
  106.63 -
  106.64 -    /**
  106.65 -     * Creates new Result object with supplied instances parameter.
  106.66 -     * @param instances to be used to return from the lookup
  106.67 -     */
  106.68 -    SimpleLookup(Collection<Object> instances) {
  106.69 -        allItems = new ArrayList<Item<?>>(instances.size());
  106.70 -
  106.71 -        for (Iterator i = instances.iterator(); i.hasNext();) {
  106.72 -            allItems.add(new InstanceContent.SimpleItem<Object>(i.next()));
  106.73 -        }
  106.74 -    }
  106.75 -
  106.76 -    <T,R> SimpleLookup(Collection<T> keys, InstanceContent.Convertor<? super T,R> conv) {
  106.77 -        allItems = new ArrayList<Item<?>>(keys.size());
  106.78 -
  106.79 -        for (T item : keys) {
  106.80 -            allItems.add(new InstanceContent.ConvertingItem<T,R>(item, conv));
  106.81 -        }
  106.82 -    }
  106.83 -
  106.84 -    public String toString() {
  106.85 -        return "SimpleLookup" + lookup(new Template<Object>(Object.class)).allInstances();
  106.86 -    }
  106.87 -
  106.88 -    public <T> Result<T> lookup(Template<T> template) {
  106.89 -        if (template == null) {
  106.90 -            throw new NullPointerException();
  106.91 -        }
  106.92 -
  106.93 -        return new SimpleResult<T>(template);
  106.94 -    }
  106.95 -
  106.96 -    public <T> T lookup(Class<T> clazz) {
  106.97 -        for (Iterator i = allItems.iterator(); i.hasNext();) {
  106.98 -            Object o = i.next();
  106.99 -
 106.100 -            if (o instanceof AbstractLookup.Pair) {
 106.101 -                AbstractLookup.Pair<?> p = (AbstractLookup.Pair<?>)o;
 106.102 -                if (p.instanceOf(clazz)) {
 106.103 -                    Object ret = p.getInstance();
 106.104 -                    if (clazz.isInstance(ret)) {
 106.105 -                        return clazz.cast(ret);
 106.106 -                    }
 106.107 -                }
 106.108 -            }
 106.109 -        }
 106.110 -        return null;
 106.111 -    }
 106.112 -
 106.113 -    /** A method that defines matching between Item and Template.
 106.114 -     * @param item the item to match
 106.115 -     * @return true if item matches the template requirements, false if not
 106.116 -     */
 106.117 -    private static boolean matches(Template<?> t, AbstractLookup.Pair<?> item) {
 106.118 -        if (!AbstractLookup.matches(t, item, true)) {
 106.119 -            return false;
 106.120 -        }
 106.121 -
 106.122 -        Class<?> type = t.getType();
 106.123 -
 106.124 -        if ((type != null) && !type.isAssignableFrom(item.getType())) {
 106.125 -            return false;
 106.126 -        }
 106.127 -
 106.128 -        return true;
 106.129 -    }
 106.130 -
 106.131 -    /**
 106.132 -     * Result used in SimpleLookup. It holds a reference to the collection
 106.133 -     * passed in constructor. As the contents of this lookup result never
 106.134 -     * changes the addLookupListener and removeLookupListener are empty.
 106.135 -     */
 106.136 -    private class SimpleResult<T> extends Lookup.Result<T> {
 106.137 -        /** can be null and is initialized lazily */
 106.138 -        private Set<Class<? extends T>> classes;
 106.139 -
 106.140 -        /** can be null and is initialized lazily */
 106.141 -        private Collection<? extends Item<T>> items;
 106.142 -
 106.143 -        /** Template used for this result. It is never null.*/
 106.144 -        private Template<T> template;
 106.145 -
 106.146 -        /** can be null and is initialized lazily */
 106.147 -        private Collection<T> results;
 106.148 -
 106.149 -        /** Just remembers the supplied argument in variable template.*/
 106.150 -        SimpleResult(Template<T> template) {
 106.151 -            this.template = template;
 106.152 -        }
 106.153 -
 106.154 -        /**
 106.155 -         * Intentionally does nothing because the lookup does not change
 106.156 -         * and no notification is needed.
 106.157 -         */
 106.158 -        public void addLookupListener(LookupListener l) {
 106.159 -        }
 106.160 -
 106.161 -        /**
 106.162 -         * Intentionally does nothing because the lookup does not change
 106.163 -         * and no notification is needed.
 106.164 -         */
 106.165 -        public void removeLookupListener(LookupListener l) {
 106.166 -        }
 106.167 -
 106.168 -        /**
 106.169 -         * Lazy initializes the results collection. Uses a call to allItems
 106.170 -         * to obtain the instances.
 106.171 -         */
 106.172 -        public java.util.Collection<? extends T> allInstances() {
 106.173 -            synchronized (this) {
 106.174 -                if (results != null) {
 106.175 -                    return results;
 106.176 -                }
 106.177 -            }
 106.178 -
 106.179 -
 106.180 -            Collection<T> res = new ArrayList<T>(allItems.size());
 106.181 -
 106.182 -            for (Item<T> item : allItems()) {
 106.183 -                res.add(item.getInstance());
 106.184 -            }
 106.185 -
 106.186 -            synchronized (this) {
 106.187 -                results = Collections.unmodifiableCollection(res);
 106.188 -            }
 106.189 -
 106.190 -            return results;
 106.191 -        }
 106.192 -
 106.193 -        /**
 106.194 -         * Lazy initializes variable classes. Uses a call to allItems to
 106.195 -         * compute the result.
 106.196 -         */
 106.197 -        public Set<Class<? extends T>> allClasses() {
 106.198 -            synchronized (this) {
 106.199 -                if (classes != null) {
 106.200 -                    return classes;
 106.201 -                }
 106.202 -            }
 106.203 -
 106.204 -            Set<Class<? extends T>> res = new HashSet<Class<? extends T>>();
 106.205 -
 106.206 -            for (Item<T> item : allItems()) {
 106.207 -                res.add(item.getType());
 106.208 -            }
 106.209 -
 106.210 -            synchronized (this) {
 106.211 -                classes = Collections.unmodifiableSet(res);
 106.212 -            }
 106.213 -
 106.214 -            return classes;
 106.215 -        }
 106.216 -
 106.217 -        /**
 106.218 -         * Lazy initializes variable items. Creates an item for each
 106.219 -         * element in the instances collection. It puts either SimpleItem
 106.220 -         * or ConvertingItem to the collection.
 106.221 -         */
 106.222 -        public Collection<? extends Item<T>> allItems() {
 106.223 -            synchronized (this) {
 106.224 -                if (items != null) {
 106.225 -                    return items;
 106.226 -                }
 106.227 -            }
 106.228 -
 106.229 -            Collection<Item<T>> res = new ArrayList<Item<T>>(allItems.size());
 106.230 -
 106.231 -            for (Iterator<Item<?>> i = allItems.iterator(); i.hasNext();) {
 106.232 -                Item<?> o = i.next();
 106.233 -
 106.234 -                if (o instanceof AbstractLookup.Pair) {
 106.235 -                    if (matches(template, (AbstractLookup.Pair) o)) {
 106.236 -                        res.add(cast(o));
 106.237 -                    }
 106.238 -                }
 106.239 -            }
 106.240 -
 106.241 -            synchronized (this) {
 106.242 -                items = Collections.unmodifiableCollection(res);
 106.243 -            }
 106.244 -
 106.245 -            return items;
 106.246 -        }
 106.247 -
 106.248 -        @SuppressWarnings("unchecked")
 106.249 -        private Item<T> cast(Item<?> i) {
 106.250 -            return (Item<T>)i;
 106.251 -        }
 106.252 -    }
 106.253 -}
   107.1 --- a/openide.util/src/org/openide/util/lookup/SimpleProxyLookup.java	Thu Dec 10 19:23:25 2009 -0500
   107.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.3 @@ -1,359 +0,0 @@
   107.4 -/*
   107.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   107.6 - *
   107.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   107.8 - *
   107.9 - * The contents of this file are subject to the terms of either the GNU
  107.10 - * General Public License Version 2 only ("GPL") or the Common
  107.11 - * Development and Distribution License("CDDL") (collectively, the
  107.12 - * "License"). You may not use this file except in compliance with the
  107.13 - * License. You can obtain a copy of the License at
  107.14 - * http://www.netbeans.org/cddl-gplv2.html
  107.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  107.16 - * specific language governing permissions and limitations under the
  107.17 - * License.  When distributing the software, include this License Header
  107.18 - * Notice in each file and include the License file at
  107.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  107.20 - * particular file as subject to the "Classpath" exception as provided
  107.21 - * by Sun in the GPL Version 2 section of the License file that
  107.22 - * accompanied this code. If applicable, add the following below the
  107.23 - * License Header, with the fields enclosed by brackets [] replaced by
  107.24 - * your own identifying information:
  107.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  107.26 - *
  107.27 - * Contributor(s):
  107.28 - *
  107.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  107.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  107.31 - * Microsystems, Inc. All Rights Reserved.
  107.32 - *
  107.33 - * If you wish your version of this file to be governed by only the CDDL
  107.34 - * or only the GPL Version 2, indicate your decision by adding
  107.35 - * "[Contributor] elects to include this software in this distribution
  107.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  107.37 - * single choice of license, a recipient has the option to distribute
  107.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  107.39 - * to extend the choice of license to its licensees as provided above.
  107.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  107.41 - * Version 2 license, then the option applies only if the new code is
  107.42 - * made subject to such option by the copyright holder.
  107.43 - */
  107.44 -package org.openide.util.lookup;
  107.45 -
  107.46 -import java.lang.ref.Reference;
  107.47 -import java.lang.ref.WeakReference;
  107.48 -import org.openide.util.Lookup;
  107.49 -import org.openide.util.LookupEvent;
  107.50 -import org.openide.util.LookupListener;
  107.51 -
  107.52 -import java.util.*;
  107.53 -
  107.54 -
  107.55 -/**
  107.56 - * Simple proxy lookup. Keeps reference to a lookup it delegates to and
  107.57 - * forwards all requests.
  107.58 - *
  107.59 - * @author Jaroslav Tulach
  107.60 - */
  107.61 -final class SimpleProxyLookup extends org.openide.util.Lookup {
  107.62 -    /** the provider to check for the status */
  107.63 -    private Provider provider;
  107.64 -
  107.65 -    /** the lookup we currently delegate to */
  107.66 -    private Lookup delegate;
  107.67 -
  107.68 -    /** map of all templates to Reference (results) associated to this lookup */
  107.69 -    private WeakHashMap<Template<?>,Reference<ProxyResult<?>>> results;
  107.70 -
  107.71 -    /**
  107.72 -     * @param provider provider to delegate to
  107.73 -     */
  107.74 -    SimpleProxyLookup(Provider provider) {
  107.75 -        this.provider = provider;
  107.76 -    }
  107.77 -
  107.78 -    /** Checks whether we still delegate to the same lookup */
  107.79 -    private Lookup checkLookup() {
  107.80 -        Lookup l = provider.getLookup();
  107.81 -
  107.82 -        // iterator over Reference (ProxyResult)
  107.83 -        Iterator<Reference<ProxyResult<?>>> toCheck = null;
  107.84 -
  107.85 -        synchronized (this) {
  107.86 -            if (l != delegate) {
  107.87 -                this.delegate = l;
  107.88 -
  107.89 -                if (results != null) {
  107.90 -                    toCheck = new ArrayList<Reference<ProxyResult<?>>>(results.values()).iterator();
  107.91 -                }
  107.92 -            }
  107.93 -        }
  107.94 -
  107.95 -        if (toCheck != null) {
  107.96 -            // update
  107.97 -            ArrayList<Object> evAndListeners = new ArrayList<Object>();
  107.98 -            for (Iterator<Reference<ProxyResult<?>>> it = toCheck; it.hasNext(); ) {
  107.99 -                java.lang.ref.Reference<ProxyResult<?>> ref = it.next();
 107.100 -                if (ref == null) {
 107.101 -                    continue;
 107.102 -                }
 107.103 -
 107.104 -                ProxyResult<?> p = ref.get();
 107.105 -
 107.106 -                if (p != null && p.updateLookup(l)) {
 107.107 -                    p.collectFires(evAndListeners);
 107.108 -                }
 107.109 -            }
 107.110 -            
 107.111 -            for (Iterator it = evAndListeners.iterator(); it.hasNext(); ) {
 107.112 -                LookupEvent ev = (LookupEvent)it.next();
 107.113 -                LookupListener ll = (LookupListener)it.next();
 107.114 -                ll.resultChanged(ev);
 107.115 -            }
 107.116 -        }
 107.117 -
 107.118 -        return delegate;
 107.119 -    }
 107.120 -
 107.121 -    @SuppressWarnings("unchecked")
 107.122 -    private static <T> ProxyResult<T> cast(ProxyResult<?> p) {
 107.123 -        return (ProxyResult<T>)p;
 107.124 -    }
 107.125 -
 107.126 -    public <T> Result<T> lookup(Template<T> template) {
 107.127 -        synchronized (this) {
 107.128 -            if (results == null) {
 107.129 -                results = new WeakHashMap<Template<?>,Reference<ProxyResult<?>>>();
 107.130 -            } else {
 107.131 -                Reference<ProxyResult<?>> ref = results.get(template);
 107.132 -
 107.133 -                if (ref != null) {
 107.134 -                    ProxyResult<?> p = ref.get();
 107.135 -
 107.136 -                    if (p != null) {
 107.137 -                        return cast(p);
 107.138 -                    }
 107.139 -                }
 107.140 -            }
 107.141 -
 107.142 -            ProxyResult<T> p = new ProxyResult<T>(template);
 107.143 -            Reference<ProxyResult<?>> ref = new WeakReference<ProxyResult<?>>(p);
 107.144 -            results.put(template, ref);
 107.145 -
 107.146 -            return p;
 107.147 -        }
 107.148 -    }
 107.149 -
 107.150 -    public <T> T lookup(Class<T> clazz) {
 107.151 -        if (clazz == null) {
 107.152 -            checkLookup();
 107.153 -            return null;
 107.154 -        }
 107.155 -        return checkLookup().lookup(clazz);
 107.156 -    }
 107.157 -
 107.158 -    public <T> Item<T> lookupItem(Template<T> template) {
 107.159 -        return checkLookup().lookupItem(template);
 107.160 -    }
 107.161 -
 107.162 -    /**
 107.163 -     * Result used in SimpleLookup. It holds a reference to the collection
 107.164 -     * passed in constructor. As the contents of this lookup result never
 107.165 -     * changes the addLookupListener and removeLookupListener are empty.
 107.166 -     */
 107.167 -    private final class ProxyResult<T> extends WaitableResult<T> implements LookupListener {
 107.168 -        /** Template used for this result. It is never null.*/
 107.169 -        private Template<T> template;
 107.170 -
 107.171 -        /** result to delegate to */
 107.172 -        private Lookup.Result<T> delegate;
 107.173 -
 107.174 -        /** listeners set */
 107.175 -        private javax.swing.event.EventListenerList listeners;
 107.176 -        private LookupListener lastListener;
 107.177 -
 107.178 -        /** Just remembers the supplied argument in variable template.*/
 107.179 -        ProxyResult(Template<T> template) {
 107.180 -            this.template = template;
 107.181 -        }
 107.182 -
 107.183 -        /** Checks state of the result
 107.184 -         */
 107.185 -        private Result<T> checkResult() {
 107.186 -            updateLookup(checkLookup());
 107.187 -
 107.188 -            return this.delegate;
 107.189 -        }
 107.190 -
 107.191 -        /** Updates the state of the lookup.
 107.192 -         * @return true if the lookup really changed
 107.193 -         */
 107.194 -        public boolean updateLookup(Lookup l) {
 107.195 -            Collection<? extends Item<T>> oldPairs = (delegate != null) ? delegate.allItems() : null;
 107.196 -
 107.197 -            LookupListener removedListener;
 107.198 -
 107.199 -            synchronized (this) {
 107.200 -                if ((delegate != null) && (lastListener != null)) {
 107.201 -                    removedListener = lastListener;
 107.202 -                    delegate.removeLookupListener(lastListener);
 107.203 -                } else {
 107.204 -                    removedListener = null;
 107.205 -                }
 107.206 -            }
 107.207 -
 107.208 -            // cannot call to foreign code 
 107.209 -            Lookup.Result<T> res = l.lookup(template);
 107.210 -
 107.211 -            synchronized (this) {
 107.212 -                if (removedListener == lastListener) {
 107.213 -                    delegate = res;
 107.214 -                    lastListener = new WeakResult<T>(this, delegate);
 107.215 -                    delegate.addLookupListener(lastListener);
 107.216 -                }
 107.217 -            }
 107.218 -
 107.219 -            if (oldPairs == null) {
 107.220 -                // nobody knows about a change
 107.221 -                return false;
 107.222 -            }
 107.223 -
 107.224 -            Collection<? extends Item<T>> newPairs = delegate.allItems();
 107.225 -
 107.226 -            // See #34961 for explanation.
 107.227 -            if (!(oldPairs instanceof List)) {
 107.228 -                if (oldPairs == Collections.EMPTY_SET) {
 107.229 -                    // avoid allocation
 107.230 -                    oldPairs = Collections.emptyList();
 107.231 -                } else {
 107.232 -                    oldPairs = new ArrayList<Item<T>>(oldPairs);
 107.233 -                }
 107.234 -            }
 107.235 -
 107.236 -            if (!(newPairs instanceof List)) {
 107.237 -                newPairs = new ArrayList<Item<T>>(newPairs);
 107.238 -            }
 107.239 -
 107.240 -            return !oldPairs.equals(newPairs);
 107.241 -        }
 107.242 -
 107.243 -        public synchronized void addLookupListener(LookupListener l) {
 107.244 -            if (listeners == null) {
 107.245 -                listeners = new javax.swing.event.EventListenerList();
 107.246 -            }
 107.247 -
 107.248 -            listeners.add(LookupListener.class, l);
 107.249 -        }
 107.250 -
 107.251 -        public synchronized void removeLookupListener(LookupListener l) {
 107.252 -            if (listeners != null) {
 107.253 -                listeners.remove(LookupListener.class, l);
 107.254 -            }
 107.255 -        }
 107.256 -
 107.257 -        public java.util.Collection<? extends T> allInstances() {
 107.258 -            return checkResult().allInstances();
 107.259 -        }
 107.260 -
 107.261 -        public Set<Class<? extends T>> allClasses() {
 107.262 -            return checkResult().allClasses();
 107.263 -        }
 107.264 -
 107.265 -        public Collection<? extends Item<T>> allItems() {
 107.266 -            return checkResult().allItems();
 107.267 -        }
 107.268 -
 107.269 -        protected void beforeLookup(Lookup.Template t) {
 107.270 -            Lookup.Result r = checkResult();
 107.271 -
 107.272 -            if (r instanceof WaitableResult) {
 107.273 -                ((WaitableResult) r).beforeLookup(t);
 107.274 -            }
 107.275 -        }
 107.276 -
 107.277 -        /** A change in lookup occured.
 107.278 -         * @param ev event describing the change
 107.279 -         *
 107.280 -         */
 107.281 -        public void resultChanged(LookupEvent anEvent) {
 107.282 -            collectFires(null);
 107.283 -        } 
 107.284 -        
 107.285 -        protected void collectFires(Collection<Object> evAndListeners) {
 107.286 -            javax.swing.event.EventListenerList l = this.listeners;
 107.287 -
 107.288 -            if (l == null) {
 107.289 -                return;
 107.290 -            }
 107.291 -
 107.292 -            Object[] listeners = l.getListenerList();
 107.293 -
 107.294 -            if (listeners.length == 0) {
 107.295 -                return;
 107.296 -            }
 107.297 -
 107.298 -            LookupEvent ev = new LookupEvent(this);
 107.299 -            AbstractLookup.notifyListeners(listeners, ev, evAndListeners);
 107.300 -        }
 107.301 -    }
 107.302 -     // end of ProxyResult
 107.303 -    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
 107.304 -        private Lookup.Result source;
 107.305 -        private Reference<ProxyResult<T>> result;
 107.306 -        
 107.307 -        public WeakResult(ProxyResult<T> r, Lookup.Result<T> s) {
 107.308 -            this.result = new WeakReference<ProxyResult<T>>(r);
 107.309 -            this.source = s;
 107.310 -        }
 107.311 -        
 107.312 -        protected void beforeLookup(Lookup.Template t) {
 107.313 -            ProxyResult r = (ProxyResult)result.get();
 107.314 -            if (r != null) {
 107.315 -                r.beforeLookup(t);
 107.316 -            } else {
 107.317 -                source.removeLookupListener(this);
 107.318 -            }
 107.319 -        }
 107.320 -
 107.321 -        protected void collectFires(Collection<Object> evAndListeners) {
 107.322 -            ProxyResult<T> r = result.get();
 107.323 -            if (r != null) {
 107.324 -                r.collectFires(evAndListeners);
 107.325 -            } else {
 107.326 -                source.removeLookupListener(this);
 107.327 -            }
 107.328 -        }
 107.329 -
 107.330 -        public void addLookupListener(LookupListener l) {
 107.331 -            assert false;
 107.332 -        }
 107.333 -
 107.334 -        public void removeLookupListener(LookupListener l) {
 107.335 -            assert false;
 107.336 -        }
 107.337 -
 107.338 -        public Collection<T> allInstances() {
 107.339 -            assert false;
 107.340 -            return null;
 107.341 -        }
 107.342 -
 107.343 -        public void resultChanged(LookupEvent ev) {
 107.344 -            ProxyResult r = (ProxyResult)result.get();
 107.345 -            if (r != null) {
 107.346 -                r.resultChanged(ev);
 107.347 -            } else {
 107.348 -                source.removeLookupListener(this);
 107.349 -            }
 107.350 -        }
 107.351 -
 107.352 -        public Collection<? extends Item<T>> allItems() {
 107.353 -            assert false;
 107.354 -            return null;
 107.355 -        }
 107.356 -
 107.357 -        public Set<Class<? extends T>> allClasses() {
 107.358 -            assert false;
 107.359 -            return null;
 107.360 -        }
 107.361 -    } // end of WeakResult
 107.362 -}
   108.1 --- a/openide.util/src/org/openide/util/lookup/SingletonLookup.java	Thu Dec 10 19:23:25 2009 -0500
   108.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.3 @@ -1,173 +0,0 @@
   108.4 -/*
   108.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   108.6 - * 
   108.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
   108.8 - * 
   108.9 - * The contents of this file are subject to the terms of either the GNU
  108.10 - * General Public License Version 2 only ("GPL") or the Common
  108.11 - * Development and Distribution License("CDDL") (collectively, the
  108.12 - * "License"). You may not use this file except in compliance with the
  108.13 - * License. You can obtain a copy of the License at
  108.14 - * http://www.netbeans.org/cddl-gplv2.html
  108.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  108.16 - * specific language governing permissions and limitations under the
  108.17 - * License.  When distributing the software, include this License Header
  108.18 - * Notice in each file and include the License file at
  108.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  108.20 - * particular file as subject to the "Classpath" exception as provided
  108.21 - * by Sun in the GPL Version 2 section of the License file that
  108.22 - * accompanied this code. If applicable, add the following below the
  108.23 - * License Header, with the fields enclosed by brackets [] replaced by
  108.24 - * your own identifying information:
  108.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  108.26 - * 
  108.27 - * If you wish your version of this file to be governed by only the CDDL
  108.28 - * or only the GPL Version 2, indicate your decision by adding
  108.29 - * "[Contributor] elects to include this software in this distribution
  108.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  108.31 - * single choice of license, a recipient has the option to distribute
  108.32 - * your version of this file under either the CDDL, the GPL Version 2 or
  108.33 - * to extend the choice of license to its licensees as provided above.
  108.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  108.35 - * Version 2 license, then the option applies only if the new code is
  108.36 - * made subject to such option by the copyright holder.
  108.37 - * 
  108.38 - * Contributor(s):
  108.39 - * 
  108.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  108.41 - */
  108.42 -
  108.43 -package org.openide.util.lookup;
  108.44 -
  108.45 -import java.util.Collection;
  108.46 -import java.util.Collections;
  108.47 -import java.util.Set;
  108.48 -import org.openide.util.Lookup;
  108.49 -import org.openide.util.LookupListener;
  108.50 -
  108.51 -/**
  108.52 - * Unmodifiable lookup that contains just one fixed object.
  108.53 - *
  108.54 - * @author Marian Petras
  108.55 - */
  108.56 -class SingletonLookup extends Lookup {
  108.57 -
  108.58 -    private final Object objectToLookup;
  108.59 -    private final String id;
  108.60 -
  108.61 -    SingletonLookup(Object objectToLookup) {
  108.62 -        this(objectToLookup, null);
  108.63 -    }
  108.64 -
  108.65 -    SingletonLookup(Object objectToLookup, String id) {
  108.66 -        if (objectToLookup == null) {
  108.67 -            throw new IllegalArgumentException("null");                 //NOI18N
  108.68 -        }
  108.69 -
  108.70 -        this.objectToLookup = objectToLookup;
  108.71 -        this.id = id;
  108.72 -    }
  108.73 -
  108.74 -    @Override
  108.75 -    public <T> T lookup(Class<T> clazz) {
  108.76 -        if (clazz == null) {
  108.77 -            throw new IllegalArgumentException("null");                 //NOI18N
  108.78 -        }
  108.79 -
  108.80 -        return (clazz.isInstance(objectToLookup))
  108.81 -               ? clazz.cast(objectToLookup)
  108.82 -               : null;
  108.83 -    }
  108.84 -
  108.85 -    @Override
  108.86 -    public <T> Result<T> lookup(Template<T> template) {
  108.87 -        if (template == null) {
  108.88 -            throw new IllegalArgumentException("null");                 //NOI18N
  108.89 -        }
  108.90 -
  108.91 -        Lookup.Item<T> item = lookupItem(template);
  108.92 -        if (item != null) {
  108.93 -            return new SingletonResult<T>(item);
  108.94 -        } else {
  108.95 -            return Lookup.EMPTY.lookup(template);
  108.96 -        }
  108.97 -    }
  108.98 -
  108.99 -    @Override
 108.100 -    public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
 108.101 -        if (clazz == null) {
 108.102 -            throw new IllegalArgumentException("null");                 //NOI18N
 108.103 -        }
 108.104 -
 108.105 -        return (clazz.isInstance(objectToLookup))
 108.106 -               ? Collections.singletonList(clazz.cast(objectToLookup))
 108.107 -               : Collections.<T>emptyList();
 108.108 -    }
 108.109 -
 108.110 -    @Override
 108.111 -    @SuppressWarnings("unchecked")
 108.112 -    public <T> Item<T> lookupItem(Template<T> template) {
 108.113 -        if (template == null) {
 108.114 -            throw new IllegalArgumentException("null");                 //NOI18N
 108.115 -        }
 108.116 -
 108.117 -        String templateId = template.getId();
 108.118 -        if ((templateId != null) && !templateId.equals(id)) {
 108.119 -            return null;
 108.120 -        }
 108.121 -
 108.122 -        Object templateInst = template.getInstance();
 108.123 -        if ((templateInst != null) && (objectToLookup != templateInst)) {
 108.124 -            return null;
 108.125 -        }
 108.126 -
 108.127 -        Class<T> clazz = template.getType();
 108.128 -        if ((clazz != null) && !clazz.isInstance(objectToLookup)) {
 108.129 -            return null;
 108.130 -        }
 108.131 -
 108.132 -        Lookup.Item<T> item;
 108.133 -        if (clazz != null) {
 108.134 -            item = Lookups.lookupItem(clazz.cast(objectToLookup), id);
 108.135 -        } else {
 108.136 -            item = Lookups.lookupItem((T) objectToLookup, id);
 108.137 -        }
 108.138 -        return item;
 108.139 -    }
 108.140 -
 108.141 -    static class SingletonResult<T> extends Lookup.Result<T> {
 108.142 -
 108.143 -        private final Lookup.Item<T> item;
 108.144 -
 108.145 -        SingletonResult(Lookup.Item<T> item) {
 108.146 -            this.item = item;
 108.147 -        }
 108.148 -
 108.149 -        @Override
 108.150 -        public void addLookupListener(LookupListener l) {
 108.151 -            // this result never changes - no need to register a listener
 108.152 -        }
 108.153 -
 108.154 -        @Override
 108.155 -        public void removeLookupListener(LookupListener l) {
 108.156 -            // this result never changes - no need to register a listener
 108.157 -        }
 108.158 -
 108.159 -        @Override
 108.160 -        public Set<Class<? extends T>> allClasses() {
 108.161 -            return Collections.<Class<? extends T>>singleton(item.getType());
 108.162 -        }
 108.163 -
 108.164 -        @Override
 108.165 -        public Collection<? extends Item<T>> allItems() {
 108.166 -            return Collections.singletonList(item);
 108.167 -        }
 108.168 -
 108.169 -        @Override
 108.170 -        public Collection<? extends T> allInstances() {
 108.171 -            return Collections.singletonList(item.getInstance());
 108.172 -        }
 108.173 -
 108.174 -    }
 108.175 -
 108.176 -}
   109.1 --- a/openide.util/src/org/openide/util/lookup/WaitableResult.java	Thu Dec 10 19:23:25 2009 -0500
   109.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.3 @@ -1,62 +0,0 @@
   109.4 -/*
   109.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   109.6 - *
   109.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   109.8 - *
   109.9 - * The contents of this file are subject to the terms of either the GNU
  109.10 - * General Public License Version 2 only ("GPL") or the Common
  109.11 - * Development and Distribution License("CDDL") (collectively, the
  109.12 - * "License"). You may not use this file except in compliance with the
  109.13 - * License. You can obtain a copy of the License at
  109.14 - * http://www.netbeans.org/cddl-gplv2.html
  109.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  109.16 - * specific language governing permissions and limitations under the
  109.17 - * License.  When distributing the software, include this License Header
  109.18 - * Notice in each file and include the License file at
  109.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  109.20 - * particular file as subject to the "Classpath" exception as provided
  109.21 - * by Sun in the GPL Version 2 section of the License file that
  109.22 - * accompanied this code. If applicable, add the following below the
  109.23 - * License Header, with the fields enclosed by brackets [] replaced by
  109.24 - * your own identifying information:
  109.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  109.26 - *
  109.27 - * Contributor(s):
  109.28 - *
  109.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  109.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  109.31 - * Microsystems, Inc. All Rights Reserved.
  109.32 - *
  109.33 - * If you wish your version of this file to be governed by only the CDDL
  109.34 - * or only the GPL Version 2, indicate your decision by adding
  109.35 - * "[Contributor] elects to include this software in this distribution
  109.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  109.37 - * single choice of license, a recipient has the option to distribute
  109.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  109.39 - * to extend the choice of license to its licensees as provided above.
  109.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  109.41 - * Version 2 license, then the option applies only if the new code is
  109.42 - * made subject to such option by the copyright holder.
  109.43 - */
  109.44 -package org.openide.util.lookup;
  109.45 -
  109.46 -import java.util.Collection;
  109.47 -import org.openide.util.Lookup;
  109.48 -
  109.49 -
  109.50 -/** A special subclass of lookup that is able to wait before queries.
  109.51 - *
  109.52 - * @author  Jaroslav Tulach
  109.53 - */
  109.54 -abstract class WaitableResult<T> extends Lookup.Result<T> {
  109.55 -    /** Used by proxy results to synchronize before lookup.
  109.56 -     */
  109.57 -    protected abstract void beforeLookup(Lookup.Template t);
  109.58 -
  109.59 -    /** Needed to group notification of outside the package listeners
  109.60 -     * after all AbstractLookup and ProxyLookups have been updated.
  109.61 -     * @param evAndListeners LookupEvent, LookupListener, LookupEvent, LookupListener, etc.
  109.62 -     */
  109.63 -    protected abstract void collectFires(Collection<Object> evAndListeners);
  109.64 -     
  109.65 -}
   110.1 --- a/openide.util/src/org/openide/util/lookup/doc-files/index.html	Thu Dec 10 19:23:25 2009 -0500
   110.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.3 @@ -1,208 +0,0 @@
   110.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
   110.5 -<!--
   110.6 -   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   110.7 -   -
   110.8 -   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
   110.9 -   -
  110.10 -   - The contents of this file are subject to the terms of either the GNU
  110.11 -   - General Public License Version 2 only ("GPL") or the Common
  110.12 -   - Development and Distribution License("CDDL") (collectively, the
  110.13 -   - "License"). You may not use this file except in compliance with the
  110.14 -   - License. You can obtain a copy of the License at
  110.15 -   - http://www.netbeans.org/cddl-gplv2.html
  110.16 -   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  110.17 -   - specific language governing permissions and limitations under the
  110.18 -   - License.  When distributing the software, include this License Header
  110.19 -   - Notice in each file and include the License file at
  110.20 -   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  110.21 -   - particular file as subject to the "Classpath" exception as provided
  110.22 -   - by Sun in the GPL Version 2 section of the License file that
  110.23 -   - accompanied this code. If applicable, add the following below the
  110.24 -   - License Header, with the fields enclosed by brackets [] replaced by
  110.25 -   - your own identifying information:
  110.26 -   - "Portions Copyrighted [year] [name of copyright owner]"
  110.27 -   -
  110.28 -   - Contributor(s):
  110.29 -   -
  110.30 -   - The Original Software is NetBeans. The Initial Developer of the Original
  110.31 -   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  110.32 -   - Microsystems, Inc. All Rights Reserved.
  110.33 -   -
  110.34 -   - If you wish your version of this file to be governed by only the CDDL
  110.35 -   - or only the GPL Version 2, indicate your decision by adding
  110.36 -   - "[Contributor] elects to include this software in this distribution
  110.37 -   - under the [CDDL or GPL Version 2] license." If you do not indicate a
  110.38 -   - single choice of license, a recipient has the option to distribute
  110.39 -   - your version of this file under either the CDDL, the GPL Version 2 or
  110.40 -   - to extend the choice of license to its licensees as provided above.
  110.41 -   - However, if you add GPL Version 2 code and therefore, elected the GPL
  110.42 -   - Version 2 license, then the option applies only if the new code is
  110.43 -   - made subject to such option by the copyright holder.
  110.44 -  -->
  110.45 -<HTML>
  110.46 -<HEAD>
  110.47 -<TITLE>Lookup Library</TITLE>
  110.48 -<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
  110.49 -</HEAD>
  110.50 -<BODY>
  110.51 -
  110.52 -<P>
  110.53 -
  110.54 -This is the home page of the <em>lookup library</em> implementation, which 
  110.55 -is intended to solve a general problem that every <cite>component-based system</CITE>
  110.56 -has had to face: how different components <b>register</b> to the system 
  110.57 -and how other parts of the system can <b>look</b> them <b>up</B>. 
  110.58 -<P>
  110.59 -There already are libraries trying to solve this problem, usually by querying for 
  110.60 -an interface and finding its appropriate implementaion. The most famous is 
  110.61 -<A href="http://www.jini.org/">Jini</A>, the platform for development of
  110.62 -distributed network services. Our library does something similar, but tries 
  110.63 -to stay small and easy
  110.64 -to use. The NetBeans <em>Lookup
  110.65 -Library</EM>'s main focus is a modular application consisting of independent modules
  110.66 -that want to communicate with each other. It does not try to solve networking or
  110.67 -legacy application integration. It is simple but powerful.
  110.68 -
  110.69 -<H2>Why would you want to use it?</H2>
  110.70 -
  110.71 -A well-written modular program separates <em>development</EM>
  110.72 -and <em>deployment</EM>.
  110.73 -There are many situations where a component needs some functionality but
  110.74 -does not actually care about the implementation. It is up to the <em>system
  110.75 -adminstrator</em> that deploys (installs) the application to decide which 
  110.76 -implementation to use.
  110.77 -<P>
  110.78 -The most simple and most often used method for allowing other implementations
  110.79 -to be plugged in is the <em>system property</em> pattern:
  110.80 -
  110.81 -<pre>
  110.82 -    <font class="keyword">public</font> <font class="type">Toolkit</font> <font class="function-name">getDefaultToolkit</font> () {
  110.83 -        java.awt.<font class="type">Toolkit</font> <font class="variable-name">t</font> = <font class="constant">null</font>;
  110.84 -        <font class="type">String</font> <font class="variable-name">classname</font> = System.getProperty (<font class="string">"java.awt.Toolkit"</font>);
  110.85 -        <font class="keyword">if</font> (classname != <font class="constant">null</font>) {
  110.86 -            <font class="keyword">try</font> {
  110.87 -                <font class="type">Class</font> <font class="variable-name">c</font> = Class.forName (classname);
  110.88 -                t = (java.awt.<font class="type">Toolkit</font>)c.newInstance ();
  110.89 -            } <font class="keyword">catch</font> (<font class="type">Exception</font> <font class="variable-name">ex</font>) {
  110.90 -                System.out.println (<font class="string">"Cannot initialize toolkit: "</font> + classname);
  110.91 -                ex.printStackTrace ();
  110.92 -            }
  110.93 -        }
  110.94 -        <font class="comment">// fallback </font>
  110.95 -        <font class="keyword">if</font> (t == <font class="constant">null</font>) {
  110.96 -            t = <font class="keyword">new</font> <font class="type">GenericAWTToolkit</font> ();
  110.97 -        }
  110.98 -    }
  110.99 -</pre>
 110.100 -
 110.101 -    
 110.102 -The idea is simple. The <em>deployer</em> can start the Java VM with the flag
 110.103 -<code>-Djava.awt.Toolkit=org.myorg.MyToolkit</code> where the <code>MyToolkit</code>
 110.104 -is his class with default constructor and the code in the <code>getDefaultToolkit</CODE>
 110.105 -method will instantiate the class and use it.
 110.106 -<P>
 110.107 -In principle this is general enough of a solution and works well, except that writing the 
 110.108 -code above is error prone and it also requires passing the arguments to the virtual machine. 
 110.109 -It would be much nicer if the registation could be done just by putting a JAR file with the <code>MyToolkit</code> class
 110.110 -into the application classpath.
 110.111 -<P>
 110.112 -Actually this has been realized also by the JDK development team and addressed in
 110.113 -JDK 1.3 as part of the <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Provider%20Configuration%20File">provider extension mechanism</A>. 
 110.114 -The <code>MyToolkit</code> could be registered by adding a file 
 110.115 -<code>/META-INF/services/java.awt.Toolkit</code> with one line
 110.116 -<code>org.myorg.MyToolkit</code> into the JAR file that contains the
 110.117 -<code>MyToolkit</CODE> implementation. The code in <code>getDefaultToolkit</CODE>
 110.118 -will scan all JAR files in classpath and search for that file,
 110.119 -create an instance of <code>MyToolkit</code> and use it. 
 110.120 -The deployer can influence which toolkit will be created by 
 110.121 -adding the right JAR files into the classpath.
 110.122 -<P>
 110.123 -Of course the code to access the <code>META-INF/services/</code> files is even
 110.124 -more error prone than the <em>property pattern</EM>.  And this is exactly the
 110.125 -place where the <em>lookup library</em> can help. It provides an implementation of
 110.126 -the search algorithm with an easy interface. Just write:
 110.127 -<pre>
 110.128 -    <font class="keyword">import</font> <font class="type">java.awt.Toolkit</font>;
 110.129 -    <font class="keyword">import</font> <font class="type">org.openide.util.Lookup;</font>;
 110.130 -    <font class="type">Toolkit</font> <font class="variable-name">t</font> = (<font class="type">Toolkit</font>)Lookup.getDefault().<a href="@TOP@org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(Toolkit.<font class="keyword">class</font>);
 110.131 -</PRE>
 110.132 -and if the JAR with <code>MyToolkit</CODE> is in the class path, the simple call 
 110.133 -above will do the rest.
 110.134 -<P>
 110.135 -So whenever one writes an application divided into several independent modules (jar files)
 110.136 -that are being developed and deployed independently, there is a need for registering
 110.137 -and discovering components. First of all, a set of interfaces can be defined to enable 
 110.138 -inter-module communication (like the abstract class <code>java.awt.Toolkit</CODE>).
 110.139 -After that a set of modules providing implementation can written (<code>MyToolkit</code> and other concurent implementations)
 110.140 -and after that, whenever a module trying to utilitize the functionality wants to access
 110.141 -the <code>Toolkit</code> via lookup, the real implementation is returned.
 110.142 -<P>
 110.143 -It is the responsibility of lookup to find a suitable implementation of the
 110.144 -requested service and return an object implementing the service. This is the
 110.145 -the basic functionality and while the library provides you with a little bit
 110.146 -more, even this simple usage might be extremaly useful: the client code knows
 110.147 -nothing about the implementation and the implementation can be switched in
 110.148 -deployment time by simply replacing one implementation jar with other. There
 110.149 -is no code change required.
 110.150 -
 110.151 -<H2> Local lookup usage </H2>
 110.152 -The example in previous paragraph demostrated the usage of lookup as a global
 110.153 -registry (by using the <CODE>Lookup.getDefault()</CODE> call). One can also
 110.154 -consider another scenario where the lookup can help.
 110.155 -<P>
 110.156 -Let's switch hats to be an API designer for a while. The goal is to introduce a
 110.157 -new object into the system. But you either are not sure yet what all the roles
 110.158 -of the new object will be or you (more importantly) want to be able to add (or
 110.159 -change) roles of the object dynamically. So why not to introduce following
 110.160 -method to the object's interface:
 110.161 -<pre>
 110.162 -<font class="keyword">public class </FONT> <font class="type">MorphingObject</FONT> {
 110.163 -    <font class="keyword">public</FONT> <font class="type"><a href="@TOP@org/openide/util/Lookup.html">Lookup</A></FONT> getLookup() {
 110.164 -        <font class="keyword">return</FONT> <font class="variable-name">myLookup;</FONT>
 110.165 -    }
 110.166 -    ...
 110.167 -}
 110.168 -</pre>
 110.169 -By exposing the method getLookup you can attach different functionality to the
 110.170 -MorphingObject at runtime and whoever gets a reference to your object can ask it
 110.171 -whether the object supports a given interface like this:
 110.172 -<pre>
 110.173 -<font class="type">MorphingObject</FONT> <font class="variable-name">morph</FONT> = ...
 110.174 -<font class="type">AnInterface</font> <font class="variable-name">impl</font> = (<font
 110.175 -class="type">AnInterface</font>)morph.getLookup().<a
 110.176 -href="@TOP@org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(AnInterface.<font class="keyword">class</font>);
 110.177 -<font class="keyword">if</font> (impl == <font class="constant">null</font>) {
 110.178 -    <font class="keyword">return;</font><font class="comment">/* AnInterface not supported now! */</font>
 110.179 -}
 110.180 -impl.useIt();
 110.181 -</PRE>
 110.182 -
 110.183 -<H2>Additional functionality</H2>
 110.184 -The NetBeans lookup library also provides:
 110.185 -<UL>
 110.186 -<LI>Support for dynamically changing the lookup content.</LI>
 110.187 -<LI>The ability to return multiple results.</LI>
 110.188 -<LI>Notification of changes. After retrieving the result, the client can attach a
 110.189 -listener and be notified when the result of the lookup is changed.</LI>
 110.190 -<LI>Lazy initialization of the implementation. The implementation objects are
 110.191 -initialized only after someone asks for them. Even the implementation classes
 110.192 -are not loaded if they are not going to be used! </LI>
 110.193 -</UL>
 110.194 -
 110.195 -<H2>Further information</H2>
 110.196 -<UL>
 110.197 -  <LI><A HREF="lookup-api.html">Lookup Library APIs</A> for those writing the client code.
 110.198 -Specifying the query, getting the result and listenning on changes.</LI>
 110.199 -  <LI><A HREF="lookup-spi.html">Lookup Library SPIs</A> for those writing the
 110.200 -implementaion code and registering it with lookup. Includes also writing own
 110.201 -lookup implementation.</LI>
 110.202 -  <LI>Download <A HREF="http://www.netbeans.org/">NetBeans platform</A> which
 110.203 -contains <code>org-openide-util.jar</code></LI>
 110.204 -    <A HREF="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/lookup/">
 110.205 -    implementation package (org.openide.util.lookup) </A>
 110.206 -    + classes Lookup, LookupEvent, LookupListener in
 110.207 -    <A href="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/">util package</A></LI>
 110.208 -  <li><a href="http://www.martinfowler.com/articles/injection.html">Inversion of Control Containers and the Dependency Injection pattern</a> (Martin Fowler)</li>
 110.209 -</UL>
 110.210 -</BODY>
 110.211 -</HTML>
   111.1 --- a/openide.util/src/org/openide/util/lookup/doc-files/lookup-api.html	Thu Dec 10 19:23:25 2009 -0500
   111.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.3 @@ -1,188 +0,0 @@
   111.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
   111.5 -<!--
   111.6 -   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   111.7 -   -
   111.8 -   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
   111.9 -   -
  111.10 -   - The contents of this file are subject to the terms of either the GNU
  111.11 -   - General Public License Version 2 only ("GPL") or the Common
  111.12 -   - Development and Distribution License("CDDL") (collectively, the
  111.13 -   - "License"). You may not use this file except in compliance with the
  111.14 -   - License. You can obtain a copy of the License at
  111.15 -   - http://www.netbeans.org/cddl-gplv2.html
  111.16 -   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  111.17 -   - specific language governing permissions and limitations under the
  111.18 -   - License.  When distributing the software, include this License Header
  111.19 -   - Notice in each file and include the License file at
  111.20 -   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  111.21 -   - particular file as subject to the "Classpath" exception as provided
  111.22 -   - by Sun in the GPL Version 2 section of the License file that
  111.23 -   - accompanied this code. If applicable, add the following below the
  111.24 -   - License Header, with the fields enclosed by brackets [] replaced by
  111.25 -   - your own identifying information:
  111.26 -   - "Portions Copyrighted [year] [name of copyright owner]"
  111.27 -   -
  111.28 -   - Contributor(s):
  111.29 -   -
  111.30 -   - The Original Software is NetBeans. The Initial Developer of the Original
  111.31 -   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  111.32 -   - Microsystems, Inc. All Rights Reserved.
  111.33 -   -
  111.34 -   - If you wish your version of this file to be governed by only the CDDL
  111.35 -   - or only the GPL Version 2, indicate your decision by adding
  111.36 -   - "[Contributor] elects to include this software in this distribution
  111.37 -   - under the [CDDL or GPL Version 2] license." If you do not indicate a
  111.38 -   - single choice of license, a recipient has the option to distribute
  111.39 -   - your version of this file under either the CDDL, the GPL Version 2 or
  111.40 -   - to extend the choice of license to its licensees as provided above.
  111.41 -   - However, if you add GPL Version 2 code and therefore, elected the GPL
  111.42 -   - Version 2 license, then the option applies only if the new code is
  111.43 -   - made subject to such option by the copyright holder.
  111.44 -  -->
  111.45 -<HTML>
  111.46 -<HEAD>
  111.47 -<TITLE>Lookup Library API</TITLE>
  111.48 -<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
  111.49 -</HEAD>
  111.50 -<BODY>
  111.51 -<H1>Lookup library API</H1>
  111.52 -<p>
  111.53 -This document describes usage of the API provided by the Lookup Library. In this
  111.54 -document we assume that someone has already provided us with a lookup
  111.55 -implementation (for those seeking how to write a lookup implementation please
  111.56 -check <A href="lookup-spi.html">the SPI document</A>).
  111.57 -
  111.58 -<H2> Getting the lookup </H2>
  111.59 -
  111.60 -The first question you might ask is this: how can I get hold of a
  111.61 -lookup instance? There are basically two ways how you can get it.
  111.62 -
  111.63 -<H3> Global lookup </H3>
  111.64 -As you can see in the
  111.65 -
  111.66 -<a href="@TOP@org/openide/util/Lookup.html">Lookup</a>
  111.67 -
  111.68 -Javadoc there is a static method
  111.69 -
  111.70 -<pre><a href="@TOP@org/openide/util/Lookup.html#getDefault()">public static Lookup getDefault()</a></pre>
  111.71 -
  111.72 -The object returned from this method is
  111.73 -a global lookup that can serve as a central place for registering services.
  111.74 -The default implementation is a lookup that implements
  111.75 -<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">
  111.76 -the JDK JAR services</A>
  111.77 -mechanism and delegates to <samp>META-INF/services/name.of.Class</samp> files.
  111.78 -<P>
  111.79 -If you want to add your class to this lookup just create a file in your
  111.80 -jar file under the <code>META-INF</code> directory (e.g. <samp>META-INF/services/com.my.APIClass</samp>)
  111.81 -and let the file contain only one line of text
  111.82 -
  111.83 -<pre>com.foo.impl.ImplOfTheAPI</pre>
  111.84 -
  111.85 -<p>(This is more easily done using the <code>@ServiceProvider</code> annotation.)</p>
  111.86 -
  111.87 -The following code will return you a newly created instance of
  111.88 -<code>com.foo.impl.ImplOfTheAPI</code>:
  111.89 -
  111.90 -<PRE>
  111.91 -   <font class="keyword">import</FONT> org.openide.util.Lookup;
  111.92 -   return Lookup.getDefault().lookup(com.my.APIClass.class);
  111.93 -</PRE>
  111.94 -
  111.95 -<H3> Local lookup </H3>
  111.96 -
  111.97 -This is just a reminder that whenever you find a method called getLookup
  111.98 -or similar returning a lookup instance, the provided lookup is <EM>not</EM> the
  111.99 -general lookup described in the previous paragraph. Rather, it is a private lookup
 111.100 -implementation that is usually bound to the object you invoked the method on.
 111.101 -
 111.102 -<H2> Use of Lookup.Template and Lookup.Result </H2>
 111.103 -
 111.104 -There are more ways how you can ask lookup besides the variant with one class
 111.105 -parameter. If you want more functionality, you have to implement the interface
 111.106 -Lookup.Template and pass an instance of such object to the lookup call.
 111.107 -<p>
 111.108 -<EM>Note:</EM> If you use Lookup.Template, the object returned from the lookup is
 111.109 -<EM>not</EM> the object you are looking for but rather a result object
 111.110 -(Lookup.Result). You can call methods on such a result object to get the actual
 111.111 -results.
 111.112 -<p>
 111.113 -Let's examine following example:
 111.114 -
 111.115 -<pre>
 111.116 -        <font class="keyword">import</FONT> org.openide.util.Lookup;
 111.117 -
 111.118 -        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
 111.119 -        Lookup.<font class="type">Template</font> <font class="variable-name">template</font> = <font class="keyword">new</font> Lookup.<font class="type">Template</font>(MyService.<font class="keyword">class</font>);
 111.120 -        Lookup.<font class="type">Result</font> <font class="variable-name">result</font> = lookup.lookup(template);
 111.121 -        <font class="type">Collection</font> <font class="variable-name">c</font> = result.allInstances();
 111.122 -        <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = c.iterator(); i.hasNext(); ) {
 111.123 -            <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
 111.124 -            s.callMyService();
 111.125 -        }
 111.126 -</pre>
 111.127 -
 111.128 -In this example the call to method lookup(...) returns immediately because the
 111.129 -result object can be constructed even without real results. The first time you
 111.130 -ask for the result object by calling r.allInstances(), the lookup has to supply you
 111.131 -the real results and this method can block until the required data are really
 111.132 -available.
 111.133 -<p>
 111.134 -If you are not interested in all objects as in the previous example, you can use the
 111.135 -template to ask for one resulting object (wrapped in special Item instance):
 111.136 -<pre>
 111.137 -        <font class="keyword">import</FONT> org.openide.util.Lookup;
 111.138 -
 111.139 -        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
 111.140 -        Lookup.<font class="type">Template</font> <font class="variable-name">template</font> = <font class="keyword">new</font> Lookup.<font class="type">Template</font>(MyService.<font class="keyword">class</font>);
 111.141 -        Lookup.<font class="type">Item</font> <font class="variable-name">item</font> = lookup.lookupItem(template);
 111.142 -        <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)item.getInstance();
 111.143 -        s.callMyService();
 111.144 -</pre>
 111.145 -
 111.146 -Again, the Item object can construct the real instance only if you call
 111.147 -getInstance. The item can be useful even without calling getInstance - you can get
 111.148 -its display name or an unique id. You can use this information, for example, for
 111.149 -constructing menu items without the need to instantiate (or even load!)
 111.150 -the class implementing the functionality. Only when the real functionality is
 111.151 -needed (e.g. the user has selected the menu item) you can call getInstance
 111.152 -and call the real meat of the implementation.
 111.153 -
 111.154 -<H2> Listenning on lookup changes </H2>
 111.155 -There is one additional piece of functionality bound to the Lookup.Result object worth
 111.156 -mentioning: you can attach a listener to it and be informed about any changes in
 111.157 -the lookup. This might be extremly usefull when the lookup dynamically changes
 111.158 -(from other threads). The listener can keep state of your object up-to-date even
 111.159 -in cases where the lookup changes asynchronously.
 111.160 -<p>
 111.161 -So here is some sample code using the listenner:
 111.162 -
 111.163 -<pre>
 111.164 -        <font class="keyword">import</FONT> org.openide.util.Lookup;
 111.165 -        <font class="keyword">import</FONT> org.openide.util.LookupListener;
 111.166 -        <font class="keyword">import</FONT> org.openide.util.LookupEvent;
 111.167 -
 111.168 -        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
 111.169 -        Lookup.<font class="type">Template</font> <font class="variable-name">template</font> = <font class="keyword">new</font> Lookup.<font class="type">Template</font>(MyService.<font class="keyword">class</font>);
 111.170 -        <font class="keyword">final</font> <font class="variable-name">Lookup</font>.<font class="type">Result</font> <font class="variable-name">result</font> = lookup.lookup(template);
 111.171 -        result.addLookupListener(<font class="keyword">new</font> <font class="type">LookupListener</font>() {
 111.172 -            <font class="keyword">public</font> <font class="type">void</font> <font class="function-name">resultChanged</font>(<font class="type">LookupEvent</font> <font class="variable-name">e</font>) {
 111.173 -                reaction(result);
 111.174 -            }
 111.175 -        });
 111.176 -        reaction(result);
 111.177 -    }
 111.178 -    <font class="keyword">private</font> <font class="keyword">static</font> <font class="type">void</font> <font class="function-name">reaction</font>(Lookup.<font class="type">Result</font> <font class="variable-name">r</font>) {
 111.179 -        <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = r.allInstances().iterator(); i.hasNext(); ) {
 111.180 -            <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
 111.181 -            s.callMyService();
 111.182 -        }
 111.183 -    }
 111.184 -</pre>
 111.185 -
 111.186 -Please note that we first attach a listener and then call the reaction method.
 111.187 -This ensures that we always get the newest possible state. Also you must be
 111.188 -careful in the reaction method since it can be called from two different
 111.189 -threads simultaneously (your code has to be prepared for this).
 111.190 -</BODY>
 111.191 -</HTML>
   112.1 --- a/openide.util/src/org/openide/util/lookup/doc-files/lookup-spi.html	Thu Dec 10 19:23:25 2009 -0500
   112.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.3 @@ -1,147 +0,0 @@
   112.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
   112.5 -<!--
   112.6 -   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   112.7 -   -
   112.8 -   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
   112.9 -   -
  112.10 -   - The contents of this file are subject to the terms of either the GNU
  112.11 -   - General Public License Version 2 only ("GPL") or the Common
  112.12 -   - Development and Distribution License("CDDL") (collectively, the
  112.13 -   - "License"). You may not use this file except in compliance with the
  112.14 -   - License. You can obtain a copy of the License at
  112.15 -   - http://www.netbeans.org/cddl-gplv2.html
  112.16 -   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  112.17 -   - specific language governing permissions and limitations under the
  112.18 -   - License.  When distributing the software, include this License Header
  112.19 -   - Notice in each file and include the License file at
  112.20 -   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  112.21 -   - particular file as subject to the "Classpath" exception as provided
  112.22 -   - by Sun in the GPL Version 2 section of the License file that
  112.23 -   - accompanied this code. If applicable, add the following below the
  112.24 -   - License Header, with the fields enclosed by brackets [] replaced by
  112.25 -   - your own identifying information:
  112.26 -   - "Portions Copyrighted [year] [name of copyright owner]"
  112.27 -   -
  112.28 -   - Contributor(s):
  112.29 -   -
  112.30 -   - The Original Software is NetBeans. The Initial Developer of the Original
  112.31 -   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  112.32 -   - Microsystems, Inc. All Rights Reserved.
  112.33 -   -
  112.34 -   - If you wish your version of this file to be governed by only the CDDL
  112.35 -   - or only the GPL Version 2, indicate your decision by adding
  112.36 -   - "[Contributor] elects to include this software in this distribution
  112.37 -   - under the [CDDL or GPL Version 2] license." If you do not indicate a
  112.38 -   - single choice of license, a recipient has the option to distribute
  112.39 -   - your version of this file under either the CDDL, the GPL Version 2 or
  112.40 -   - to extend the choice of license to its licensees as provided above.
  112.41 -   - However, if you add GPL Version 2 code and therefore, elected the GPL
  112.42 -   - Version 2 license, then the option applies only if the new code is
  112.43 -   - made subject to such option by the copyright holder.
  112.44 -  -->
  112.45 -<HTML>
  112.46 -<HEAD>
  112.47 -<TITLE>Lookup Library SPI</TITLE>
  112.48 -<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
  112.49 -</HEAD>
  112.50 -<BODY>
  112.51 -<H1>Lookup library SPI</H1>
  112.52 -This document describe usage of the SPI provided by the Lookup Library
  112.53 -(for those seeking how to use lookup instance please
  112.54 -check <A href="lookup-api.html">the API document</A>).
  112.55 -<p>
  112.56 -By using the SPI you can create lookups that can be used by the users of the
  112.57 -Lookup API. While the Lookup API consists of a couple of classes in the package
  112.58 -<em>org.openide.util.*</EM>,
  112.59 -the SPI has its own package <em>org.openide.util.lookup.*</EM>.
  112.60 -
  112.61 -<H2> Simple lookups </H2>
  112.62 -Let us start with the simplest case. You have decided that your newly created
  112.63 -object will provide an API in the form of a getLookup() method. You have to
  112.64 -return a functional lookup from this call. You can use static methods in class
  112.65 -<a href="@TOP@org/openide/util/lookup/Lookups.html">
  112.66 -<code>Lookups</code></A> to create a lookup for you. If you want only one
  112.67 -object to be returned, just call 
  112.68 -<a href="@TOP@org/openide/util/lookup/Lookups.html#singleton(java.lang.Object)">
  112.69 -<code>Lookups.singleton(x)</code></A> where x is the object to be 
  112.70 -returned by the lookup. Or if you want to supply more objects, use a call to the method
  112.71 -<a href="@TOP@org/openide/util/lookup/Lookups.html#fixed(java.lang.Object...)">
  112.72 -<code>fixed(Object []x)</CODE></A>.
  112.73 -<EM> Note: </EM> The lookups returned from methods <code>singleton(...)</code> and
  112.74 -<code>fixed(...)</code> do <EM>
  112.75 -not </EM> support dynamic changes and attaching listeners. Their content is
  112.76 -fixed from the time you call the creating method.
  112.77 -
  112.78 -<H2> ProxyLookup </H2>
  112.79 -There can be situations where you get a lookup object from someone else and you
  112.80 -want your lookup to return exactly the instances from the original lookup plus
  112.81 -your own results. Here the class ProxyLookup comes into the play.
  112.82 -<p>
  112.83 -You simply create a new lookup like this:
  112.84 -
  112.85 -<pre>
  112.86 -    <font class="keyword">import</FONT> org.openide.util.Lookup;
  112.87 -    <font class="keyword">import</FONT> org.openide.util.lookup.*;
  112.88 -
  112.89 -    <font class="type">Lookup</font> <font class="variable-name">lookup1</font> = ...;
  112.90 -
  112.91 -    <font class="type">Lookup</font> <font class="variable-name">lookup2</font> = Lookups.singleton(MyService.<font class="keyword">class</font>);
  112.92 -    <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">ProxyLookup</font>(<font class="keyword">new</font> <font class="type">Lookup</font>[] { lookup, lookup2 });
  112.93 -</pre>
  112.94 -
  112.95 -<H2> AbstractLookup </H2>
  112.96 -<!-- This paragraph originally copied from
  112.97 -@TOP@org/openide/doc-files/services-api.html#lookup-impl
  112.98 --->
  112.99 -
 112.100 -<p>The most powerful way to provide a lookup is to directly define
 112.101 -what instances and items it should provide, by subclassing. For this,
 112.102 -
 112.103 -<a href="@TOP@org/openide/util/lookup/AbstractLookup.html"><code>AbstractLookup</code></a>
 112.104 -
 112.105 -is recommended as it is easiest to use.
 112.106 -
 112.107 -<p>The simplest way to use <code>AbstractLookup</code> is to use its
 112.108 -public constructor (in which case you need not subclass it). Here you
 112.109 -provide an
 112.110 -
 112.111 -<a href="@TOP@org/openide/util/lookup/AbstractLookup.Content.html"><code>AbstractLookup.Content</code></a>
 112.112 -
 112.113 -object which you have created and hold on to privately, and which
 112.114 -keeps track of instances and permits them to be registered and
 112.115 -deregistered. Often
 112.116 -
 112.117 -<a href="@TOP@org/openide/util/lookup/InstanceContent.html"><code>InstanceContent</code></a>
 112.118 -
 112.119 -is used as the content implementation. To add something to the lookup,
 112.120 -simply use
 112.121 -
 112.122 -<a href="@TOP@org/openide/util/lookup/InstanceContent.html#add(java.lang.Object)"><code>add(Object)</code></a>
 112.123 -
 112.124 -(and <code>remove(Object)</code> for the reverse). These may be called
 112.125 -at any time and will update the set of registered instances (firing
 112.126 -result changes as needed).
 112.127 -
 112.128 -<pre>
 112.129 -    <font class="keyword">import</FONT> org.openide.util.lookup.*;
 112.130 -    <font class="type">InstanceContent</font> <font class="variable-name">ic</font> = <font class="keyword">new</font> <font class="type">InstanceContent</font> ();
 112.131 -    ic.add(firstObject);
 112.132 -    <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">AbstractLookup</font> (ic);
 112.133 -</pre>
 112.134 -
 112.135 -<p>In case it is expensive to actually compute the object in the
 112.136 -lookup, but there is some cheap "key" which can easily generate it,
 112.137 -you may instead register the key by passing in an
 112.138 -
 112.139 -<a href="@TOP@org/openide/util/lookup/InstanceContent.Convertor.html"><code>InstanceContent.Convertor</code></a>.
 112.140 -
 112.141 -This convertor translates the key to the real instance that the lookup
 112.142 -client sees, if and when needed. For example, if you have a long list
 112.143 -of class names and wish to register default instances of each class,
 112.144 -you might actually register the class name as the key, and supply a
 112.145 -convertor which really loads the class and instantiates it. This makes
 112.146 -it easy to set up the lookup, but nothing is really loaded until
 112.147 -someone asks for it.
 112.148 -
 112.149 -</BODY>
 112.150 -</HTML>
   113.1 --- a/openide.util/src/org/openide/util/lookup/package.html	Thu Dec 10 19:23:25 2009 -0500
   113.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.3 @@ -1,48 +0,0 @@
   113.4 -<!--
   113.5 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   113.6 -
   113.7 -Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   113.8 -
   113.9 -
  113.10 -The contents of this file are subject to the terms of either the GNU
  113.11 -General Public License Version 2 only ("GPL") or the Common
  113.12 -Development and Distribution License("CDDL") (collectively, the
  113.13 -"License"). You may not use this file except in compliance with the
  113.14 -License. You can obtain a copy of the License at
  113.15 -http://www.netbeans.org/cddl-gplv2.html
  113.16 -or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  113.17 -specific language governing permissions and limitations under the
  113.18 -License.  When distributing the software, include this License Header
  113.19 -Notice in each file and include the License file at
  113.20 -nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  113.21 -particular file as subject to the "Classpath" exception as provided
  113.22 -by Sun in the GPL Version 2 section of the License file that
  113.23 -accompanied this code. If applicable, add the following below the
  113.24 -License Header, with the fields enclosed by brackets [] replaced by
  113.25 -your own identifying information:
  113.26 -"Portions Copyrighted [year] [name of copyright owner]"
  113.27 -
  113.28 -Contributor(s):
  113.29 -
  113.30 -The Original Software is NetBeans. The Initial Developer of the Original
  113.31 -Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  113.32 -Microsystems, Inc. All Rights Reserved.
  113.33 -
  113.34 -If you wish your version of this file to be governed by only the CDDL
  113.35 -or only the GPL Version 2, indicate your decision by adding
  113.36 -"[Contributor] elects to include this software in this distribution
  113.37 -under the [CDDL or GPL Version 2] license." If you do not indicate a
  113.38 -single choice of license, a recipient has the option to distribute
  113.39 -your version of this file under either the CDDL, the GPL Version 2 or
  113.40 -to extend the choice of license to its licensees as provided above.
  113.41 -However, if you add GPL Version 2 code and therefore, elected the GPL
  113.42 -Version 2 license, then the option applies only if the new code is
  113.43 -made subject to such option by the copyright holder.
  113.44 --->
  113.45 -
  113.46 -<html>
  113.47 -<body>
  113.48 -Support classes for the Registration and {@link org.openide.util.Lookup} extension mechanism.
  113.49 -Read more: <a href="doc-files/index.html">Lookup Library</a>
  113.50 -</body>
  113.51 -</html>
   114.1 --- a/openide.util/test/unit/src/org/bar/Comparator2.java	Thu Dec 10 19:23:25 2009 -0500
   114.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.3 @@ -1,7 +0,0 @@
   114.4 -
   114.5 -package org.bar;
   114.6 -
   114.7 -public class Comparator2 implements java.util.Comparator {
   114.8 -    public int compare(Object o1, Object o2) {return 0;}
   114.9 -    public boolean equals(Object obj) {return true;}
  114.10 -}
   115.1 --- a/openide.util/test/unit/src/org/bar/Comparator3.java	Thu Dec 10 19:23:25 2009 -0500
   115.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.3 @@ -1,7 +0,0 @@
   115.4 -
   115.5 -package org.bar;
   115.6 -
   115.7 -public class Comparator3 implements java.util.Comparator {
   115.8 -    public int compare(Object o1, Object o2) {return 0;}
   115.9 -    public boolean equals(Object obj) {return true;}
  115.10 -}
   116.1 --- a/openide.util/test/unit/src/org/bar/Implementation2.java	Thu Dec 10 19:23:25 2009 -0500
   116.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.3 @@ -1,3 +0,0 @@
   116.4 -package org.bar;
   116.5 -import org.foo.Interface;
   116.6 -public class Implementation2 implements Interface {}
   117.1 --- a/openide.util/test/unit/src/org/bar/Iterator2.java	Thu Dec 10 19:23:25 2009 -0500
   117.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.3 @@ -1,11 +0,0 @@
   117.4 -
   117.5 -package org.bar;
   117.6 -
   117.7 -public class Iterator2 implements java.util.Iterator {
   117.8 -    public boolean hasNext() {return false;}
   117.9 -    
  117.10 -    public Object next() {return null;}
  117.11 -    
  117.12 -    public void remove() {}
  117.13 -   
  117.14 -}
   118.1 --- a/openide.util/test/unit/src/org/foo/Interface.java	Thu Dec 10 19:23:25 2009 -0500
   118.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.3 @@ -1,2 +0,0 @@
   118.4 -package org.foo;
   118.5 -public interface Interface {}
   119.1 --- a/openide.util/test/unit/src/org/foo/impl/Comparator1.java	Thu Dec 10 19:23:25 2009 -0500
   119.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.3 @@ -1,7 +0,0 @@
   119.4 -
   119.5 -package org.foo.impl;
   119.6 -
   119.7 -public class Comparator1 implements java.util.Comparator {
   119.8 -    public int compare(Object o1, Object o2) {return 0;}
   119.9 -    public boolean equals(Object obj) {return true;}
  119.10 -}
   120.1 --- a/openide.util/test/unit/src/org/foo/impl/Implementation1.java	Thu Dec 10 19:23:25 2009 -0500
   120.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.3 @@ -1,3 +0,0 @@
   120.4 -package org.foo.impl;
   120.5 -import org.foo.Interface;
   120.6 -public class Implementation1 implements Interface {}
   121.1 --- a/openide.util/test/unit/src/org/foo/impl/Iterator1.java	Thu Dec 10 19:23:25 2009 -0500
   121.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.3 @@ -1,11 +0,0 @@
   121.4 -
   121.5 -package org.foo.impl;
   121.6 -
   121.7 -public class Iterator1 implements java.util.Iterator {
   121.8 -    public boolean hasNext() {return false;}
   121.9 -    
  121.10 -    public Object next() {return null;}
  121.11 -    
  121.12 -    public void remove() {}
  121.13 -   
  121.14 -}
   122.1 --- a/openide.util/test/unit/src/org/foo/impl/Runnable1.java	Thu Dec 10 19:23:25 2009 -0500
   122.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.3 @@ -1,6 +0,0 @@
   122.4 -
   122.5 -package org.foo.impl;
   122.6 -
   122.7 -public class Runnable1 implements Runnable {
   122.8 -   public void run () {}
   122.9 -}
   123.1 --- a/openide.util/test/unit/src/org/netbeans/modules/openide/util/ServiceProviderProcessorTest.java	Thu Dec 10 19:23:25 2009 -0500
   123.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.3 @@ -1,180 +0,0 @@
   123.4 -/*
   123.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   123.6 - *
   123.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
   123.8 - *
   123.9 - * The contents of this file are subject to the terms of either the GNU
  123.10 - * General Public License Version 2 only ("GPL") or the Common
  123.11 - * Development and Distribution License("CDDL") (collectively, the
  123.12 - * "License"). You may not use this file except in compliance with the
  123.13 - * License. You can obtain a copy of the License at
  123.14 - * http://www.netbeans.org/cddl-gplv2.html
  123.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  123.16 - * specific language governing permissions and limitations under the
  123.17 - * License.  When distributing the software, include this License Header
  123.18 - * Notice in each file and include the License file at
  123.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  123.20 - * particular file as subject to the "Classpath" exception as provided
  123.21 - * by Sun in the GPL Version 2 section of the License file that
  123.22 - * accompanied this code. If applicable, add the following below the
  123.23 - * License Header, with the fields enclosed by brackets [] replaced by
  123.24 - * your own identifying information:
  123.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  123.26 - *
  123.27 - * If you wish your version of this file to be governed by only the CDDL
  123.28 - * or only the GPL Version 2, indicate your decision by adding
  123.29 - * "[Contributor] elects to include this software in this distribution
  123.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  123.31 - * single choice of license, a recipient has the option to distribute
  123.32 - * your version of this file under either the CDDL, the GPL Version 2 or
  123.33 - * to extend the choice of license to its licensees as provided above.
  123.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  123.35 - * Version 2 license, then the option applies only if the new code is
  123.36 - * made subject to such option by the copyright holder.
  123.37 - *
  123.38 - * Contributor(s):
  123.39 - *
  123.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  123.41 - */
  123.42 -
  123.43 -package org.netbeans.modules.openide.util;
  123.44 -
  123.45 -import java.io.ByteArrayOutputStream;
  123.46 -import java.io.File;
  123.47 -import java.util.ArrayList;
  123.48 -import java.util.Arrays;
  123.49 -import java.util.Collections;
  123.50 -import java.util.Comparator;
  123.51 -import java.util.List;
  123.52 -import org.netbeans.junit.NbTestCase;
  123.53 -import org.openide.util.Lookup;
  123.54 -import org.openide.util.lookup.Lookups;
  123.55 -import org.openide.util.lookup.ServiceProvider;
  123.56 -import org.openide.util.lookup.ServiceProviders;
  123.57 -import org.openide.util.test.AnnotationProcessorTestUtils;
  123.58 -
  123.59 -public class ServiceProviderProcessorTest extends NbTestCase {
  123.60 -
  123.61 -    public ServiceProviderProcessorTest(String n) {
  123.62 -        super(n);
  123.63 -    }
  123.64 -
  123.65 -    private static List<Class<?>> classesOf(Iterable<?> objects) {
  123.66 -        List<Class<?>> cs = new ArrayList<Class<?>>();
  123.67 -        for (Object o : objects) {
  123.68 -            cs.add(o.getClass());
  123.69 -        }
  123.70 -        return cs;
  123.71 -    }
  123.72 -
  123.73 -    private static List<Class<?>> classesOfLookup(Class<?> xface) {
  123.74 -        return classesOf(Lookup.getDefault().lookupAll(xface));
  123.75 -    }
  123.76 -
  123.77 -    private static List<Class<?>> sortClassList(List<Class<?>> classes) {
  123.78 -        List<Class<?>> sorted = new ArrayList<Class<?>>(classes);
  123.79 -        Collections.sort(sorted, new Comparator<Class<?>>() {
  123.80 -            public int compare(Class<?> c1, Class<?> c2) {
  123.81 -                return c1.getName().compareTo(c2.getName());
  123.82 -            }
  123.83 -        });
  123.84 -        return sorted;
  123.85 -    }
  123.86 -
  123.87 -    public void testBasicUsage() throws Exception {
  123.88 -        assertEquals(Collections.singletonList(Implementation.class), classesOfLookup(Interface.class));
  123.89 -    }
  123.90 -    public interface Interface {}
  123.91 -    @ServiceProvider(service=Interface.class)
  123.92 -    public static class Implementation implements Interface {}
  123.93 -
  123.94 -    public void testPosition() throws Exception {
  123.95 -        assertEquals(Arrays.<Class<?>>asList(OrderedImpl3.class, OrderedImpl2.class, OrderedImpl1.class), classesOfLookup(OrderedInterface.class));
  123.96 -    }
  123.97 -    public interface OrderedInterface {}
  123.98 -    @ServiceProvider(service=OrderedInterface.class)
  123.99 -    public static class OrderedImpl1 implements OrderedInterface {}
 123.100 -    @ServiceProvider(service=OrderedInterface.class, position=200)
 123.101 -    public static class OrderedImpl2 implements OrderedInterface {}
 123.102 -    @ServiceProvider(service=OrderedInterface.class, position=100)
 123.103 -    public static class OrderedImpl3 implements OrderedInterface {}
 123.104 -
 123.105 -    public void testPath() throws Exception {
 123.106 -        assertEquals(Collections.singletonList(PathImplementation.class), classesOf(Lookups.forPath("some/path").lookupAll(Interface.class)));
 123.107 -    }
 123.108 -    @ServiceProvider(service=Interface.class, path="some/path")
 123.109 -    public static class PathImplementation implements Interface {}
 123.110 -
 123.111 -    public void testSupersedes() throws Exception {
 123.112 -        assertEquals(Arrays.<Class<?>>asList(Overrider.class, Unrelated.class), sortClassList(classesOfLookup(CancellableInterface.class)));
 123.113 -    }
 123.114 -    public interface CancellableInterface {}
 123.115 -    @ServiceProvider(service=CancellableInterface.class)
 123.116 -    public static class Overridden implements CancellableInterface {}
 123.117 -    @ServiceProvider(service=CancellableInterface.class, supersedes="org.netbeans.modules.openide.util.ServiceProviderProcessorTest$Overridden")
 123.118 -    public static class Overrider implements CancellableInterface {}
 123.119 -    @ServiceProvider(service=CancellableInterface.class)
 123.120 -    public static class Unrelated implements CancellableInterface {}
 123.121 -
 123.122 -    public void testMultipleRegistrations() throws Exception {
 123.123 -        assertEquals(Collections.singletonList(Multitasking.class), classesOfLookup(Interface1.class));
 123.124 -        assertEquals(Collections.singletonList(Multitasking.class), classesOfLookup(Interface2.class));
 123.125 -    }
 123.126 -    public interface Interface1 {}
 123.127 -    public interface Interface2 {}
 123.128 -    @ServiceProviders({@ServiceProvider(service=Interface1.class), @ServiceProvider(service=Interface2.class)})
 123.129 -    public static class Multitasking implements Interface1, Interface2 {}
 123.130 -
 123.131 -    public void testErrorReporting() throws Exception {
 123.132 -        clearWorkDir();
 123.133 -        File src = new File(getWorkDir(), "src");
 123.134 -        File dest = new File(getWorkDir(), "classes");
 123.135 -        String xfaceName = Interface.class.getCanonicalName();
 123.136 -
 123.137 -        AnnotationProcessorTestUtils.makeSource(src, "p.C1",
 123.138 -                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
 123.139 -                "public class C1 implements " + xfaceName + " {}");
 123.140 -        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 123.141 -        assertTrue(AnnotationProcessorTestUtils.runJavac(src, "C1", dest, null, baos));
 123.142 -
 123.143 -        AnnotationProcessorTestUtils.makeSource(src, "p.C2",
 123.144 -                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
 123.145 -                "class C2 implements " + xfaceName + " {}");
 123.146 -        baos = new ByteArrayOutputStream();
 123.147 -        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C2", dest, null, baos));
 123.148 -        assertTrue(baos.toString(), baos.toString().contains("public"));
 123.149 -
 123.150 -        AnnotationProcessorTestUtils.makeSource(src, "p.C3",
 123.151 -                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
 123.152 -                "public class C3 implements " + xfaceName + " {",
 123.153 -                "public C3(boolean x) {}",
 123.154 -                "}");
 123.155 -        baos = new ByteArrayOutputStream();
 123.156 -        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C3", dest, null, baos));
 123.157 -        assertTrue(baos.toString(), baos.toString().contains("constructor"));
 123.158 -
 123.159 -        AnnotationProcessorTestUtils.makeSource(src, "p.C4",
 123.160 -                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
 123.161 -                "public class C4 implements " + xfaceName + " {",
 123.162 -                "C4() {}",
 123.163 -                "}");
 123.164 -        baos = new ByteArrayOutputStream();
 123.165 -        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C4", dest, null, baos));
 123.166 -        assertTrue(baos.toString(), baos.toString().contains("constructor"));
 123.167 -
 123.168 -        AnnotationProcessorTestUtils.makeSource(src, "p.C5",
 123.169 -                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
 123.170 -                "public abstract class C5 implements " + xfaceName + " {}");
 123.171 -        baos = new ByteArrayOutputStream();
 123.172 -        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C5", dest, null, baos));
 123.173 -        assertTrue(baos.toString(), baos.toString().contains("abstract"));
 123.174 -
 123.175 -        AnnotationProcessorTestUtils.makeSource(src, "p.C6",
 123.176 -                "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)",
 123.177 -                "public class C6 {}");
 123.178 -        baos = new ByteArrayOutputStream();
 123.179 -        assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C6", dest, null, baos));
 123.180 -        assertTrue(baos.toString(), baos.toString().contains("assignable"));
 123.181 -    }
 123.182 -
 123.183 -}
   124.1 --- a/openide.util/test/unit/src/org/openide/util/InitJobTest.java	Thu Dec 10 19:23:25 2009 -0500
   124.2 +++ b/openide.util/test/unit/src/org/openide/util/InitJobTest.java	Mon Dec 14 20:58:39 2009 +0100
   124.3 @@ -81,6 +81,11 @@
   124.4      protected boolean runInEQ() {
   124.5          return true;
   124.6      }
   124.7 +
   124.8 +    @Override
   124.9 +    protected int timeOut() {
  124.10 +        return 15000;
  124.11 +    }
  124.12      
  124.13      /** Basic testing of Utilities.attachInitJob, if calls to AsyncGUIJob
  124.14       * impl conforms to the API behaviour described in javadoc *
   125.1 --- a/openide.util/test/unit/src/org/openide/util/UtilitiesActiveQueueTest.java	Thu Dec 10 19:23:25 2009 -0500
   125.2 +++ b/openide.util/test/unit/src/org/openide/util/UtilitiesActiveQueueTest.java	Mon Dec 14 20:58:39 2009 +0100
   125.3 @@ -114,48 +114,6 @@
   125.4          }
   125.5      }
   125.6      
   125.7 -    public void testMemoryLeak() throws Exception {
   125.8 -        final Class<?> u1 = Utilities.class;
   125.9 -        class L extends URLClassLoader {
  125.10 -            public L() {
  125.11 -                super(new URL[] {u1.getProtectionDomain().getCodeSource().getLocation()}, u1.getClassLoader().getParent());
  125.12 -            }
  125.13 -            protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
  125.14 -                if (name.equals(u1.getName()) || name.startsWith(u1.getName() + "$")) {
  125.15 -                    Class c = findLoadedClass(name);
  125.16 -                    if (c == null) {
  125.17 -                        c = findClass(name);
  125.18 -                    }
  125.19 -                    if (resolve) {
  125.20 -                        resolveClass(c);
  125.21 -                    }
  125.22 -                    return c;
  125.23 -                } else {
  125.24 -                    return super.loadClass(name, resolve);
  125.25 -                }
  125.26 -            }
  125.27 -        }
  125.28 -        ClassLoader l = new L();
  125.29 -        Class<?> u2 = l.loadClass(u1.getName());
  125.30 -        assertEquals(l, u2.getClassLoader());
  125.31 -        Object obj = new Object();
  125.32 -        @SuppressWarnings("unchecked")
  125.33 -        ReferenceQueue<Object> q = (ReferenceQueue<Object>) u2.getMethod("activeReferenceQueue").invoke(null);
  125.34 -        RunnableRef ref = new RunnableRef(obj, q);
  125.35 -        synchronized (ref) {
  125.36 -            obj = null;
  125.37 -            assertGC("Ref should be GC'ed as usual", ref);
  125.38 -            ref.wait();
  125.39 -            assertTrue("Run method has been executed", ref.executed);
  125.40 -        }
  125.41 -        Reference<?> r = new WeakReference<Object>(u2);
  125.42 -        q = null;
  125.43 -        u2 = null;
  125.44 -        l = null;
  125.45 -        assertGC("#86625: Utilities.class can also be collected now", r);
  125.46 -    }
  125.47 -
  125.48 -    
  125.49      private static class RunnableRef extends WeakReference<Object>
  125.50      implements Runnable {
  125.51          public boolean wait;
   126.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupArrayStorageTest.java	Thu Dec 10 19:23:25 2009 -0500
   126.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.3 @@ -1,120 +0,0 @@
   126.4 -/*
   126.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   126.6 - *
   126.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   126.8 - *
   126.9 - * The contents of this file are subject to the terms of either the GNU
  126.10 - * General Public License Version 2 only ("GPL") or the Common
  126.11 - * Development and Distribution License("CDDL") (collectively, the
  126.12 - * "License"). You may not use this file except in compliance with the
  126.13 - * License. You can obtain a copy of the License at
  126.14 - * http://www.netbeans.org/cddl-gplv2.html
  126.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  126.16 - * specific language governing permissions and limitations under the
  126.17 - * License.  When distributing the software, include this License Header
  126.18 - * Notice in each file and include the License file at
  126.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  126.20 - * particular file as subject to the "Classpath" exception as provided
  126.21 - * by Sun in the GPL Version 2 section of the License file that
  126.22 - * accompanied this code. If applicable, add the following below the
  126.23 - * License Header, with the fields enclosed by brackets [] replaced by
  126.24 - * your own identifying information:
  126.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  126.26 - *
  126.27 - * Contributor(s):
  126.28 - *
  126.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  126.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  126.31 - * Microsystems, Inc. All Rights Reserved.
  126.32 - *
  126.33 - * If you wish your version of this file to be governed by only the CDDL
  126.34 - * or only the GPL Version 2, indicate your decision by adding
  126.35 - * "[Contributor] elects to include this software in this distribution
  126.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  126.37 - * single choice of license, a recipient has the option to distribute
  126.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  126.39 - * to extend the choice of license to its licensees as provided above.
  126.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  126.41 - * Version 2 license, then the option applies only if the new code is
  126.42 - * made subject to such option by the copyright holder.
  126.43 - */
  126.44 -
  126.45 -package org.openide.util.lookup;
  126.46 -
  126.47 -import junit.framework.*;
  126.48 -import org.netbeans.junit.*;
  126.49 -import org.openide.util.Lookup;
  126.50 -
  126.51 -public class AbstractLookupArrayStorageTest extends AbstractLookupBaseHid {
  126.52 -    public AbstractLookupArrayStorageTest(java.lang.String testName) {
  126.53 -        super(testName, null);
  126.54 -    }
  126.55 -
  126.56 -    public static TestSuite suite () {
  126.57 -        NbTestSuite suite = new NbTestSuite ();
  126.58 -        suite.addTest (new PL (2));
  126.59 -        suite.addTest (new AL (1));
  126.60 -        suite.addTest (new AL (-1));
  126.61 -        suite.addTest (new PL (-1));
  126.62 -        suite.addTest (new AL (5));
  126.63 -        suite.addTest (new PL (3));
  126.64 -        suite.addTest (new AL (2000));
  126.65 -        suite.addTest (new PL (2000));
  126.66 -        return suite;
  126.67 -    }
  126.68 -
  126.69 -    static final class AL extends ArrayTestSuite {
  126.70 -        public AL (int trash) {
  126.71 -            super (trash);
  126.72 -        }
  126.73 -        
  126.74 -        public Lookup createLookup (Lookup lookup) {
  126.75 -            return lookup;
  126.76 -        }
  126.77 -        
  126.78 -        public void clearCaches () {
  126.79 -        }
  126.80 -        
  126.81 -    }
  126.82 -    
  126.83 -    static final class PL extends ArrayTestSuite {
  126.84 -        public PL (int trash) {
  126.85 -            super (trash);
  126.86 -        }
  126.87 -        
  126.88 -        public Lookup createLookup (Lookup lookup) {
  126.89 -            return  new ProxyLookup (new Lookup[] { lookup });
  126.90 -        }
  126.91 -        
  126.92 -        public void clearCaches () {
  126.93 -        }
  126.94 -        
  126.95 -    }
  126.96 -    
  126.97 -    private static abstract class ArrayTestSuite extends NbTestSuite 
  126.98 -    implements AbstractLookupBaseHid.Impl {
  126.99 -        private int trash;
 126.100 -        
 126.101 -        public ArrayTestSuite (int trash) {
 126.102 -            super (AbstractLookupArrayStorageTest.class);
 126.103 -            this.trash = trash;
 126.104 -            
 126.105 -            int cnt = this.countTestCases();
 126.106 -            for (int i = 0; i < cnt; i++) {
 126.107 -                Object o = this.testAt (i);
 126.108 -                AbstractLookupBaseHid t = (AbstractLookupBaseHid)o;
 126.109 -                t.impl = this;
 126.110 -            }
 126.111 -        }
 126.112 -        
 126.113 -        public Lookup createInstancesLookup (InstanceContent ic) {
 126.114 -            if (trash == -1) {
 126.115 -                return new AbstractLookup (ic, new ArrayStorage ());
 126.116 -            } else {
 126.117 -                return new AbstractLookup (ic, new ArrayStorage (new Integer (trash)));
 126.118 -            }
 126.119 -        }
 126.120 -        
 126.121 -        
 126.122 -    }
 126.123 -}
   127.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupAsynchExecutorTest.java	Thu Dec 10 19:23:25 2009 -0500
   127.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.3 @@ -1,108 +0,0 @@
   127.4 -/*
   127.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   127.6 - *
   127.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   127.8 - *
   127.9 - * The contents of this file are subject to the terms of either the GNU
  127.10 - * General Public License Version 2 only ("GPL") or the Common
  127.11 - * Development and Distribution License("CDDL") (collectively, the
  127.12 - * "License"). You may not use this file except in compliance with the
  127.13 - * License. You can obtain a copy of the License at
  127.14 - * http://www.netbeans.org/cddl-gplv2.html
  127.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  127.16 - * specific language governing permissions and limitations under the
  127.17 - * License.  When distributing the software, include this License Header
  127.18 - * Notice in each file and include the License file at
  127.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  127.20 - * particular file as subject to the "Classpath" exception as provided
  127.21 - * by Sun in the GPL Version 2 section of the License file that
  127.22 - * accompanied this code. If applicable, add the following below the
  127.23 - * License Header, with the fields enclosed by brackets [] replaced by
  127.24 - * your own identifying information:
  127.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  127.26 - *
  127.27 - * Contributor(s):
  127.28 - *
  127.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  127.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  127.31 - * Microsystems, Inc. All Rights Reserved.
  127.32 - *
  127.33 - * If you wish your version of this file to be governed by only the CDDL
  127.34 - * or only the GPL Version 2, indicate your decision by adding
  127.35 - * "[Contributor] elects to include this software in this distribution
  127.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  127.37 - * single choice of license, a recipient has the option to distribute
  127.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  127.39 - * to extend the choice of license to its licensees as provided above.
  127.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  127.41 - * Version 2 license, then the option applies only if the new code is
  127.42 - * made subject to such option by the copyright holder.
  127.43 - */
  127.44 -
  127.45 -package org.openide.util.lookup;
  127.46 -
  127.47 -import java.util.ArrayList;
  127.48 -import java.util.List;
  127.49 -import java.util.concurrent.Executor;
  127.50 -import org.netbeans.junit.NbTestCase;
  127.51 -import org.openide.util.Lookup;
  127.52 -import org.openide.util.LookupEvent;
  127.53 -import org.openide.util.LookupListener;
  127.54 -
  127.55 -public class AbstractLookupAsynchExecutorTest extends NbTestCase implements Executor {
  127.56 -    private List<Runnable> toRun = new ArrayList<Runnable>();
  127.57 -
  127.58 -
  127.59 -    public AbstractLookupAsynchExecutorTest(java.lang.String testName) {
  127.60 -        super(testName);
  127.61 -    }
  127.62 -
  127.63 -    public void testCanProxyLookupHaveWrongResults() {
  127.64 -        final InstanceContent ic = new InstanceContent(this);
  127.65 -        final AbstractLookup lookup = new AbstractLookup(ic);
  127.66 -
  127.67 -        class L implements LookupListener {
  127.68 -            ProxyLookup pl;
  127.69 -            Lookup.Result<String> original;
  127.70 -            Lookup.Result<String> wrapped;
  127.71 -            boolean ok;
  127.72 -
  127.73 -            public void test() {
  127.74 -                pl = new ProxyLookup(lookup);
  127.75 -                original = lookup.lookupResult(String.class);
  127.76 -
  127.77 -                original.addLookupListener(this);
  127.78 -
  127.79 -                wrapped = pl.lookupResult(String.class);
  127.80 -
  127.81 -                assertEquals("Original empty", 0, original.allInstances().size());
  127.82 -                assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
  127.83 -
  127.84 -                ic.add("Hello!");
  127.85 -            }
  127.86 -
  127.87 -            public void resultChanged(LookupEvent ev) {
  127.88 -                ok = true;
  127.89 -                assertContainsHello();
  127.90 -            }
  127.91 -
  127.92 -            public void assertContainsHello() {
  127.93 -                assertEquals("Original has hello", 1, original.allInstances().size());
  127.94 -                assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
  127.95 -            }
  127.96 -
  127.97 -        }
  127.98 -        L listener = new L();
  127.99 -        listener.test();
 127.100 -        listener.assertContainsHello();
 127.101 -        for (Runnable r : toRun) {
 127.102 -            r.run();
 127.103 -        }
 127.104 -        assertTrue("Listener called", listener.ok);
 127.105 -    }
 127.106 -
 127.107 -    public void execute(Runnable command) {
 127.108 -        toRun.add(command);
 127.109 -    }
 127.110 -
 127.111 -}
   128.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java	Thu Dec 10 19:23:25 2009 -0500
   128.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.3 @@ -1,2088 +0,0 @@
   128.4 -/*
   128.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   128.6 - *
   128.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   128.8 - *
   128.9 - * The contents of this file are subject to the terms of either the GNU
  128.10 - * General Public License Version 2 only ("GPL") or the Common
  128.11 - * Development and Distribution License("CDDL") (collectively, the
  128.12 - * "License"). You may not use this file except in compliance with the
  128.13 - * License. You can obtain a copy of the License at
  128.14 - * http://www.netbeans.org/cddl-gplv2.html
  128.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  128.16 - * specific language governing permissions and limitations under the
  128.17 - * License.  When distributing the software, include this License Header
  128.18 - * Notice in each file and include the License file at
  128.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  128.20 - * particular file as subject to the "Classpath" exception as provided
  128.21 - * by Sun in the GPL Version 2 section of the License file that
  128.22 - * accompanied this code. If applicable, add the following below the
  128.23 - * License Header, with the fields enclosed by brackets [] replaced by
  128.24 - * your own identifying information:
  128.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  128.26 - *
  128.27 - * Contributor(s):
  128.28 - *
  128.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  128.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  128.31 - * Microsystems, Inc. All Rights Reserved.
  128.32 - *
  128.33 - * If you wish your version of this file to be governed by only the CDDL
  128.34 - * or only the GPL Version 2, indicate your decision by adding
  128.35 - * "[Contributor] elects to include this software in this distribution
  128.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  128.37 - * single choice of license, a recipient has the option to distribute
  128.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  128.39 - * to extend the choice of license to its licensees as provided above.
  128.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  128.41 - * Version 2 license, then the option applies only if the new code is
  128.42 - * made subject to such option by the copyright holder.
  128.43 - */
  128.44 -
  128.45 -package org.openide.util.lookup;
  128.46 -
  128.47 -import java.io.ByteArrayInputStream;
  128.48 -import java.io.ByteArrayOutputStream;
  128.49 -import java.io.ObjectInputStream;
  128.50 -import java.io.ObjectOutputStream;
  128.51 -import java.io.Serializable;
  128.52 -import java.lang.ref.WeakReference;
  128.53 -import java.lang.ref.Reference;
  128.54 -import java.util.ArrayList;
  128.55 -import java.util.Arrays;
  128.56 -import java.util.Collection;
  128.57 -import java.util.Collections;
  128.58 -import java.util.Iterator;
  128.59 -import java.util.LinkedList;
  128.60 -import java.util.List;
  128.61 -import java.util.concurrent.Executors;
  128.62 -import java.util.concurrent.TimeUnit;
  128.63 -import javax.swing.ActionMap;
  128.64 -import javax.swing.InputMap;
  128.65 -import org.netbeans.junit.NbTestCase;
  128.66 -import org.openide.util.Lookup;
  128.67 -import org.openide.util.Lookup.Template;
  128.68 -import org.openide.util.LookupEvent;
  128.69 -import org.openide.util.LookupListener;
  128.70 -
  128.71 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  128.72 -public class AbstractLookupBaseHid extends NbTestCase {
  128.73 -    private static AbstractLookupBaseHid running;
  128.74 -
  128.75 -    /** instance content to work with */
  128.76 -    InstanceContent ic;
  128.77 -    /** the lookup to work on */
  128.78 -    protected Lookup instanceLookup;
  128.79 -    /** the lookup created to work with */
  128.80 -    private Lookup lookup;
  128.81 -    /** implementation of methods that can influence the behaviour */
  128.82 -    Impl impl;
  128.83 -    
  128.84 -    protected AbstractLookupBaseHid(String testName, Impl impl) {
  128.85 -        super(testName);
  128.86 -        if (impl == null && (this instanceof Impl)) {
  128.87 -            impl = (Impl)this;
  128.88 -        }
  128.89 -        this.impl = impl;
  128.90 -    }
  128.91 -    
  128.92 -    protected @Override void setUp() {
  128.93 -        this.ic = new InstanceContent ();
  128.94 -        
  128.95 -        beforeActualTest(getName());
  128.96 -        
  128.97 -        this.instanceLookup = createInstancesLookup (ic);
  128.98 -        this.lookup = createLookup (instanceLookup);
  128.99 -        running = this;
 128.100 -    }        
 128.101 -    
 128.102 -    protected @Override void tearDown() {
 128.103 -        running = null;
 128.104 -    }
 128.105 -    
 128.106 -    /** The methods to influence test behaviour */
 128.107 -    public static interface Impl {
 128.108 -        /** Creates the initial abstract lookup.
 128.109 -         */
 128.110 -        public Lookup createInstancesLookup (InstanceContent ic);
 128.111 -        /** Creates an lookup for given lookup. This class just returns 
 128.112 -         * the object passed in, but subclasses can be different.
 128.113 -         * @param lookup in lookup
 128.114 -         * @return a lookup to use
 128.115 -         */
 128.116 -        public Lookup createLookup (Lookup lookup);
 128.117 -        
 128.118 -        /** If the impl has any caches that would prevent the system
 128.119 -         * to not garbage collect correctly, then clear them now.
 128.120 -         */
 128.121 -        public void clearCaches ();
 128.122 -    }
 128.123 -    
 128.124 -    private Lookup createInstancesLookup (InstanceContent ic) {
 128.125 -        return impl.createInstancesLookup (ic);
 128.126 -    }
 128.127 -    
 128.128 -    private Lookup createLookup (Lookup lookup) {
 128.129 -        return impl.createLookup (lookup);
 128.130 -    }
 128.131 -    
 128.132 -    /** instances that we register */
 128.133 -    private static Object[] INSTANCES = new Object[] {
 128.134 -        new Integer (10), 
 128.135 -        new Object ()
 128.136 -    };
 128.137 -    
 128.138 -    /** Test if first is really first.
 128.139 -     */
 128.140 -    public void testFirst () {
 128.141 -        Integer i1 = 1;
 128.142 -        Integer i2 = 2;
 128.143 -        
 128.144 -        ic.add (i1);
 128.145 -        ic.add (i2);
 128.146 -        
 128.147 -        Integer found = lookup.lookup(Integer.class);
 128.148 -        if (found != i1) {
 128.149 -            fail ("First object is not first: " + found + " != " + i1);
 128.150 -        }
 128.151 -        
 128.152 -        List<Integer> list = new ArrayList<Integer>();
 128.153 -        list.add (i2);
 128.154 -        list.add (i1);
 128.155 -        ic.set (list, null);
 128.156 -        
 128.157 -        found = lookup.lookup (Integer.class);
 128.158 -        if (found != i2) {
 128.159 -            fail ("Second object is not first after reorder: " + found + " != " + i2);
 128.160 -        }
 128.161 -        
 128.162 -    }
 128.163 -
 128.164 -    public void testToString() {
 128.165 -        String txt = lookup.toString();
 128.166 -        assertNotNull("Something is there", txt);
 128.167 -        assertTrue("Something2: " + txt, txt.length() > 0);
 128.168 -    }
 128.169 -
 128.170 -
 128.171 -    /** Tests ordering of items in the lookup.
 128.172 -    */
 128.173 -    public void testOrder () {
 128.174 -        addInstances (INSTANCES);
 128.175 -
 128.176 -        if (INSTANCES[0] != lookup.lookup (INSTANCES[0].getClass ())) {
 128.177 -            fail ("First object in intances not found");
 128.178 -        }
 128.179 -
 128.180 -        Iterator<?> all = lookup.lookupAll(Object.class).iterator();
 128.181 -        checkIterator ("Difference between instances added and found", all, Arrays.asList (INSTANCES));
 128.182 -    }
 128.183 -    
 128.184 -    /** Checks the reorder of items in lookup reflects the result.
 128.185 -     * Testing both classes and interfaces, because they are often treated
 128.186 -     * especially.
 128.187 -     */
 128.188 -    public void testReorder () {
 128.189 -        String s1 = "s2";
 128.190 -        String s2 = "s1";
 128.191 -        Runnable r1 = new Runnable () {
 128.192 -            public void run () {}
 128.193 -        };
 128.194 -        Runnable r2 = new Runnable () {
 128.195 -            public void run () {}
 128.196 -        };
 128.197 -        List<Object> l = new ArrayList<Object>();
 128.198 -
 128.199 -        l.add (s1);
 128.200 -        l.add (s2);
 128.201 -        l.add (r1);
 128.202 -        l.add (r2);
 128.203 -        ic.set (l, null);
 128.204 -     
 128.205 -        assertEquals ("s1 is found", s1, lookup.lookup (String.class));
 128.206 -        assertEquals ("r1 is found", r1, lookup.lookup (Runnable.class));
 128.207 -        
 128.208 -        Collections.reverse (l);
 128.209 -        
 128.210 -        ic.set (l, null);
 128.211 -        
 128.212 -        assertEquals ("s2 is found", s2, lookup.lookup (String.class));
 128.213 -        assertEquals ("r2 is found", r2, lookup.lookup (Runnable.class));
 128.214 -    }
 128.215 -    
 128.216 -    /** Tries to set empty collection to the lookup.
 128.217 -     */
 128.218 -    public void testSetEmpty () {
 128.219 -        ic.add ("A serializable string");
 128.220 -        lookup.lookup (Serializable.class);
 128.221 -        
 128.222 -        ic.set (Collections.emptyList(), null);
 128.223 -    }
 128.224 -    
 128.225 -    /** Tests a more complex reorder on nodes.
 128.226 -     */
 128.227 -    public void testComplexReorder () {
 128.228 -        Integer i1 = 1;
 128.229 -        Long i2 = 2L;
 128.230 -        
 128.231 -        List<Object> l = new ArrayList<Object>();
 128.232 -        l.add (i1);
 128.233 -        l.add (i2);
 128.234 -        ic.set (l, null);
 128.235 -        
 128.236 -        assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
 128.237 -        assertEquals ("Find long", i2, lookup.lookup (Long.class));
 128.238 -        assertEquals ("Find number", i1, lookup.lookup (Number.class));
 128.239 -        
 128.240 -        Collections.reverse (l);
 128.241 -        
 128.242 -        ic.set (l, null);
 128.243 -        
 128.244 -        assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
 128.245 -        assertEquals ("Find long", i2, lookup.lookup (Long.class));
 128.246 -        assertEquals ("Find number", i2, lookup.lookup (Number.class));
 128.247 -    }
 128.248 -    
 128.249 -    /** Checks whether setPairs keeps the order.
 128.250 -     */
 128.251 -    public void testSetPairs () {
 128.252 -        // test setPairs method
 128.253 -        List<Object> li = new ArrayList<Object>();
 128.254 -        li.addAll (Arrays.asList (INSTANCES));
 128.255 -        ic.set (li, null);
 128.256 -        
 128.257 -        Lookup.Result<Object> res = lookup.lookupResult(Object.class);
 128.258 -        Iterator<?> all = res.allInstances().iterator();
 128.259 -        checkIterator ("Original order not kept", all, li);
 128.260 -        
 128.261 -        // reverse the order
 128.262 -        Collections.reverse (li);
 128.263 -        
 128.264 -        // change the pairs
 128.265 -        LL listener = new LL (res);
 128.266 -        res.addLookupListener (listener);
 128.267 -        ic.set (li, null);
 128.268 -        if (listener.getCount () != 1) {
 128.269 -            fail ("Result has not changed even we set reversed order");
 128.270 -        }
 128.271 -        
 128.272 -        all = res.allInstances ().iterator ();
 128.273 -        checkIterator ("Reversed order not kept", all, li);
 128.274 -    }
 128.275 -
 128.276 -    /** Checks whether setPairs fires correct events.
 128.277 -     */
 128.278 -    public void testSetPairsFire () {
 128.279 -        // test setPairs method
 128.280 -        List<Object> li = new ArrayList<Object>();
 128.281 -        li.addAll (Arrays.asList (INSTANCES));
 128.282 -        ic.set (li, null);
 128.283 -        
 128.284 -        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
 128.285 -        Iterator<?> all = res.allInstances().iterator();
 128.286 -        checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
 128.287 -        
 128.288 -        // change the pairs
 128.289 -        LL listener = new LL (res);
 128.290 -        res.addLookupListener (listener);
 128.291 -
 128.292 -        List<Object> l2 = new ArrayList<Object>(li);
 128.293 -        l2.remove (INSTANCES[0]);
 128.294 -        ic.set (l2, null);
 128.295 -
 128.296 -        all = lookup.lookupAll(Object.class).iterator();
 128.297 -        checkIterator ("The removed integer is not noticed", all, l2);
 128.298 -
 128.299 -        if (listener.getCount () != 1) {
 128.300 -            fail ("Nothing has not been fired");
 128.301 -        }
 128.302 -    }
 128.303 -
 128.304 -    /** Checks whether set pairs does not fire when they should not.
 128.305 -    */
 128.306 -    public void testSetPairsDoesNotFire () {
 128.307 -        Object tmp = new Object ();
 128.308 -
 128.309 -        List<Object> li = new ArrayList<Object>();
 128.310 -        li.add (tmp);
 128.311 -        li.addAll (Arrays.asList (INSTANCES));
 128.312 -        ic.set (li, null);
 128.313 -        
 128.314 -        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
 128.315 -        Iterator<?> all = res.allInstances ().iterator ();
 128.316 -        checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
 128.317 -        
 128.318 -        // change the pairs
 128.319 -        LL listener = new LL (res);
 128.320 -        res.addLookupListener (listener);
 128.321 -
 128.322 -        List<Object> l2 = new ArrayList<Object>(li);
 128.323 -        l2.remove (tmp);
 128.324 -        ic.set (l2, null);
 128.325 -
 128.326 -        all = lookup.lookupAll(Object.class).iterator();
 128.327 -        checkIterator ("The removed integer is not noticed", all, l2);
 128.328 -
 128.329 -        if (listener.getCount () != 0) {
 128.330 -            fail ("Something has been fired");
 128.331 -        }
 128.332 -    }
 128.333 -    
 128.334 -    /** Test whether after registration it is possible to find registered objects
 128.335 -    * 
 128.336 -     */
 128.337 -    public void testLookupAndAdd () throws Exception {
 128.338 -        addInstances (INSTANCES);
 128.339 -
 128.340 -        for (int i = 0; i < INSTANCES.length; i++) {
 128.341 -            Object obj = INSTANCES[i];
 128.342 -            findAll (lookup, obj.getClass (), true);
 128.343 -        }
 128.344 -    }
 128.345 -
 128.346 -    /** Tries to find all classes and superclasses in the lookup.
 128.347 -    */
 128.348 -    private void findAll(Lookup lookup, Class<?> clazz, boolean shouldBeThere) {
 128.349 -        if (clazz == null) return;
 128.350 -
 128.351 -        Object found = lookup.lookup (clazz);
 128.352 -        if (found == null) {
 128.353 -            if (shouldBeThere) {
 128.354 -                // should find at either instance or something else, but must
 128.355 -                // find at least something
 128.356 -                fail ("Lookup (" + clazz.getName () + ") found nothing");
 128.357 -            }
 128.358 -        } else {
 128.359 -            if (!shouldBeThere) {
 128.360 -                // should find at either instance or something else, but must
 128.361 -                // find at least something
 128.362 -                fail ("Lookup (" + clazz.getName () + ") found " + found);
 128.363 -            }
 128.364 -        }
 128.365 -
 128.366 -        Lookup.Result<?> res = lookup.lookupResult(clazz);
 128.367 -        Collection<?> collection = res.allInstances();
 128.368 -
 128.369 -        for (int i = 0; i < INSTANCES.length; i++) {
 128.370 -            boolean isSubclass = clazz.isInstance (INSTANCES[i]);
 128.371 -            boolean isThere = collection.contains (INSTANCES[i]);
 128.372 -
 128.373 -            if (isSubclass != isThere) {
 128.374 -                // a problem found
 128.375 -                // should find at either instance or something else, but must
 128.376 -                // find at least something
 128.377 -                fail ("Lookup.Result (" + clazz.getName () + ") for " + INSTANCES[i] + " is subclass: " + isSubclass + " isThere: " + isThere);
 128.378 -            }
 128.379 -        }
 128.380 -
 128.381 -        // go on for superclasses
 128.382 -
 128.383 -        findAll (lookup, clazz.getSuperclass (), shouldBeThere);
 128.384 -
 128.385 -        Class[] ies = clazz.getInterfaces ();
 128.386 -        for (int i = 0; i < ies.length; i++) {
 128.387 -            findAll (lookup, ies[i], shouldBeThere);
 128.388 -        }
 128.389 -    }
 128.390 -    
 128.391 -    /** Test if it is possible to remove a registered object. */
 128.392 -    public void testRemoveRegisteredObject() {
 128.393 -        Integer inst = new Integer(10);
 128.394 -        
 128.395 -        ic.add(inst);
 128.396 -        if (lookup.lookup(inst.getClass()) == null) {
 128.397 -            // should find an instance
 128.398 -            fail("Lookup (" + inst.getClass().getName () + ") found nothing");
 128.399 -        }
 128.400 -        
 128.401 -        ic.remove(inst);
 128.402 -        if (lookup.lookup(inst.getClass()) != null) {
 128.403 -            // should NOT find an instance
 128.404 -            fail("Lookup (" + inst.getClass().getName () +
 128.405 -                ") found an instance after remove operation");
 128.406 -        }
 128.407 -    }
 128.408 -    
 128.409 -    public void testCanReturnReallyStrangeResults () throws Exception {
 128.410 -        class QueryingPair extends AbstractLookup.Pair<Object> {
 128.411 -            private Integer i = 434;
 128.412 -            
 128.413 -            //
 128.414 -            // do the test
 128.415 -            //
 128.416 -            
 128.417 -            public void doTest () throws Exception {
 128.418 -                ic.add (i);
 128.419 -                ic.addPair (this);
 128.420 -                
 128.421 -                Object found = lookup.lookup (QueryingPair.class);
 128.422 -                assertEquals ("This object is found", this, found);
 128.423 -            }
 128.424 -            
 128.425 -            
 128.426 -            //
 128.427 -            // Implementation of pair
 128.428 -            // 
 128.429 -        
 128.430 -            public String getId() {
 128.431 -                return getType ().toString();
 128.432 -            }
 128.433 -
 128.434 -            public String getDisplayName() {
 128.435 -                return getId ();
 128.436 -            }
 128.437 -
 128.438 -            public Class<?> getType() {
 128.439 -                return getClass ();
 128.440 -            }
 128.441 -
 128.442 -            protected boolean creatorOf(Object obj) {
 128.443 -                return obj == this;
 128.444 -            }
 128.445 -
 128.446 -            protected boolean instanceOf(Class<?> c) {
 128.447 -                assertEquals ("Integer found or exception is thrown", i, lookup.lookup (Integer.class));
 128.448 -                return c.isAssignableFrom(getType ());
 128.449 -            }
 128.450 -
 128.451 -            public Object getInstance() {
 128.452 -                return this;
 128.453 -            }
 128.454 -            
 128.455 -            
 128.456 -        }
 128.457 -        
 128.458 -        
 128.459 -        QueryingPair qp = new QueryingPair ();
 128.460 -        qp.doTest ();
 128.461 -    }
 128.462 -    
 128.463 -    /** Test of firing events. */
 128.464 -    public void testLookupListener() {
 128.465 -        Object inst = 10;
 128.466 -        Lookup.Result<?> res = lookup.lookupResult(inst.getClass());
 128.467 -        res.allInstances ();
 128.468 -        
 128.469 -        LL listener = new LL(res);
 128.470 -        res.addLookupListener(listener);
 128.471 -        
 128.472 -        ic.add(inst);
 128.473 -        if (listener.getCount() == 0) {
 128.474 -            fail("None event fired during NbLookup.addPair()");
 128.475 -        }
 128.476 -        
 128.477 -        ic.remove(inst);
 128.478 -        if (listener.getCount() == 0) {
 128.479 -            fail("None event fired during NbLookup.removePair()");
 128.480 -        }
 128.481 -        
 128.482 -        ic.add(inst);
 128.483 -        if (listener.getCount() == 0) {
 128.484 -            fail("None event fired during second NbLookup.addPair()");
 128.485 -        }
 128.486 -        
 128.487 -        ic.remove(inst);
 128.488 -        if (listener.getCount() == 0) {
 128.489 -            fail("None event fired during second NbLookup.removePair()");
 128.490 -        }
 128.491 -    }
 128.492 -    
 128.493 -    /** Testing identity of the lookup.
 128.494 -     */
 128.495 -    public void testId () {
 128.496 -        Lookup.Template<?> templ;
 128.497 -        int cnt;
 128.498 -        
 128.499 -        addInstances (INSTANCES);
 128.500 -        
 128.501 -        Lookup.Result<?> res = lookup.lookupResult(Object.class);
 128.502 -        for (AbstractLookup.Item<?> item : res.allItems()) {
 128.503 -            
 128.504 -            templ = new Lookup.Template<Object>(null, item.getId(), null);
 128.505 -            cnt = lookup.lookup (templ).allInstances ().size ();
 128.506 -            if (cnt != 1) {
 128.507 -                fail ("Identity lookup failed. Instances = " + cnt);
 128.508 -            }
 128.509 -
 128.510 -            templ = makeTemplate(item.getType(), item.getId());
 128.511 -            cnt = lookup.lookup (templ).allInstances ().size ();
 128.512 -            if (cnt != 1) {
 128.513 -                fail ("Identity lookup with type failed. Instances = " + cnt);
 128.514 -            }
 128.515 -            
 128.516 -            templ = makeTemplate(this.getClass(), item.getId());
 128.517 -            cnt = lookup.lookup (templ).allInstances ().size ();
 128.518 -            if (cnt != 0) {
 128.519 -                fail ("Identity lookup with wrong type failed. Instances = " + cnt);
 128.520 -            }
 128.521 -            
 128.522 -            templ = new Lookup.Template<Object>(null, null, item.getInstance());
 128.523 -            cnt = lookup.lookup (templ).allInstances ().size ();
 128.524 -            if (cnt != 1) {
 128.525 -                fail ("Instance lookup failed. Instances = " + cnt);
 128.526 -            }
 128.527 -
 128.528 -            templ = new Lookup.Template<Object>(null, item.getId(), item.getInstance());
 128.529 -            cnt = lookup.lookup (templ).allInstances ().size ();
 128.530 -            if (cnt != 1) {
 128.531 -                fail ("Instance & identity lookup failed. Instances = " + cnt);
 128.532 -            }
 128.533 -            
 128.534 -        }
 128.535 -    }
 128.536 -    private static <T> Lookup.Template<T> makeTemplate(Class<T> clazz, String id) { // captures type parameter
 128.537 -        return new Lookup.Template<T>(clazz, id, null);
 128.538 -    }
 128.539 -    
 128.540 -    /** Tests adding and removing.
 128.541 -     */
 128.542 -    public void testAddAndRemove () throws Exception {
 128.543 -        Object map = new javax.swing.ActionMap ();
 128.544 -        LL ll = new LL ();
 128.545 -        
 128.546 -        Lookup.Result<?> res = lookup.lookupResult(map.getClass());
 128.547 -        res.allItems();
 128.548 -        res.addLookupListener (ll);
 128.549 -        ll.source = res;
 128.550 -        
 128.551 -        ic.add (map);
 128.552 -        
 128.553 -        assertEquals ("First change when adding", ll.getCount (), 1);
 128.554 -        
 128.555 -        ic.remove (map);
 128.556 -        
 128.557 -        assertEquals ("Second when removing", ll.getCount (), 1);
 128.558 -        
 128.559 -        ic.add (map);
 128.560 -        
 128.561 -        assertEquals ("Third when readding", ll.getCount (), 1);
 128.562 -        
 128.563 -        ic.remove (map);
 128.564 -        
 128.565 -        assertEquals ("Forth when reremoving", ll.getCount (), 1);
 128.566 -        
 128.567 -    }
 128.568 -    
 128.569 -    /** Will a class garbage collect even it is registered in lookup.
 128.570 -     */
 128.571 -    public void testGarbageCollect () throws Exception {
 128.572 -        ClassLoader l = new CL ();
 128.573 -        Class<?> c = l.loadClass(Garbage.class.getName());
 128.574 -        Reference<?> ref = new WeakReference<Object>(c);
 128.575 -
 128.576 -        lookup.lookup (c);
 128.577 -        
 128.578 -        // now test garbage collection
 128.579 -        c = null;
 128.580 -        l = null;
 128.581 -        impl.clearCaches ();
 128.582 -        assertGC ("The classloader has not been garbage collected!", ref);
 128.583 -    }
 128.584 -                
 128.585 -    /** Items are the same as results.
 128.586 -     */
 128.587 -    public void testItemsAndIntances () {
 128.588 -        addInstances (INSTANCES);
 128.589 -        
 128.590 -        Lookup.Result<Object> r = lookup.lookupResult(Object.class);
 128.591 -        Collection<? extends Lookup.Item<?>> items = r.allItems();
 128.592 -        Collection<?> insts = r.allInstances();
 128.593 -        
 128.594 -        if (items.size () != insts.size ()) {
 128.595 -            fail ("Different size of sets");
 128.596 -        }
 128.597 -
 128.598 -        for (Lookup.Item<?> item : items) {
 128.599 -            if (!insts.contains (item.getInstance ())) {
 128.600 -                fail ("Intance " + item.getInstance () + " is missing in " + insts);
 128.601 -            }
 128.602 -        }
 128.603 -    }
 128.604 -    
 128.605 -    /** Checks search for interface.
 128.606 -     */
 128.607 -    public void testSearchForInterface () {
 128.608 -        Lookup.Template<Serializable> t = new Lookup.Template<Serializable>(Serializable.class, null, null);
 128.609 -        
 128.610 -        assertNull("Nothing to find", lookup.lookupItem (t));
 128.611 -        
 128.612 -        Serializable s = new Serializable () {};
 128.613 -        ic.add (s);
 128.614 -        
 128.615 -        Lookup.Item item = lookup.lookupItem (t);
 128.616 -        assertNotNull ("Something found", item);
 128.617 -    }
 128.618 -
 128.619 -    /** Test to add broken item if it incorrectly answers instanceOf questions.
 128.620 -     */
 128.621 -    public void testIncorectInstanceOf40364 () {
 128.622 -        final Long sharedLong = new Long (0);
 128.623 -        
 128.624 -        class P extends AbstractLookup.Pair<Object> {
 128.625 -            public boolean isLong;
 128.626 -            
 128.627 -            P (boolean b) {
 128.628 -                isLong = b;
 128.629 -            }
 128.630 -            
 128.631 -            protected boolean creatorOf (Object obj) {
 128.632 -                return obj == sharedLong;
 128.633 -            }
 128.634 -            
 128.635 -            public String getDisplayName () {
 128.636 -                return "";
 128.637 -            }
 128.638 -            
 128.639 -            public String getId () {
 128.640 -                return "";
 128.641 -            }
 128.642 -            
 128.643 -            public Object getInstance () {
 128.644 -                return sharedLong;
 128.645 -            }
 128.646 -            
 128.647 -            public Class<?> getType() {
 128.648 -                return isLong ? Long.class : Number.class;
 128.649 -            }
 128.650 -            
 128.651 -            protected boolean instanceOf(Class<?> c) {
 128.652 -                return c.isAssignableFrom (getType ());
 128.653 -            }
 128.654 -    
 128.655 -            public @Override int hashCode() {
 128.656 -                return getClass ().hashCode ();
 128.657 -            }    
 128.658 -
 128.659 -            public @Override boolean equals(Object obj) {
 128.660 -                return obj != null && getClass ().equals (obj.getClass ());
 128.661 -            }
 128.662 -        }
 128.663 -        
 128.664 -        // to create the right structure in the lookup
 128.665 -        lookup.lookup (Object.class);
 128.666 -        lookup.lookup (Long.class);
 128.667 -        lookup.lookup (Number.class);
 128.668 -        
 128.669 -        P lng1 = new P (true);
 128.670 -        ic.addPair (lng1);
 128.671 -
 128.672 -        P lng2 = new P (false);
 128.673 -        ic.setPairs (Collections.singleton (lng2));
 128.674 -        
 128.675 -        Collection<? extends Lookup.Item<?>> res = lookup.lookupResult(Object.class).allItems();
 128.676 -        assertEquals ("Just one pair", 1, res.size ());
 128.677 -    }
 128.678 -
 128.679 -    public void testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly () throws Exception {
 128.680 -        class X implements TestInterfaceInheritanceA, TestInterfaceInheritanceB {
 128.681 -        }
 128.682 -        final X shared = new X ();
 128.683 -        
 128.684 -        class P extends AbstractLookup.Pair<Object> {
 128.685 -            public int howLong;
 128.686 -            
 128.687 -            P (int b) {
 128.688 -                howLong = b;
 128.689 -            }
 128.690 -            
 128.691 -            protected boolean creatorOf (Object obj) {
 128.692 -                return obj == shared;
 128.693 -            }
 128.694 -            
 128.695 -            public String getDisplayName () {
 128.696 -                return "";
 128.697 -            }
 128.698 -            
 128.699 -            public String getId () {
 128.700 -                return "";
 128.701 -            }
 128.702 -            
 128.703 -            public Object getInstance () {
 128.704 -                return shared;
 128.705 -            }
 128.706 -            
 128.707 -            public Class<?> getType() {
 128.708 -                return howLong == 0 ? TestInterfaceInheritanceB.class : TestInterfaceInheritanceA.class;
 128.709 -            }
 128.710 -            
 128.711 -            protected boolean instanceOf(Class<?> c) {
 128.712 -                return c.isAssignableFrom (getType ());
 128.713 -            }
 128.714 -    
 128.715 -            public @Override int hashCode() {
 128.716 -                return getClass ().hashCode ();
 128.717 -            }    
 128.718 -
 128.719 -            public @Override boolean equals(Object obj) {
 128.720 -                if (obj instanceof P) {
 128.721 -                    P p = (P)obj;
 128.722 -                    if (this.howLong > 0) {
 128.723 -                        this.howLong--;
 128.724 -                        return false;
 128.725 -                    }
 128.726 -                    if (p.howLong > 0) {
 128.727 -                        p.howLong--;
 128.728 -                        return false;
 128.729 -                    }
 128.730 -                    return getClass ().equals (p.getClass ());
 128.731 -                }
 128.732 -                return false;
 128.733 -            }
 128.734 -        }
 128.735 -        
 128.736 -        // to create the right structure in the lookup
 128.737 -        Lookup.Result<?> a = lookup.lookupResult(TestInterfaceInheritanceA.class);
 128.738 -        Lookup.Result<?> b = lookup.lookupResult(TestInterfaceInheritanceB.class);
 128.739 -        
 128.740 -        P lng1 = new P (0);
 128.741 -        ic.addPair (lng1);
 128.742 -        
 128.743 -        assertEquals ("One in a", 1, a.allItems ().size ());
 128.744 -        assertEquals ("One in b", 1, b.allItems ().size ());
 128.745 -
 128.746 -        P lng2 = new P (1);
 128.747 -        
 128.748 -
 128.749 -        /* Following call used to generate this exception:
 128.750 -    java.lang.IllegalStateException: Duplicate pair in treePair1:  pair2:  index1: 0 index2: 0 item1: org.openide.util.lookup.AbstractLookupBaseHid$1X@1a457b6 item2: org.openide.util.lookup.AbstractLookupBaseHid$1X@1a457b6 id1: 7a78d3 id2: 929206
 128.751 -	at org.openide.util.lookup.ALPairComparator.compare(ALPairComparator.java:52)
 128.752 -	at java.util.Arrays.mergeSort(Arrays.java:1284)
 128.753 -	at java.util.Arrays.sort(Arrays.java:1223)
 128.754 -	at java.util.Collections.sort(Collections.java:159)
 128.755 -	at org.openide.util.lookup.InheritanceTree.retainAllInterface(InheritanceTree.java:753)
 128.756 -	at org.openide.util.lookup.InheritanceTree.retainAll(InheritanceTree.java:183)
 128.757 -	at org.openide.util.lookup.DelegatingStorage.retainAll(DelegatingStorage.java:83)
 128.758 -	at org.openide.util.lookup.AbstractLookup.setPairsAndCollectListeners(AbstractLookup.java:238)
 128.759 -	at org.openide.util.lookup.AbstractLookup.setPairs(AbstractLookup.java:203)
 128.760 -	at org.openide.util.lookup.AbstractLookup$Content.setPairs(AbstractLookup.java:885)
 128.761 -	at org.openide.util.lookup.AbstractLookupBaseHid.testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly(AbstractLookupBaseHid.java:696)
 128.762 -	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 128.763 -	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 128.764 -	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 128.765 -	at org.netbeans.junit.NbTestCase.run(NbTestCase.java:119)
 128.766 -    */  
 128.767 -        ic.setPairs (Collections.singleton (lng2));
 128.768 -
 128.769 -        
 128.770 -    }
 128.771 -    
 128.772 -    public void testInstancesArePreservedFoundWhenFixing48590 () throws Exception {
 128.773 -        class X implements Runnable, Serializable {
 128.774 -            public void run () {
 128.775 -                
 128.776 -            }
 128.777 -            
 128.778 -            public void assertOnlyMe (String msg, Lookup.Result<?> res) {
 128.779 -                Collection<?> col = res.allInstances();
 128.780 -                assertEquals (msg + " just one", 1, col.size ());
 128.781 -                assertSame (msg + " and it is me", this, col.iterator ().next ());
 128.782 -            }
 128.783 -        }
 128.784 -        
 128.785 -        Lookup.Result<?> runnable = lookup.lookupResult(Runnable.class);
 128.786 -        Lookup.Result<?> serial = lookup.lookupResult(Serializable.class);
 128.787 -        
 128.788 -        
 128.789 -        X x = new X ();
 128.790 -        ic.add (x);
 128.791 -        
 128.792 -        
 128.793 -        x.assertOnlyMe ("x implements it (1)", runnable);
 128.794 -        x.assertOnlyMe ("x implements it (2)", serial);
 128.795 -        
 128.796 -        ic.set (Collections.singleton (x), null);
 128.797 -        
 128.798 -        x.assertOnlyMe ("x implements it (3)", runnable);
 128.799 -        x.assertOnlyMe ("x implements it (4)", serial);
 128.800 -    }
 128.801 -    
 128.802 -    /** Testing lookup of inherited classes. */
 128.803 -    public void testInheritance() {
 128.804 -        class A {}
 128.805 -        class B extends A implements java.rmi.Remote {}
 128.806 -        class BB extends B {}
 128.807 -        class C extends A implements java.rmi.Remote {}
 128.808 -        class D extends A {}
 128.809 -        
 128.810 -        A[] types = {new B(), new BB(), new C(), new D()};
 128.811 -        
 128.812 -        for (int i = 0; i < types.length; i++) {
 128.813 -            ic.add(types[i]);
 128.814 -            if (lookup.lookup(types[i].getClass()) == null) {
 128.815 -                // should find an instance
 128.816 -                fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
 128.817 -            }
 128.818 -        }
 128.819 -        
 128.820 -        int size1, size2;
 128.821 -        
 128.822 -        //interface query
 128.823 -        size1 = lookup.lookupAll(java.rmi.Remote.class).size();
 128.824 -        size2 = countInstances(types, java.rmi.Remote.class);
 128.825 -        
 128.826 -        if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
 128.827 -        
 128.828 -        // superclass query
 128.829 -        size1 = lookup.lookupAll(A.class).size();
 128.830 -        size2 = countInstances(types, A.class);
 128.831 -        
 128.832 -        if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
 128.833 -    }
 128.834 -    
 128.835 -    /** Test interface inheritance.
 128.836 -     */
 128.837 -    public void testInterfaceInheritance() {
 128.838 -        TestInterfaceInheritanceA[] types = {
 128.839 -            new TestInterfaceInheritanceB() {},
 128.840 -            new TestInterfaceInheritanceBB() {},
 128.841 -            new TestInterfaceInheritanceC() {},
 128.842 -            new TestInterfaceInheritanceD() {}
 128.843 -        };
 128.844 -        
 128.845 -        for (int i = 0; i < types.length; i++) {
 128.846 -            ic.add(types[i]);
 128.847 -            if (lookup.lookup(types[i].getClass()) == null) {
 128.848 -                // should find an instance
 128.849 -                fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
 128.850 -            }
 128.851 -        }
 128.852 -        
 128.853 -        int size1, size2;
 128.854 -        
 128.855 -        //interface query
 128.856 -        LL l = new LL ();
 128.857 -        Lookup.Result<?> res = lookup.lookupResult(java.rmi.Remote.class);
 128.858 -        l.source = res;
 128.859 -        size1 = res.allInstances().size();
 128.860 -        size2 = countInstances(types, java.rmi.Remote.class);
 128.861 -        
 128.862 -        if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
 128.863 -        
 128.864 -        // superclass query
 128.865 -        size1 = lookup.lookupAll(TestInterfaceInheritanceA.class).size();
 128.866 -        size2 = countInstances(types, TestInterfaceInheritanceA.class);
 128.867 -        
 128.868 -        if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
 128.869 -        
 128.870 -        res.addLookupListener (l);
 128.871 -        ic.remove (types[0]);
 128.872 -        
 128.873 -        if (l.getCount () != 1) {
 128.874 -            fail ("No notification that a Remote is removed");
 128.875 -        }
 128.876 -    }
 128.877 -    
 128.878 -    /** Checks whether the AbstractLookup is guarded against modifications
 128.879 -     * while doing some kind of modification.
 128.880 -     */
 128.881 -    public void testModificationArePreventedWhenDoingModifications () throws Exception {
 128.882 -        BrokenPair broken = new BrokenPair (true, false);
 128.883 -        ic.addPair (broken);
 128.884 -        
 128.885 -        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
 128.886 -        Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
 128.887 -        assertEquals ("Broken is found", broken, item);
 128.888 -    }
 128.889 -    
 128.890 -    public void testModificationArePreventedWhenDoingModificationsResult () throws Exception {
 128.891 -        BrokenPair broken = new BrokenPair (false, true);
 128.892 -        ic.addPair (broken);
 128.893 -        
 128.894 -        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
 128.895 -        
 128.896 -        Collection<? extends BrokenPair> c = lookup.lookup (templ).allInstances();
 128.897 -        assertEquals ("One item", 1, c.size ());
 128.898 -        assertEquals ("Broken is found again", broken, c.iterator().next ());
 128.899 -    }
 128.900 -    
 128.901 -    public void testModificationArePreventedWhenDoingModificationsItemAndResult () throws Exception {
 128.902 -        BrokenPair broken = new BrokenPair (false, true);
 128.903 -        ic.addPair (broken);
 128.904 -        
 128.905 -        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
 128.906 -        Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
 128.907 -        assertEquals ("Broken is found", broken, item);
 128.908 -        
 128.909 -        Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
 128.910 -        assertEquals ("One item", 1, c.size ());
 128.911 -        assertEquals ("Broken is found again", broken, c.iterator().next ());
 128.912 -    }
 128.913 -
 128.914 -    public void testModificationArePreventedWhenDoingModificationsResultAndItem () throws Exception {
 128.915 -        BrokenPair broken = new BrokenPair (false, true);
 128.916 -        ic.addPair (broken);
 128.917 -        
 128.918 -        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
 128.919 -        Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
 128.920 -        assertEquals ("One item", 1, c.size ());
 128.921 -        assertEquals ("Broken is found again", broken, c.iterator().next ());
 128.922 -        
 128.923 -        Object item = lookup.lookupItem (templ);
 128.924 -        assertEquals ("Broken is found", broken, item);
 128.925 -    }
 128.926 -    
 128.927 -    public void testAddALotOfPairsIntoTheLookupOneByOne () throws Exception {
 128.928 -        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
 128.929 -        for (int i = 0; i < 1000; i++) {
 128.930 -            ic.add(i);
 128.931 -        }
 128.932 -        assertEquals (
 128.933 -            "there is the right count", 
 128.934 -            1000, 
 128.935 -            res.allItems().size ()
 128.936 -        );
 128.937 -    }
 128.938 -    
 128.939 -    public void testAddALotOfPairsIntoTheLookup () throws Exception {
 128.940 -        List<Integer> arr = new ArrayList<Integer>();
 128.941 -        for (int i = 0; i < 1000; i++) {
 128.942 -            arr.add(i);
 128.943 -        }
 128.944 -        ic.set (arr, null);
 128.945 -        
 128.946 -        assertEquals (
 128.947 -            "there is the right count", 
 128.948 -            1000, 
 128.949 -            lookup.lookupResult(Integer.class).allItems().size()
 128.950 -        );
 128.951 -    }
 128.952 -
 128.953 -    
 128.954 -    public void testDoubleAddIssue35274 () throws Exception {
 128.955 -        class P extends AbstractLookup.Pair<Object> {
 128.956 -            protected boolean creatorOf(Object obj) { return false; }
 128.957 -            public String getDisplayName() { return ""; }
 128.958 -            public String getId() { return ""; }
 128.959 -            public Object getInstance() { return null; }
 128.960 -            public Class<?> getType() { return Object.class; }
 128.961 -            protected boolean instanceOf(Class<?> c) { return c.isAssignableFrom(getType ()); }
 128.962 -            public @Override int hashCode() {return getClass().hashCode();}
 128.963 -            public @Override boolean equals(Object obj) {return getClass() == obj.getClass();}
 128.964 -        }
 128.965 -        
 128.966 -        P p = new P ();
 128.967 -        
 128.968 -        ic.addPair (p);
 128.969 -        ic.addPair (p);
 128.970 -        
 128.971 -        Lookup.Result<Object> result = lookup.lookupResult(Object.class);
 128.972 -        Collection res = result.allItems ();
 128.973 -        assertEquals ("One item there", 1, res.size ());
 128.974 -        assertTrue ("It is the p", p == res.iterator ().next ());
 128.975 -        
 128.976 -        P p2 = new P ();
 128.977 -        ic.addPair (p2);
 128.978 -        
 128.979 -        Reference<?> ref = new WeakReference<Object>(result);
 128.980 -        result = null;
 128.981 -        assertGC ("The result can disappear", ref);
 128.982 -        
 128.983 -        impl.clearCaches ();
 128.984 -        
 128.985 -        result = lookup.lookupResult(Object.class);
 128.986 -        res = result.allItems ();
 128.987 -        assertEquals ("One item is still there", 1, res.size ());
 128.988 -        assertTrue ("But the p2 replaced p", p2 == res.iterator ().next ());
 128.989 -        
 128.990 -    }
 128.991 -    
 128.992 -    /** Test for proper serialization.
 128.993 -     */
 128.994 -    public void testSerializationSupport () throws Exception {
 128.995 -        doSerializationSupport (1);
 128.996 -    }
 128.997 -    public void testDoubleSerializationSupport () throws Exception {
 128.998 -        doSerializationSupport (2);
 128.999 -    }
128.1000 -
128.1001 -    private void doSerializationSupport (int count) throws Exception {
128.1002 -        if (lookup instanceof Serializable) {
128.1003 -            ic.addPair (new SerialPair ("1"));
128.1004 -            ic.addPair (new SerialPair ("2"));
128.1005 -            ic.addPair (new SerialPair ("3"));
128.1006 -
128.1007 -            Lookup l = (Lookup)reserialize(lookup);
128.1008 -
128.1009 -            assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
128.1010 -
128.1011 -            assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
128.1012 -
128.1013 -            while (count-- > 0) {
128.1014 -                l = (Lookup)reserialize(l);
128.1015 -            }
128.1016 -
128.1017 -            assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
128.1018 -
128.1019 -            assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
128.1020 -        }
128.1021 -    }
128.1022 -
128.1023 -    /** When a lookup with two different versions of the same class 
128.1024 -     * get's serialized, the results may be very bad. 
128.1025 -     */
128.1026 -    public void testSerializationOfTwoClassesWithTheSameName () throws Exception {
128.1027 -        if (lookup instanceof Serializable) {
128.1028 -            doTwoSerializedClasses (false, false);
128.1029 -        }
128.1030 -    }
128.1031 -    public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSave () throws Exception {
128.1032 -        if (lookup instanceof Serializable) {
128.1033 -            doTwoSerializedClasses (true, false);
128.1034 -        }
128.1035 -    }
128.1036 -    public void testSerializationOfTwoClassesWithTheSameNameWithBroken () throws Exception {
128.1037 -        if (lookup instanceof Serializable) {
128.1038 -            doTwoSerializedClasses (false, true);
128.1039 -        }
128.1040 -    }
128.1041 -    public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSaveWithBroken () throws Exception {
128.1042 -        if (lookup instanceof Serializable) {
128.1043 -            doTwoSerializedClasses (true, true);
128.1044 -        }
128.1045 -    }
128.1046 -   
128.1047 -    private void doTwoSerializedClasses (boolean queryBeforeSerialization, boolean useBroken) throws Exception {
128.1048 -        ClassLoader loader = new CL ();
128.1049 -        Class c = loader.loadClass (Garbage.class.getName ());
128.1050 -
128.1051 -        // in case of InheritanceTree it creates a slot for class Garbage
128.1052 -        lookup.lookup(c);
128.1053 -
128.1054 -        // but creates new instance and adds it into the lookup
128.1055 -        // without querying for it
128.1056 -        loader = new CL ();
128.1057 -        c = loader.loadClass (Garbage.class.getName ());
128.1058 -
128.1059 -        Object theInstance = c.newInstance ();
128.1060 -
128.1061 -        ic.addPair (new SerialPair (theInstance));
128.1062 -
128.1063 -        Broken2Pair broken = null;
128.1064 -        if (useBroken) {
128.1065 -            broken = new Broken2Pair ();
128.1066 -            ic.addPair (broken);
128.1067 -            
128.1068 -            assertNull (
128.1069 -                "We need to create the slot for the List as " +
128.1070 -                "the Broken2Pair will ask for it after deserialization", 
128.1071 -                lookup.lookup (java.awt.List.class)
128.1072 -            );
128.1073 -        }
128.1074 -
128.1075 -        if (queryBeforeSerialization) {
128.1076 -            assertEquals ("Instance is found", theInstance, lookup.lookup (c));
128.1077 -        }
128.1078 -        
128.1079 -        // replace the old lookup with new one
128.1080 -        lookup = (Lookup)reserialize(lookup);
128.1081 -        
128.1082 -        Lookup.Result result = lookup.lookup (new Lookup.Template (Garbage.class));
128.1083 -        assertEquals ("One item is the result", 1, result.allInstances ().size ());
128.1084 -        Object r = result.allInstances ().iterator ().next ();
128.1085 -        assertNotNull("A value is found", r);
128.1086 -        assertEquals ("It is of the right class", Garbage.class, r.getClass());
128.1087 -    }
128.1088 -   
128.1089 -    /** Test of reorder and item change which used to fail on interfaces.
128.1090 -     */
128.1091 -    public void testReoderingIssue13779 () throws Exception {
128.1092 -        LinkedList arr = new LinkedList ();
128.1093 -        
128.1094 -        class R extends Exception implements Cloneable {
128.1095 -        }
128.1096 -        Object o1 = new R ();
128.1097 -        Object o2 = new R ();
128.1098 -        Object o3 = new R ();
128.1099 -        
128.1100 -        arr.add (o1);
128.1101 -        arr.add (o2);
128.1102 -        
128.1103 -        ic.set (arr, null);
128.1104 -        
128.1105 -        Lookup.Result objectResult = lookup.lookup (new Lookup.Template (Exception.class));
128.1106 -        Lookup.Result interfaceResult = lookup.lookup (new Lookup.Template (Cloneable.class));
128.1107 -        objectResult.allItems ();
128.1108 -        interfaceResult.allItems ();
128.1109 -        
128.1110 -        LL l1 = new LL (objectResult);
128.1111 -        LL l2 = new LL (interfaceResult);
128.1112 -        
128.1113 -        objectResult.addLookupListener(l1);
128.1114 -        interfaceResult.addLookupListener(l2);
128.1115 -        
128.1116 -        arr.addFirst (o3);
128.1117 -        
128.1118 -        ic.set (arr, null);
128.1119 -        
128.1120 -        assertEquals ("One change on objects", 1, l1.getCount ());
128.1121 -        assertEquals ("One change on interfaces", 1, l2.getCount ());
128.1122 -        
128.1123 -        arr.addFirst (new Cloneable () { });
128.1124 -        ic.set (arr, null);
128.1125 -        
128.1126 -        assertEquals ("No change on objects", 0, l1.getCount ());
128.1127 -        assertEquals ("But one change on interfaces", 1, l2.getCount ());
128.1128 -        
128.1129 -    }
128.1130 -    
128.1131 -    public void testDeadlockBetweenProxyResultAndLookupIssue47772 () throws Exception {
128.1132 -        final String myModule = "My Module";
128.1133 -        ic.add (myModule);
128.1134 -        
128.1135 -        class MyProxy extends ProxyLookup {
128.1136 -            public MyProxy () {
128.1137 -                super (new Lookup[] { lookup });
128.1138 -            }
128.1139 -        }
128.1140 -        final MyProxy my = new MyProxy ();
128.1141 -        
128.1142 -        final Lookup.Result allModules = my.lookup (new Lookup.Template (String.class));
128.1143 -        
128.1144 -        class PairThatNeedsInfoAboutModules extends AbstractLookup.Pair {
128.1145 -            public String getDisplayName () {
128.1146 -                return "Need a module";
128.1147 -            }
128.1148 -            public String getId () {
128.1149 -                return getDisplayName ();
128.1150 -            }
128.1151 -            public Class getType () {
128.1152 -                return Integer.class;
128.1153 -            }
128.1154 -            protected boolean instanceOf (Class c) {
128.1155 -                if (c == Integer.class) {
128.1156 -                    synchronized (this) {
128.1157 -                        notifyAll ();
128.1158 -                        try {
128.1159 -                            wait (1000);
128.1160 -                        } catch (InterruptedException ex) {
128.1161 -                            fail (ex.getMessage ());
128.1162 -                        }
128.1163 -                    }
128.1164 -                    java.util.Collection coll = allModules.allInstances ();
128.1165 -                    assertEquals ("Size is 1", 1, coll.size ());
128.1166 -                    assertEquals ("My module is there", myModule, coll.iterator ().next ());
128.1167 -                }
128.1168 -                return c.isAssignableFrom (Integer.class);
128.1169 -            }
128.1170 -            
128.1171 -            public Object getInstance () {
128.1172 -                return new Integer (10);
128.1173 -            }
128.1174 -            
128.1175 -            protected boolean creatorOf (Object obj) {
128.1176 -                return new Integer (10).equals (obj);
128.1177 -            }
128.1178 -        }
128.1179 -        
128.1180 -        PairThatNeedsInfoAboutModules pair = new PairThatNeedsInfoAboutModules ();
128.1181 -        ic.addPair (pair);
128.1182 -        
128.1183 -        synchronized (pair) {
128.1184 -            class BlockInInstanceOf implements Runnable {
128.1185 -                public void run () {
128.1186 -                    Integer i = my.lookup(Integer.class);
128.1187 -                    assertEquals (new Integer (10), i);
128.1188 -                }
128.1189 -            }
128.1190 -            BlockInInstanceOf blk = new BlockInInstanceOf ();
128.1191 -            Executors.newSingleThreadScheduledExecutor().schedule(blk, 0, TimeUnit.MICROSECONDS);
128.1192 -            pair.wait ();
128.1193 -        }
128.1194 -        
128.1195 -        java.util.Collection coll = allModules.allInstances ();
128.1196 -        assertEquals ("Size is 1", 1, coll.size ());
128.1197 -        assertEquals ("My module is there", myModule, coll.iterator ().next ());
128.1198 -    }
128.1199 -
128.1200 -    public void testAWayToGenerateProblem13779 () {
128.1201 -        ic.add (new Integer (1));
128.1202 -        ic.add (new Integer (2));
128.1203 -        ic.add (new Integer (1));
128.1204 -        ic.add (new Integer (2));
128.1205 -        
128.1206 -        Collection c = lookup.lookup (new Lookup.Template (Integer.class)).allInstances ();
128.1207 -        assertEquals ("There are two objects", 2, c.size ());
128.1208 -        
128.1209 -    }
128.1210 -    
128.1211 -    /** Replacing items with different objects.
128.1212 -     */
128.1213 -    public void testReplacingObjectsDoesNotGenerateException () throws Exception {
128.1214 -        LinkedList arr = new LinkedList ();
128.1215 -        
128.1216 -        class R extends Exception implements Cloneable {
128.1217 -        }
128.1218 -        arr.add (new R ());
128.1219 -        arr.add (new R ());
128.1220 -        
128.1221 -        ic.set (arr, null);
128.1222 -        
128.1223 -        arr.clear();
128.1224 -        
128.1225 -        arr.add (new R ());
128.1226 -        arr.add (new R ());
128.1227 -        
128.1228 -        ic.set (arr, null);
128.1229 -    }
128.1230 -
128.1231 -    public void testAfterDeserializationNoQueryIsPeformedOnAlreadyQueriedObjects() throws Exception {
128.1232 -        if (! (lookup instanceof Serializable)) {
128.1233 -            // well this test works only for serializable lookups
128.1234 -            return;
128.1235 -        }
128.1236 -        
128.1237 -        SerialPair my = new SerialPair ("no");
128.1238 -        ic.addPair (my);
128.1239 -        
128.1240 -        Lookup.Result res = lookup.lookup (new Lookup.Template (String.class));
128.1241 -        assertEquals ("One instance", 1, res.allInstances().size ());
128.1242 -        assertEquals ("my.instanceOf called once", 1, my.countInstanceOf);
128.1243 -        
128.1244 -        Lookup serial = (Lookup)reserialize(lookup);
128.1245 -        
128.1246 -        Lookup.Result r2 = serial.lookup(new Lookup.Template(String.class));
128.1247 -        
128.1248 -        assertEquals ("One item", 1, r2.allItems ().size ());
128.1249 -        Object one = r2.allItems().iterator().next ();
128.1250 -        assertEquals ("The right class", SerialPair.class, one.getClass());
128.1251 -        SerialPair p = (SerialPair)one;
128.1252 -        
128.1253 -        assertEquals ("p.instanceOf has not been queried", 0, p.countInstanceOf);
128.1254 -    }
128.1255 -    
128.1256 -    /** Checks the iterator */
128.1257 -    private <T> void checkIterator(String msg, Iterator<? extends T> it1, List<? extends T> list) {
128.1258 -        int cnt = 0;
128.1259 -        Iterator<? extends T> it2 = list.iterator();
128.1260 -        while (it1.hasNext () && it2.hasNext ()) {
128.1261 -            T n1 = it1.next();
128.1262 -            T n2 = it2.next();
128.1263 -            
128.1264 -            if (n1 != n2) {
128.1265 -                fail (msg + " iterator[" + cnt + "] = " + n1 + " but list[" + cnt + "] = " + n2);
128.1266 -            }
128.1267 -            
128.1268 -            cnt++;
128.1269 -        }
128.1270 -        
128.1271 -        if (it1.hasNext ()) {
128.1272 -            fail ("Iterator has more elements than list");
128.1273 -        }
128.1274 -        
128.1275 -        if (it2.hasNext ()) {
128.1276 -            fail ("List has more elements than iterator");
128.1277 -        }
128.1278 -    }
128.1279 -    
128.1280 -    
128.1281 -    public void testResultsAreUnmodifyableOrAtLeastTheyDoNotPropagateToCache() throws Exception {
128.1282 -        String s = "Ahoj";
128.1283 -        
128.1284 -        ic.add(s);
128.1285 -        
128.1286 -        Lookup.Result res = lookup.lookup(new Template(String.class));
128.1287 -        
128.1288 -        for (int i = 1; i < 5; i++) {
128.1289 -            Collection c1 = res.allInstances();
128.1290 -            Collection c2 = res.allClasses();
128.1291 -            Collection c3 = res.allItems();
128.1292 -
128.1293 -            assertTrue(i + ": c1 has it", c1.contains(s));
128.1294 -            assertTrue(i + ": c2 has it", c2.contains(s.getClass()));
128.1295 -            assertEquals(i + ": c3 has one", 1, c3.size());
128.1296 -            Lookup.Item item = (Lookup.Item) c3.iterator().next();
128.1297 -            assertEquals(i + ": c3 has it", s, item.getInstance());
128.1298 -
128.1299 -            try {
128.1300 -                c1.remove(s);
128.1301 -                assertEquals("No elements now", 0, c1.size());
128.1302 -            } catch (UnsupportedOperationException ex) {
128.1303 -                // ok, this need not be supported
128.1304 -            }
128.1305 -            try {
128.1306 -                c2.remove(s.getClass());
128.1307 -                assertEquals("No elements now", 0, c2.size());
128.1308 -            } catch (UnsupportedOperationException ex) {
128.1309 -                // ok, this need not be supported
128.1310 -            }
128.1311 -            try {
128.1312 -                c3.remove(item);
128.1313 -                assertEquals("No elements now", 0, c3.size());
128.1314 -            } catch (UnsupportedOperationException ex) {
128.1315 -                // ok, this need not be supported
128.1316 -            }
128.1317 -        }
128.1318 -    }
128.1319 -    
128.1320 -    public void testSomeProblemWithDVBFrameworkSeemsToBeInLookup() {
128.1321 -        for (int i = 0; i < 5; i++) {
128.1322 -            ic.add(lookup);
128.1323 -            assertEquals("Can be found", lookup, lookup.lookup(lookup.getClass()));
128.1324 -            ic.set(Collections.EMPTY_LIST, null);
128.1325 -        }        
128.1326 -    }
128.1327 -
128.1328 -    public void testListeningAndQueryingByTwoListenersInstances() {
128.1329 -        doListeningAndQueryingByTwoListeners(0);
128.1330 -    }
128.1331 -    public void testListeningAndQueryingByTwoListenersClasses() {
128.1332 -        doListeningAndQueryingByTwoListeners(1);        
128.1333 -    }
128.1334 -    public void testListeningAndQueryingByTwoListenersItems() {
128.1335 -        doListeningAndQueryingByTwoListeners(2);
128.1336 -    }
128.1337 -    
128.1338 -    
128.1339 -    private void doListeningAndQueryingByTwoListeners(final int type) {
128.1340 -        class L implements LookupListener {
128.1341 -            Lookup.Result integer = lookup.lookup(new Template(Integer.class));
128.1342 -            Lookup.Result number = lookup.lookup(new Template(Number.class));
128.1343 -            Lookup.Result serial = lookup.lookup(new Template(Serializable.class));
128.1344 -            
128.1345 -            {
128.1346 -                integer.addLookupListener(this);
128.1347 -                number.addLookupListener(this);
128.1348 -                serial.addLookupListener(this);
128.1349 -            }
128.1350 -            
128.1351 -            int round;
128.1352 -            
128.1353 -            public void resultChanged(LookupEvent ev) {
128.1354 -                Collection c1 = get(type, integer);
128.1355 -                Collection c2 = get(type, number);
128.1356 -                Collection c3 = get(type, serial);
128.1357 -                
128.1358 -                assertEquals("round " + round + " c1 vs. c2", c1, c2);
128.1359 -                assertEquals("round " + round + " c1 vs. c3", c1, c3);
128.1360 -                assertEquals("round " + round + " c2 vs. c3", c2, c3);
128.1361 -                
128.1362 -                round++;
128.1363 -            }            
128.1364 -
128.1365 -            private Collection get(int type, Lookup.Result res) {
128.1366 -                Collection c;
128.1367 -                switch(type) {
128.1368 -                    case 0: c = res.allInstances(); break;
128.1369 -                    case 1: c = res.allClasses(); break;
128.1370 -                    case 2: c = res.allItems(); break;
128.1371 -                    default: c = null; fail("Type: " + type); break;
128.1372 -                }
128.1373 -                
128.1374 -                assertNotNull(c);
128.1375 -                return new ArrayList(c);
128.1376 -            }
128.1377 -        }
128.1378 -        
128.1379 -        L listener = new L();
128.1380 -        listener.resultChanged(null);
128.1381 -        
128.1382 -        for(int i = 0; i < 100; i++) {
128.1383 -            ic.add(new Integer(i));
128.1384 -        }
128.1385 -        
128.1386 -        assertEquals("3x100+1 checks", 301, listener.round);
128.1387 -    }
128.1388 -    
128.1389 -    public void testChangeOfNodeDoesNotFireChangeInActionMap() {
128.1390 -        ActionMap am = new ActionMap();
128.1391 -        Lookup s = Lookups.singleton(am);
128.1392 -        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, false, 0);
128.1393 -    }
128.1394 -    public void testChangeOfNodeDoesNotFireChangeInActionMapSimple() {
128.1395 -        ActionMap am = new ActionMap();
128.1396 -        Lookup s = Lookups.singleton(am);
128.1397 -        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, true, 0);
128.1398 -    }
128.1399 -
128.1400 -    public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookupSimple() {
128.1401 -        doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(true);
128.1402 -    }
128.1403 -    
128.1404 -    public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup() {
128.1405 -        doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(false);
128.1406 -    }
128.1407 -    private void doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(boolean wrapBySimple) {
128.1408 -        final ActionMap am = new ActionMap();
128.1409 -        
128.1410 -        class Before extends AbstractLookup {
128.1411 -            public InstanceContent ic;
128.1412 -            public Before() {
128.1413 -                this(new InstanceContent());
128.1414 -            }
128.1415 -            
128.1416 -            private Before(InstanceContent ic) {
128.1417 -                super(ic);
128.1418 -                this.ic = ic;
128.1419 -            }
128.1420 -
128.1421 -            protected @Override void beforeLookup(Template template) {
128.1422 -                if (ic != null) {
128.1423 -                    ic.add(am);
128.1424 -                    ic = null;
128.1425 -                }
128.1426 -            }
128.1427 -        }
128.1428 -        
128.1429 -        Before s = new Before();
128.1430 -        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, wrapBySimple, 1);
128.1431 -        
128.1432 -        assertNull("beforeLookup called once", s.ic);
128.1433 -    }
128.1434 -    
128.1435 -    private void doChangeOfNodeDoesNotFireChangeInActionMap(final ActionMap am, Lookup actionMapLookup, final boolean wrapBySimple, int firstChange) {
128.1436 -        Lookup[] lookups = { lookup, actionMapLookup };
128.1437 -        
128.1438 -        class Provider implements Lookup.Provider {
128.1439 -            ProxyLookup delegate;
128.1440 -            Lookup query;
128.1441 -            
128.1442 -            public Provider(Lookup[] arr) {
128.1443 -                if (wrapBySimple) {
128.1444 -                    delegate = new ProxyLookup(arr);
128.1445 -                    query = Lookups.proxy(this);
128.1446 -                } else {
128.1447 -                    query = delegate = new ProxyLookup(arr);
128.1448 -                }
128.1449 -            }
128.1450 -            
128.1451 -            public Lookup getLookup() {
128.1452 -                return delegate;
128.1453 -            }
128.1454 -            
128.1455 -            public void setLookups(Lookup... arr) {
128.1456 -                if (wrapBySimple) {
128.1457 -                    delegate = new ProxyLookup(arr);                    
128.1458 -                } else {
128.1459 -                    delegate.setLookups(arr);
128.1460 -                }
128.1461 -            }
128.1462 -        }
128.1463 -        
128.1464 -        Provider p = new Provider(lookups);
128.1465 -        
128.1466 -        Lookup.Result res = p.query.lookup(new Lookup.Template(ActionMap.class));
128.1467 -        LL ll = new LL();
128.1468 -        res.addLookupListener(ll);
128.1469 -
128.1470 -        Collection c = res.allInstances();
128.1471 -        assertFalse("Has next", c.isEmpty());
128.1472 -        
128.1473 -        ActionMap am1 = (ActionMap)c.iterator().next();
128.1474 -        assertEquals("Am is there", am, am1);
128.1475 -        
128.1476 -        assertEquals("Correct # of changes in first get", firstChange, ll.getCount());
128.1477 -        
128.1478 -        Object m1 = new InputMap();
128.1479 -        Object m2 = new InputMap();
128.1480 -        
128.1481 -        ic.add(m1);
128.1482 -        assertEquals("No change in ActionMap 1", 0, ll.getCount());
128.1483 -        ic.set(Collections.singletonList(m2), null);
128.1484 -        assertEquals("No change in ActionMap 2", 0, ll.getCount());
128.1485 -        ic.add(m2);
128.1486 -        assertEquals("No change in ActionMap 3", 0, ll.getCount());
128.1487 -        p.setLookups(lookup, actionMapLookup, Lookup.EMPTY);
128.1488 -        assertEquals("No change in ActionMap 4", 0, ll.getCount());
128.1489 -        
128.1490 -        ActionMap am2 = p.query.lookup(ActionMap.class);
128.1491 -        assertEquals("Still the same action map", am, am2);
128.1492 -        
128.1493 -        
128.1494 -        class Before extends AbstractLookup {
128.1495 -            public InstanceContent ic;
128.1496 -            public Before() {
128.1497 -                this(new InstanceContent());
128.1498 -            }
128.1499 -            
128.1500 -            private Before(InstanceContent ic) {
128.1501 -                super(ic);
128.1502 -                this.ic = ic;
128.1503 -            }
128.1504 -
128.1505 -            protected @Override void beforeLookup(Template template) {
128.1506 -                if (ic != null) {
128.1507 -                    ic.add(am);
128.1508 -                    ic = null;
128.1509 -                }
128.1510 -            }
128.1511 -        }
128.1512 -        
128.1513 -        Before s = new Before();
128.1514 -        
128.1515 -        // adding different Before, but returning the same instance
128.1516 -        // this happens with metaInfServices lookup often, moreover
128.1517 -        // it adds the instance in beforeLookup, which confuses a lot
128.1518 -        p.setLookups(new Lookup[]{ lookup, new Before() });
128.1519 -        assertEquals("No change in ActionMap 5", 0, ll.getCount());
128.1520 -        
128.1521 -        
128.1522 -    }
128.1523 -
128.1524 -    public void testTasklistsCase() throws Exception {
128.1525 -        ic.remove(new Object());
128.1526 -    }
128.1527 -    
128.1528 -    
128.1529 -
128.1530 -    public void testMultipleListeners() {
128.1531 -        Object object = new ImplementationObject();
128.1532 -        ic.add(object);
128.1533 -        
128.1534 -        Listener[] listeners = new Listener[4];
128.1535 -        Lookup.Result result = lookup.lookup(new Lookup.Template(LookupObject.class));
128.1536 -        for(int i = 0; i < listeners.length; ++i) {
128.1537 -            listeners[i] = new Listener();
128.1538 -            result.addLookupListener(listeners[i]);
128.1539 -        }
128.1540 -        // initialize listening
128.1541 -        result.allItems();
128.1542 -        
128.1543 -        ic.remove(object);
128.1544 -        
128.1545 -        // Apparently, only odd-numbered listeners get called when there are multiple LookupListeners on a result
128.1546 -        //for(int i = 0; i < listeners.length; ++i) {
128.1547 -        //    System.out.println("Listener " + i + ": " + listeners[i].wasCalled());            
128.1548 -        //}
128.1549 -        for(int i = 0; i < listeners.length; ++i) {
128.1550 -            assertTrue("Listener " + i + " called", listeners[i].wasCalled());
128.1551 -        }
128.1552 -    }
128.1553 -
128.1554 -    static Object reserialize(Object o) throws Exception {
128.1555 -        ByteArrayOutputStream os = new ByteArrayOutputStream();
128.1556 -        ObjectOutputStream oos = new ObjectOutputStream(os);
128.1557 -        oos.writeObject(o);
128.1558 -        oos.close();
128.1559 -
128.1560 -        ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
128.1561 -        ObjectInputStream ois = new ObjectInputStream(is);
128.1562 -        return ois.readObject();
128.1563 -    }
128.1564 -    
128.1565 -    private class Listener implements LookupListener {
128.1566 -        private boolean listenerCalled = false;
128.1567 -        
128.1568 -        public void resultChanged(LookupEvent ev) {
128.1569 -            listenerCalled = true;
128.1570 -        }
128.1571 -        
128.1572 -        public boolean wasCalled() {
128.1573 -            return listenerCalled;
128.1574 -        }
128.1575 -        
128.1576 -        public void reset() {
128.1577 -            listenerCalled = false;
128.1578 -        }
128.1579 -    }
128.1580 -    
128.1581 -    private interface LookupObject {}
128.1582 -    private class ImplementationObject implements LookupObject {}
128.1583 -    private class NullObject implements LookupObject {}
128.1584 -    
128.1585 -    
128.1586 -    public void testReturnSomethingElseThenYouClaimYouWillReturn() {
128.1587 -        class Liar extends AbstractLookup.Pair {
128.1588 -            public Object obj;
128.1589 -            
128.1590 -            protected boolean instanceOf(Class c) {
128.1591 -                return c.isAssignableFrom(String.class);
128.1592 -            }
128.1593 -
128.1594 -            protected boolean creatorOf(Object obj) {
128.1595 -                return this.obj == obj;
128.1596 -            }
128.1597 -
128.1598 -            public Object getInstance() {
128.1599 -                return this.obj;
128.1600 -            }
128.1601 -
128.1602 -            public Class getType() {
128.1603 -                return String.class;
128.1604 -            }
128.1605 -
128.1606 -            public String getId() {
128.1607 -                return String.class.getName();
128.1608 -            }
128.1609 -
128.1610 -            public String getDisplayName() {
128.1611 -                return getId();
128.1612 -            }
128.1613 -        }
128.1614 -        
128.1615 -        
128.1616 -        Liar l = new Liar();
128.1617 -        l.obj = new Integer(5);
128.1618 -        
128.1619 -        this.ic.addPair(l);
128.1620 -        
128.1621 -        Collection c = lookup.lookup(new Lookup.Template(String.class)).allInstances();
128.1622 -        assertTrue("It is empty: " + c, c.isEmpty());
128.1623 -    }
128.1624 -
128.1625 -    public void testCanProxyLookupHaveWrongResults() {
128.1626 -        class L implements LookupListener {
128.1627 -            ProxyLookup pl;
128.1628 -            Lookup.Result<String> original;
128.1629 -            Lookup.Result<String> wrapped;
128.1630 -            boolean ok;
128.1631 -
128.1632 -            public void test() {
128.1633 -                pl = new ProxyLookup(lookup);
128.1634 -                original = lookup.lookupResult(String.class);
128.1635 -
128.1636 -                original.addLookupListener(this);
128.1637 -
128.1638 -                wrapped = pl.lookupResult(String.class);
128.1639 -
128.1640 -                assertEquals("Original empty", 0, original.allInstances().size());
128.1641 -                assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
128.1642 -
128.1643 -                ic.add("Hello!");
128.1644 -            }
128.1645 -
128.1646 -            public void resultChanged(LookupEvent ev) {
128.1647 -                ok = true;
128.1648 -
128.1649 -                assertEquals("Original has hello", 1, original.allInstances().size());
128.1650 -                assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
128.1651 -            }
128.1652 -
128.1653 -        }
128.1654 -        L listener = new L();
128.1655 -        listener.test();
128.1656 -        assertTrue("Listener called", listener.ok);
128.1657 -    }
128.1658 -
128.1659 -    public void testObjectFromInstanceContentConverterDisappearsIfNotReferenced() {
128.1660 -        Conv converter = new Conv("foo");
128.1661 -        ic.add (converter, converter);
128.1662 -        Lookup lkp = instanceLookup;
128.1663 -        StringBuilder sb = lookup.lookup (StringBuilder.class);
128.1664 -        assertNotNull (sb);
128.1665 -        int hash = System.identityHashCode(sb);
128.1666 -        assertEquals ("foo", sb.toString());
128.1667 -        Reference<StringBuilder> r = new WeakReference<StringBuilder>(sb);
128.1668 -        sb = null;
128.1669 -        assertGC("Lookup held onto object", r);
128.1670 -        sb = lookup.lookup (StringBuilder.class);
128.1671 -        assertNotSame(hash, System.identityHashCode(sb));
128.1672 -        r = new WeakReference<StringBuilder>(sb);
128.1673 -        sb = null;
128.1674 -        assertGC("Lookup held onto object", r);
128.1675 -        ic.remove (converter, converter);
128.1676 -        Reference <InstanceContent.Convertor> cref = new WeakReference<InstanceContent.Convertor>(converter);
128.1677 -        converter = null;
128.1678 -        assertGC("Converter still referenced", cref); 
128.1679 -
128.1680 -        sb = lkp.lookup(StringBuilder.class);
128.1681 -        assertNull ("Converter removed from lookup, but object it " +
128.1682 -                "created still present:'" + sb +"'", sb);
128.1683 -        converter = new Conv("bar");
128.1684 -        ic.add (converter, converter);
128.1685 -        assertNotNull (lkp.lookup(StringBuilder.class));
128.1686 -        assertEquals ("bar", lkp.lookup(StringBuilder.class).toString());
128.1687 -    }
128.1688 -
128.1689 -    private static class Conv implements InstanceContent.Convertor<Conv, StringBuilder> {
128.1690 -        private final String str;
128.1691 -        private Conv (String str) {
128.1692 -            this.str = str;
128.1693 -        }
128.1694 -
128.1695 -        public StringBuilder convert(Conv obj) {
128.1696 -            return new StringBuilder (str);
128.1697 -        }
128.1698 -
128.1699 -        public Class<? extends StringBuilder> type(Conv obj) {
128.1700 -            return StringBuilder.class;
128.1701 -        }
128.1702 -
128.1703 -        public String id(Conv obj) {
128.1704 -            return "Foo";
128.1705 -        }
128.1706 -
128.1707 -        public String displayName(Conv obj) {
128.1708 -            return "Foo";
128.1709 -        }
128.1710 -    } // end of Conv
128.1711 -
128.1712 -    public void testCanGCResults() throws Exception {
128.1713 -        class L implements LookupListener {
128.1714 -            int cnt;
128.1715 -            
128.1716 -            public void resultChanged(LookupEvent ev) {
128.1717 -                cnt++;
128.1718 -            }
128.1719 -            
128.1720 -        }
128.1721 -        L listener1 = new L();
128.1722 -        L listener2 = new L();
128.1723 -        
128.1724 -        Lookup.Result<String> res1 = this.instanceLookup.lookupResult(String.class);
128.1725 -        Lookup.Result<String> res2 = this.lookup.lookupResult(String.class);
128.1726 -        
128.1727 -        assertEquals("Empty1", 0, res1.allItems().size());
128.1728 -        assertEquals("Empty2", 0, res2.allItems().size());
128.1729 -        
128.1730 -        res1.addLookupListener(listener1);
128.1731 -        res2.addLookupListener(listener2);
128.1732 -        
128.1733 -        addInstances(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
128.1734 -        this.ic.add("Ahoj");
128.1735 -        
128.1736 -        assertEquals("Change1", 1, listener1.cnt);
128.1737 -        assertEquals("Change2", 1, listener2.cnt);
128.1738 -        
128.1739 -        assertEquals("Full1", 1, res1.allItems().size());
128.1740 -        assertEquals("Full2", 1, res2.allItems().size());
128.1741 -        
128.1742 -        
128.1743 -        Reference<Object> ref2 = new WeakReference<Object>(res2);
128.1744 -        res2 = null;
128.1745 -        assertGC("Result can disappear", ref2);
128.1746 -    }
128.1747 -    
128.1748 -    void beforeActualTest(String n) {
128.1749 -        if (n.equals("testEqualsIsNotCalledTooMuch")) {
128.1750 -            CntPair.cnt = 0;
128.1751 -            CntPair.hashCnt = 0;
128.1752 -            CntPair.instances = 0;
128.1753 -            int how = 1000;
128.1754 -
128.1755 -            for(int i = 0; i < how; i++) {
128.1756 -                this.ic.addPair(new CntPair("x" + i));
128.1757 -            }
128.1758 -
128.1759 -            assertEquals("No equals called", 0, CntPair.cnt);
128.1760 -            assertEquals("1000 instances ", how, CntPair.instances);
128.1761 -        }
128.1762 -    }
128.1763 -    
128.1764 -    public void testEqualsIsNotCalledTooMuch() throws Exception {
128.1765 -        // most of the work done in beforeActualTest
128.1766 -
128.1767 -        // desirable: assertEquals("no comparitions", 0, CntPair.cnt);
128.1768 -        // works for InheritanceTree, but not for ArrayStorage, but array
128.1769 -        // storages are generally small
128.1770 -        
128.1771 -        if (CntPair.cnt > 12000) {
128.1772 -            fail("Too much comparitions " + CntPair.cnt);
128.1773 -        }
128.1774 -        if (CntPair.hashCnt > 40000) {
128.1775 -            fail("Too much hashes: " + CntPair.hashCnt);
128.1776 -        }
128.1777 -        
128.1778 -        assertEquals("instaces is enough", 1000, CntPair.instances);
128.1779 -    }
128.1780 -    
128.1781 -    /** Adds instances to the instance lookup.
128.1782 -     */
128.1783 -    private void addInstances (Object... instances) {
128.1784 -        for (int i = 0; i < instances.length; i++) {
128.1785 -            ic.add(instances[i]);
128.1786 -        }
128.1787 -    }
128.1788 -    
128.1789 -    /** Count instances of clazz in an array. */
128.1790 -    private int countInstances (Object[] objs, Class clazz) {
128.1791 -        int count = 0;
128.1792 -        for (int i = 0; i < objs.length; i++) {
128.1793 -            if (clazz.isInstance(objs[i])) count++;
128.1794 -        }
128.1795 -        return count;
128.1796 -    }
128.1797 -    
128.1798 -    /** Counting listener */
128.1799 -    protected static class LL implements LookupListener {
128.1800 -        private int count = 0;
128.1801 -        public Object source;
128.1802 -        public Thread changesIn;
128.1803 -        
128.1804 -        public LL () {
128.1805 -            this (null);
128.1806 -        }
128.1807 -        
128.1808 -        public LL (Object source) {
128.1809 -            this.source = source;
128.1810 -        }
128.1811 -        
128.1812 -        public void resultChanged(LookupEvent ev) {
128.1813 -            if (changesIn != null) {
128.1814 -                assertEquals("Changes in the same thread", changesIn, Thread.currentThread());
128.1815 -            } else {
128.1816 -                changesIn = Thread.currentThread();
128.1817 -            }
128.1818 -            ++count;
128.1819 -            if (source != null) {
128.1820 -                assertSame ("Source is the same", source, ev.getSource ());
128.1821 -//                assertSame ("Result is the same", source, ev.getResult ());
128.1822 -            }
128.1823 -        }
128.1824 -
128.1825 -        public int getCount() {
128.1826 -            int i = count;
128.1827 -            count = 0;
128.1828 -            return i;
128.1829 -        }
128.1830 -    };
128.1831 -
128.1832 -    /** A set of interfaces for testInterfaceInheritance
128.1833 -     */
128.1834 -    interface TestInterfaceInheritanceA {}
128.1835 -    interface TestInterfaceInheritanceB extends TestInterfaceInheritanceA, java.rmi.Remote {}
128.1836 -    interface TestInterfaceInheritanceBB extends TestInterfaceInheritanceB {}
128.1837 -    interface TestInterfaceInheritanceC extends TestInterfaceInheritanceA, java.rmi.Remote {}
128.1838 -    interface TestInterfaceInheritanceD extends TestInterfaceInheritanceA {}
128.1839 -    
128.1840 -    /** A special class for garbage test */
128.1841 -    public static final class Garbage extends Object implements Serializable {
128.1842 -        static final long serialVersionUID = 435340912534L;
128.1843 -    }
128.1844 -    
128.1845 -
128.1846 -    /* A classloader that can load one class in a special way */
128.1847 -    private static class CL extends ClassLoader {
128.1848 -        public CL () {
128.1849 -            super (null);
128.1850 -        }
128.1851 -
128.1852 -        public @Override Class findClass(String name) throws ClassNotFoundException {
128.1853 -            if (name.equals (Garbage.class.getName ())) {
128.1854 -                String n = name.replace ('.', '/');
128.1855 -                java.io.InputStream is = getClass ().getResourceAsStream ("/" + n + ".class");
128.1856 -                byte[] arr = new byte[8096];
128.1857 -                try {
128.1858 -                    int cnt = is.read (arr);
128.1859 -                    if (cnt == arr.length) {
128.1860 -                        fail ("Buffer to load the class is not big enough");
128.1861 -                    }
128.1862 -
128.1863 -                    return defineClass (name, arr, 0, cnt);
128.1864 -                } catch (java.io.IOException ex) {
128.1865 -                        ex.printStackTrace();
128.1866 -                        fail ("IO Exception");
128.1867 -                        return null;
128.1868 -                }
128.1869 -            } else {
128.1870 -                return null;
128.1871 -            }
128.1872 -        }
128.1873 -
128.1874 -        /** Convert obj to other object. There is no need to implement
128.1875 -         * cache mechanism. It is provided by AbstractLookup.Item.getInstance().
128.1876 -         * Method should be called more than once because Lookup holds
128.1877 -         * just weak reference.
128.1878 -         */
128.1879 -        public Object convert(Object obj) {
128.1880 -            return null;
128.1881 -        }
128.1882 -
128.1883 -        /** Return type of converted object. */
128.1884 -        public Class type(Object obj) {
128.1885 -            try {
128.1886 -                return loadClass (Garbage.class.getName ());
128.1887 -            } catch (ClassNotFoundException ex) {
128.1888 -                fail ("Class not found");
128.1889 -                throw new InternalError ();
128.1890 -            }
128.1891 -        }
128.1892 -    }
128.1893 -    
128.1894 -    private static final class CntPair extends AbstractLookup.Pair {
128.1895 -        private static int instances;
128.1896 -        private String txt;
128.1897 -        
128.1898 -        public CntPair(String txt) {
128.1899 -            this.txt = txt;
128.1900 -            instances++;
128.1901 -        }
128.1902 -
128.1903 -        public static int hashCnt;
128.1904 -        @Override
128.1905 -        public int hashCode() {
128.1906 -            hashCnt++;
128.1907 -            return txt.hashCode() + 3777;
128.1908 -        }
128.1909 -
128.1910 -        public static int cnt;
128.1911 -        @Override
128.1912 -        public boolean equals(Object obj) {
128.1913 -            cnt++;
128.1914 -            
128.1915 -            if (obj == null) {
128.1916 -                return false;
128.1917 -            }
128.1918 -            if (getClass() != obj.getClass()) {
128.1919 -                return false;
128.1920 -            }
128.1921 -            final CntPair other = (CntPair) obj;
128.1922 -            if (this.txt != other.txt && (this.txt == null || !this.txt.equals(other.txt))) {
128.1923 -                return false;
128.1924 -            }
128.1925 -            return true;
128.1926 -        }
128.1927 -
128.1928 -        protected boolean instanceOf(Class c) {
128.1929 -            return c.isAssignableFrom(String.class);
128.1930 -        }
128.1931 -
128.1932 -        protected boolean creatorOf(Object obj) {
128.1933 -            return obj == txt;
128.1934 -        }
128.1935 -
128.1936 -        public Object getInstance() {
128.1937 -            return txt;
128.1938 -        }
128.1939 -
128.1940 -        public Class getType() {
128.1941 -            return String.class;
128.1942 -        }
128.1943 -
128.1944 -        public String getId() {
128.1945 -            return txt;
128.1946 -        }
128.1947 -
128.1948 -        public String getDisplayName() {
128.1949 -            return txt;
128.1950 -        }
128.1951 -        
128.1952 -    }
128.1953 -
128.1954 -    public static final class SerialPair extends AbstractLookup.Pair
128.1955 -    implements java.io.Serializable {
128.1956 -        static final long serialVersionUID = 54305834L;
128.1957 -        private Object value;
128.1958 -        public transient int countInstanceOf;
128.1959 -        
128.1960 -        public SerialPair (Object value) {
128.1961 -            this.value = value;
128.1962 -        }
128.1963 -        
128.1964 -        protected boolean creatorOf(Object obj) {
128.1965 -            return obj == value;
128.1966 -        }
128.1967 -        
128.1968 -        public String getDisplayName() {
128.1969 -            return getId ();
128.1970 -        }
128.1971 -        
128.1972 -        public String getId() {
128.1973 -            return value.toString();
128.1974 -        }
128.1975 -        
128.1976 -        public Object getInstance() {
128.1977 -            return value;
128.1978 -        }
128.1979 -        
128.1980 -        public Class getType() {
128.1981 -            return value.getClass ();
128.1982 -        }
128.1983 -        
128.1984 -        protected boolean instanceOf(Class c) {
128.1985 -            countInstanceOf++;
128.1986 -            return c.isInstance(value);
128.1987 -        }
128.1988 -    } // end of SerialPair
128.1989 -    
128.1990 -    private static class BrokenPair extends AbstractLookup.Pair {
128.1991 -        private transient ThreadLocal IN = new ThreadLocal ();
128.1992 -        private boolean checkModify;
128.1993 -        private boolean checkQuery;
128.1994 -        
128.1995 -        public BrokenPair (boolean checkModify, boolean checkQuery) {
128.1996 -            this.checkModify = checkModify;
128.1997 -            this.checkQuery = checkQuery;
128.1998 -        }
128.1999 -        
128.2000 -        protected boolean creatorOf(Object obj) { return this == obj; }
128.2001 -        public String getDisplayName() { return "Broken"; }
128.2002 -        public String getId() { return "broken"; }
128.2003 -        public Object getInstance() { return this; }
128.2004 -        public Class getType() { return getClass (); }
128.2005 -        protected boolean instanceOf(Class c) { 
128.2006 -            
128.2007 -            if (checkQuery) {
128.2008 -                if (IN.get () == null) {
128.2009 -                    try {
128.2010 -                        IN.set (this);
128.2011 -                        // broken behaviour, tries to modify the lookup
128.2012 -                        // queries have to survive
128.2013 -
128.2014 -                        running.lookup.lookup (java.awt.List.class);
128.2015 -
128.2016 -                        // 
128.2017 -                        // creation of new result has to survive as well
128.2018 -                        Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.Button.class));
128.2019 -                        Collection all = myQuery.allItems ();
128.2020 -                    } finally {
128.2021 -                        IN.set (null);
128.2022 -                    }
128.2023 -                }
128.2024 -            }
128.2025 -                
128.2026 -
128.2027 -            if (checkModify) {
128.2028 -                //
128.2029 -                // modifications should fail
128.2030 -                //
128.2031 -
128.2032 -                try {
128.2033 -                    running.ic.addPair (new SerialPair (""));
128.2034 -                    fail ("Modification from a query should be prohibited");
128.2035 -                } catch (IllegalStateException ex) {
128.2036 -                }
128.2037 -                
128.2038 -                try {
128.2039 -                    running.ic.removePair (this);
128.2040 -                    fail ("This has to throw the exception");
128.2041 -                } catch (IllegalStateException ex) {
128.2042 -                }
128.2043 -                try {
128.2044 -                    running.ic.setPairs (Collections.EMPTY_SET);
128.2045 -                    fail ("This has to throw the exception as well");
128.2046 -                } catch (IllegalStateException ex) {
128.2047 -                }
128.2048 -            }
128.2049 -            
128.2050 -            return c.isAssignableFrom(getType ()); 
128.2051 -        }
128.2052 -    } // end of BrokenPair
128.2053 -    
128.2054 -    private static class Broken2Pair extends AbstractLookup.Pair {
128.2055 -        static final long serialVersionUID = 4532587018501L;
128.2056 -        public transient ThreadLocal IN;
128.2057 -        
128.2058 -        public Broken2Pair () {
128.2059 -        }
128.2060 -        
128.2061 -        private void writeObject (java.io.ObjectOutputStream oos) throws java.io.IOException {
128.2062 -        }
128.2063 -        
128.2064 -        private void readObject (java.io.ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException {
128.2065 -            IN = new ThreadLocal ();
128.2066 -        }
128.2067 -        
128.2068 -        protected boolean creatorOf(Object obj) { return this == obj; }
128.2069 -        public String getDisplayName() { return "Broken"; }
128.2070 -        public String getId() { return "broken"; }
128.2071 -        public Object getInstance() { return this; }
128.2072 -        public Class getType() { return getClass (); }
128.2073 -        protected boolean instanceOf(Class c) { 
128.2074 -            
128.2075 -            // behaviour gets broken only after deserialization
128.2076 -            if (IN != null && IN.get () == null) {
128.2077 -                try {
128.2078 -                    IN.set (this);
128.2079 -
128.2080 -                    // creation of new result has to survive as well
128.2081 -                    Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.List.class));
128.2082 -                    Collection all = myQuery.allItems ();
128.2083 -                } finally {
128.2084 -                    IN.set (null);
128.2085 -                }
128.2086 -            }
128.2087 -            
128.2088 -            return c.isAssignableFrom(getType ()); 
128.2089 -        }
128.2090 -    } // end of Broken2Pair    
128.2091 -}
   129.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupExecutorTest.java	Thu Dec 10 19:23:25 2009 -0500
   129.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.3 @@ -1,98 +0,0 @@
   129.4 -/*
   129.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   129.6 - *
   129.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   129.8 - *
   129.9 - * The contents of this file are subject to the terms of either the GNU
  129.10 - * General Public License Version 2 only ("GPL") or the Common
  129.11 - * Development and Distribution License("CDDL") (collectively, the
  129.12 - * "License"). You may not use this file except in compliance with the
  129.13 - * License. You can obtain a copy of the License at
  129.14 - * http://www.netbeans.org/cddl-gplv2.html
  129.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  129.16 - * specific language governing permissions and limitations under the
  129.17 - * License.  When distributing the software, include this License Header
  129.18 - * Notice in each file and include the License file at
  129.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  129.20 - * particular file as subject to the "Classpath" exception as provided
  129.21 - * by Sun in the GPL Version 2 section of the License file that
  129.22 - * accompanied this code. If applicable, add the following below the
  129.23 - * License Header, with the fields enclosed by brackets [] replaced by
  129.24 - * your own identifying information:
  129.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  129.26 - *
  129.27 - * Contributor(s):
  129.28 - *
  129.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  129.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  129.31 - * Microsystems, Inc. All Rights Reserved.
  129.32 - *
  129.33 - * If you wish your version of this file to be governed by only the CDDL
  129.34 - * or only the GPL Version 2, indicate your decision by adding
  129.35 - * "[Contributor] elects to include this software in this distribution
  129.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  129.37 - * single choice of license, a recipient has the option to distribute
  129.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  129.39 - * to extend the choice of license to its licensees as provided above.
  129.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  129.41 - * Version 2 license, then the option applies only if the new code is
  129.42 - * made subject to such option by the copyright holder.
  129.43 - */
  129.44 -
  129.45 -package org.openide.util.lookup;
  129.46 -
  129.47 -import java.util.concurrent.Executor;
  129.48 -import org.openide.util.Lookup;
  129.49 -import org.openide.util.LookupEvent;
  129.50 -import org.openide.util.LookupListener;
  129.51 -
  129.52 -public class AbstractLookupExecutorTest extends AbstractLookupBaseHid 
  129.53 -implements AbstractLookupBaseHid.Impl, Executor, LookupListener {
  129.54 -    Lookup.Result<?> res;
  129.55 -    
  129.56 -    
  129.57 -    public AbstractLookupExecutorTest(java.lang.String testName) {
  129.58 -        super(testName, null);
  129.59 -    }
  129.60 -
  129.61 -    //
  129.62 -    // Impl of AbstractLookupBaseHid.Impl
  129.63 -    //
  129.64 -
  129.65 -    /** Creates the initial abstract lookup.
  129.66 -     */
  129.67 -    public Lookup createInstancesLookup (InstanceContent ic) {
  129.68 -        ic.attachExecutor(this);
  129.69 -        Lookup l = new AbstractLookup (ic, new InheritanceTree ());
  129.70 -        return l;
  129.71 -    }
  129.72 -    
  129.73 -    /** Creates an lookup for given lookup. This class just returns 
  129.74 -     * the object passed in, but subclasses can be different.
  129.75 -     * @param lookup in lookup
  129.76 -     * @return a lookup to use
  129.77 -     */
  129.78 -    public Lookup createLookup (Lookup lookup) {
  129.79 -        res = lookup.lookupResult(Object.class);
  129.80 -        res.addLookupListener(this);
  129.81 -        return lookup;
  129.82 -    }
  129.83 -
  129.84 -    public void clearCaches () {
  129.85 -    }    
  129.86 -
  129.87 -    ThreadLocal<Object> ME = new ThreadLocal<Object>();
  129.88 -    public void execute(Runnable command) {
  129.89 -        assertEquals("Not yet set", null, ME.get());
  129.90 -        ME.set(this);
  129.91 -        try {
  129.92 -            command.run();
  129.93 -        } finally {
  129.94 -            ME.set(null);
  129.95 -        }
  129.96 -    }
  129.97 -
  129.98 -    public void resultChanged(LookupEvent ev) {
  129.99 -        assertEquals("Changes delivered only from execute method", this, ME.get());
 129.100 -    }
 129.101 -}
   130.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupMemoryTest.java	Thu Dec 10 19:23:25 2009 -0500
   130.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.3 @@ -1,158 +0,0 @@
   130.4 -/*
   130.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   130.6 - *
   130.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   130.8 - *
   130.9 - * The contents of this file are subject to the terms of either the GNU
  130.10 - * General Public License Version 2 only ("GPL") or the Common
  130.11 - * Development and Distribution License("CDDL") (collectively, the
  130.12 - * "License"). You may not use this file except in compliance with the
  130.13 - * License. You can obtain a copy of the License at
  130.14 - * http://www.netbeans.org/cddl-gplv2.html
  130.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  130.16 - * specific language governing permissions and limitations under the
  130.17 - * License.  When distributing the software, include this License Header
  130.18 - * Notice in each file and include the License file at
  130.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  130.20 - * particular file as subject to the "Classpath" exception as provided
  130.21 - * by Sun in the GPL Version 2 section of the License file that
  130.22 - * accompanied this code. If applicable, add the following below the
  130.23 - * License Header, with the fields enclosed by brackets [] replaced by
  130.24 - * your own identifying information:
  130.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  130.26 - *
  130.27 - * Contributor(s):
  130.28 - *
  130.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  130.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  130.31 - * Microsystems, Inc. All Rights Reserved.
  130.32 - *
  130.33 - * If you wish your version of this file to be governed by only the CDDL
  130.34 - * or only the GPL Version 2, indicate your decision by adding
  130.35 - * "[Contributor] elects to include this software in this distribution
  130.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  130.37 - * single choice of license, a recipient has the option to distribute
  130.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  130.39 - * to extend the choice of license to its licensees as provided above.
  130.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  130.41 - * Version 2 license, then the option applies only if the new code is
  130.42 - * made subject to such option by the copyright holder.
  130.43 - */
  130.44 -
  130.45 -package org.openide.util.lookup;
  130.46 -
  130.47 -import java.util.*;
  130.48 -import org.netbeans.junit.*;
  130.49 -import org.netbeans.modules.openide.util.ActiveQueue;
  130.50 -import org.openide.util.Lookup;
  130.51 -
  130.52 -/** Testing memory consumption of various AbstractLookup aspects.
  130.53 - */
  130.54 -public class AbstractLookupMemoryTest extends NbTestCase {
  130.55 -    public AbstractLookupMemoryTest(java.lang.String testName) {
  130.56 -        super(testName);
  130.57 -    }
  130.58 -
  130.59 -    public static void main(java.lang.String[] args) {
  130.60 -        junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupMemoryTest.class));
  130.61 -    }
  130.62 -
  130.63 -    public void testEmptySize () {
  130.64 -        AbstractLookup instanceLookup = new AbstractLookup ();
  130.65 -        assertSize ("Empty lookup should be small", 16, instanceLookup);
  130.66 -        
  130.67 -        InstanceContent ic = new InstanceContent ();
  130.68 -        instanceLookup = new AbstractLookup (ic);
  130.69 -        assertSize ("Lookup with InstanceContent should be small as well", 16, instanceLookup);
  130.70 -    }
  130.71 -
  130.72 -    public void testPairSize () {
  130.73 -        AbstractLookup.Pair pair = new EmptyPair ();
  130.74 -        assertSize ("Pair occupies only 16 bytes", 16, pair);
  130.75 -    }
  130.76 -    
  130.77 -    public void testPairWithOnePointerSize () {
  130.78 -        AbstractLookup.Pair pair = new OneItemPair ();
  130.79 -        assertSize ("Pair occupies only 16 bytes", 16, pair);
  130.80 -    }
  130.81 -    
  130.82 -    public void testLookupWithPairs () {
  130.83 -        Lookup.Template<Object> t = new Lookup.Template<Object>(Object.class);
  130.84 -        class L implements org.openide.util.LookupListener {
  130.85 -            public int cnt;
  130.86 -            public void resultChanged (org.openide.util.LookupEvent ev) {
  130.87 -                cnt++;
  130.88 -            }
  130.89 -        }
  130.90 -        L listener = new L ();
  130.91 -        L listener2 = new L ();
  130.92 -
  130.93 -        EmptyPair[] pairs = {
  130.94 -            new EmptyPair(),
  130.95 -            new EmptyPair(),
  130.96 -            new EmptyPair(),
  130.97 -            new EmptyPair(),
  130.98 -        };
  130.99 -        Object[] ignore = {
 130.100 -            pairs[0],
 130.101 -            pairs[1],
 130.102 -            pairs[2],
 130.103 -            pairs[3],
 130.104 -            t,
 130.105 -            ActiveQueue.queue(),
 130.106 -            listener,
 130.107 -            listener2,
 130.108 -            new Integer (11) // trashhold is shared
 130.109 -        };
 130.110 -        
 130.111 -        AbstractLookup.Content c = new AbstractLookup.Content ();
 130.112 -        AbstractLookup l = new AbstractLookup (c, (Integer)ignore[ignore.length - 1]);
 130.113 -
 130.114 -        c.addPair ((EmptyPair)ignore[0]);
 130.115 -        assertSize ("Should be really small (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
 130.116 -        
 130.117 -        c.addPair ((EmptyPair)ignore[1]);
 130.118 -        assertSize ("Is bigger I guess (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
 130.119 -        
 130.120 -        c.setPairs(Arrays.asList(pairs).subList(0, 3));
 130.121 -        assertSize ("Even bigger (not counting the pair sizes)", Collections.singleton (l), 64, ignore);
 130.122 -        
 130.123 -        c.setPairs(Arrays.asList(pairs).subList(0, 4));
 130.124 -        assertSize ("Now not that much(not counting the pair sizes)", Collections.singleton (l), 64, ignore);
 130.125 -        
 130.126 -        Lookup.Result res = l.lookup (t);
 130.127 -        
 130.128 -        assertSize ("After creating a result", Collections.singleton (l), 120, ignore);
 130.129 -        
 130.130 -        res.addLookupListener (listener);
 130.131 -        
 130.132 -        assertSize ("And attaching one listener", Collections.singleton (l), 120, ignore);
 130.133 -
 130.134 -        res.addLookupListener (listener2);
 130.135 -        assertSize ("Second listener makes the situation much worse", Collections.singleton (l), 200, ignore);
 130.136 -        res.removeLookupListener(listener2);
 130.137 -        assertSize ("But removing it returns us back to original size", Collections.singleton (l), 120, ignore);
 130.138 -        
 130.139 -        
 130.140 -        assertEquals ("Current for pairs are in", res.allItems ().size (), 4); // also activates the listener
 130.141 -        assertSize ("and making the listener to work", Collections.singleton (l), 120, ignore);
 130.142 -        
 130.143 -        c.removePair ((EmptyPair)ignore[0]);
 130.144 -        assertEquals ("A changes has been delivered", 1, listener.cnt);
 130.145 -    }
 130.146 -
 130.147 -    /** Simple pair with no data */
 130.148 -    private static class EmptyPair extends AbstractLookup.Pair {
 130.149 -        protected boolean creatorOf(Object obj) { return false; }
 130.150 -        public String getDisplayName() { return ""; }
 130.151 -        public String getId() { return ""; }
 130.152 -        public Object getInstance() { return null; }
 130.153 -        public Class getType() { return Object.class; }
 130.154 -        protected boolean instanceOf(Class c) { return c == getType (); }
 130.155 -    } // end of EmptyPair
 130.156 -    
 130.157 -    /** Pair with one item (like InstanceContent.Pair) */
 130.158 -    private static class OneItemPair extends EmptyPair {
 130.159 -        private Object pointer;
 130.160 -    }
 130.161 -}
   131.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   131.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.3 @@ -1,353 +0,0 @@
   131.4 -/*
   131.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   131.6 - *
   131.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   131.8 - *
   131.9 - * The contents of this file are subject to the terms of either the GNU
  131.10 - * General Public License Version 2 only ("GPL") or the Common
  131.11 - * Development and Distribution License("CDDL") (collectively, the
  131.12 - * "License"). You may not use this file except in compliance with the
  131.13 - * License. You can obtain a copy of the License at
  131.14 - * http://www.netbeans.org/cddl-gplv2.html
  131.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  131.16 - * specific language governing permissions and limitations under the
  131.17 - * License.  When distributing the software, include this License Header
  131.18 - * Notice in each file and include the License file at
  131.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  131.20 - * particular file as subject to the "Classpath" exception as provided
  131.21 - * by Sun in the GPL Version 2 section of the License file that
  131.22 - * accompanied this code. If applicable, add the following below the
  131.23 - * License Header, with the fields enclosed by brackets [] replaced by
  131.24 - * your own identifying information:
  131.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  131.26 - *
  131.27 - * Contributor(s):
  131.28 - *
  131.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  131.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  131.31 - * Microsystems, Inc. All Rights Reserved.
  131.32 - *
  131.33 - * If you wish your version of this file to be governed by only the CDDL
  131.34 - * or only the GPL Version 2, indicate your decision by adding
  131.35 - * "[Contributor] elects to include this software in this distribution
  131.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  131.37 - * single choice of license, a recipient has the option to distribute
  131.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  131.39 - * to extend the choice of license to its licensees as provided above.
  131.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  131.41 - * Version 2 license, then the option applies only if the new code is
  131.42 - * made subject to such option by the copyright holder.
  131.43 - */
  131.44 -
  131.45 -package org.openide.util.lookup;
  131.46 -
  131.47 -import java.util.concurrent.ExecutionException;
  131.48 -
  131.49 -import java.lang.ref.WeakReference;
  131.50 -import java.util.*;
  131.51 -import java.util.concurrent.Executors;
  131.52 -import java.util.concurrent.TimeUnit;
  131.53 -import junit.framework.Test;
  131.54 -import org.netbeans.junit.*;
  131.55 -import org.openide.util.Lookup;
  131.56 -import org.openide.util.lookup.AbstractLookup.Pair;
  131.57 -
  131.58 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  131.59 -public class AbstractLookupTest extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
  131.60 -    public AbstractLookupTest(java.lang.String testName) {
  131.61 -        super(testName, null);
  131.62 -    }
  131.63 -
  131.64 -    //
  131.65 -    // Impl of AbstractLookupBaseHid.Impl
  131.66 -    //
  131.67 -
  131.68 -    /** Creates the initial abstract lookup.
  131.69 -     */
  131.70 -    public Lookup createInstancesLookup (InstanceContent ic) {
  131.71 -        return new AbstractLookup (ic, new InheritanceTree ());
  131.72 -    }
  131.73 -    
  131.74 -    /** Creates an lookup for given lookup. This class just returns 
  131.75 -     * the object passed in, but subclasses can be different.
  131.76 -     * @param lookup in lookup
  131.77 -     * @return a lookup to use
  131.78 -     */
  131.79 -    public Lookup createLookup (Lookup lookup) {
  131.80 -        return lookup;
  131.81 -    }
  131.82 -
  131.83 -    public void clearCaches () {
  131.84 -    }    
  131.85 -
  131.86 -    static class LkpResultCanBeGargageCollectedAndClearsTheResult extends AbstractLookup {
  131.87 -        public int cleared;
  131.88 -        public int dirty;
  131.89 -
  131.90 -        synchronized @Override boolean cleanUpResult(Template t) {
  131.91 -            boolean res = super.cleanUpResult (t);
  131.92 -            if (res) {
  131.93 -                cleared++;
  131.94 -            } else {
  131.95 -                dirty++;
  131.96 -            }
  131.97 -
  131.98 -            notifyAll ();
  131.99 -
 131.100 -            return res;
 131.101 -        }
 131.102 -    }
 131.103 -    public void testResultCanBeGargageCollectedAndClearsTheResult () throws Exception {
 131.104 -        LkpResultCanBeGargageCollectedAndClearsTheResult lkp = new LkpResultCanBeGargageCollectedAndClearsTheResult ();
 131.105 -        assertSize ("24 for AbstractLookup, 8 for two ints", 32, lkp);
 131.106 -        synchronized (lkp) {
 131.107 -            Lookup.Result res = lkp.lookup (new Lookup.Template (getClass ()));
 131.108 -            res.allItems();
 131.109 -            
 131.110 -            WeakReference ref = new WeakReference (res);
 131.111 -            res = null;
 131.112 -            assertGC ("Reference can get cleared", ref);
 131.113 -         
 131.114 -            // wait till we 
 131.115 -            while (lkp.cleared == 0 && lkp.dirty == 0) {
 131.116 -                lkp.wait ();
 131.117 -            }
 131.118 -            
 131.119 -            assertEquals ("No dirty cleanups", 0, lkp.dirty);
 131.120 -            assertEquals ("One final cleanup", 1, lkp.cleared);
 131.121 -        }
 131.122 -        //assertSize ("Everything has been cleaned to original size", 32, lkp);
 131.123 -        
 131.124 -    }
 131.125 -    
 131.126 -    public void testPairCannotBeUsedInMoreThanOneLookupAtOnce () throws Exception {
 131.127 -        /** Simple pair with no data */
 131.128 -        class EmptyPair extends AbstractLookup.Pair {
 131.129 -            protected boolean creatorOf(Object obj) { return false; }
 131.130 -            public String getDisplayName() { return "Empty"; }
 131.131 -            public String getId() { return "empty"; }
 131.132 -            public Object getInstance() { return null; }
 131.133 -            public Class getType() { return Object.class; }
 131.134 -            protected boolean instanceOf(Class c) { return c == getType (); }
 131.135 -        } // end of EmptyPair
 131.136 -        
 131.137 -        AbstractLookup.Content c1 = new AbstractLookup.Content ();
 131.138 -        AbstractLookup.Content c2 = new AbstractLookup.Content ();
 131.139 -        AbstractLookup l1 = new AbstractLookup (c1);
 131.140 -        AbstractLookup l2 = new AbstractLookup (c2);
 131.141 -        
 131.142 -        EmptyPair empty = new EmptyPair ();
 131.143 -        c1.addPair (empty);
 131.144 -        Lookup.Result res = l1.lookup (new Lookup.Template (Object.class));
 131.145 -        assertEquals (
 131.146 -            "Pair is really found", empty, 
 131.147 -            res.allItems ().iterator().next ()
 131.148 -        );
 131.149 -        try {
 131.150 -            c2.addPair (empty);
 131.151 -            fail ("It should not be possible to add pair to two lookups");
 131.152 -        } catch (IllegalStateException ex) {
 131.153 -            // ok, exception is fine
 131.154 -        }
 131.155 -        assertEquals (
 131.156 -            "L2 is still empty", Collections.EMPTY_LIST, 
 131.157 -            new ArrayList (l2.lookup (new Lookup.Template (Object.class)).allItems ())
 131.158 -        );
 131.159 -    }
 131.160 -    
 131.161 -    public void testInitializationCanBeDoneFromAnotherThread () {
 131.162 -        class MyLkp extends AbstractLookup implements Runnable {
 131.163 -            private InstanceContent ic;
 131.164 -            private boolean direct;
 131.165 -            
 131.166 -            public MyLkp (boolean direct) {
 131.167 -                this (direct, new InstanceContent ());
 131.168 -            }
 131.169 -                
 131.170 -            private MyLkp (boolean direct, InstanceContent ic) {
 131.171 -                super (ic);
 131.172 -                this.direct = direct;
 131.173 -                this.ic = ic;
 131.174 -            }
 131.175 -            
 131.176 -            protected @Override void initialize() {
 131.177 -                if (direct) {
 131.178 -                    run ();
 131.179 -                } else {
 131.180 -                    try {
 131.181 -                        Executors.newSingleThreadScheduledExecutor().schedule(this, 0, TimeUnit.MICROSECONDS).get();
 131.182 -                    } catch (InterruptedException ex) {
 131.183 -                        ex.printStackTrace();
 131.184 -                    } catch (ExecutionException ex) {
 131.185 -                        ex.printStackTrace();
 131.186 -                    }
 131.187 -                }
 131.188 -            }
 131.189 -            
 131.190 -            public void run () {
 131.191 -                ic.add (this);
 131.192 -                ic.remove (this);
 131.193 -                ic.set (Collections.nCopies(10, this), null);
 131.194 -                ic.set (Collections.EMPTY_LIST, null);
 131.195 -                ic.add (AbstractLookupTest.this);
 131.196 -            }
 131.197 -        }
 131.198 -        
 131.199 -        assertEquals ("The test should be there", this, new MyLkp (true).lookup (Object.class));
 131.200 -        assertEquals ("and in async mode as well", this, new MyLkp (false).lookup (Object.class));
 131.201 -    }
 131.202 -    
 131.203 -    public void testBeforeLookupIsCalled () {
 131.204 -        class BeforeL extends AbstractLookup {
 131.205 -            public ArrayList list = new ArrayList ();
 131.206 -            public String toAdd;
 131.207 -            public InstanceContent ic;
 131.208 -            
 131.209 -            public BeforeL () {
 131.210 -                this (new InstanceContent ());
 131.211 -            }
 131.212 -            
 131.213 -            private BeforeL (InstanceContent c) {
 131.214 -                super (c);
 131.215 -                this.ic = c;
 131.216 -            }
 131.217 -        
 131.218 -            protected @Override void beforeLookup(Template t) {
 131.219 -                if (toAdd != null) {
 131.220 -                    list.add (0, new SerialPair (toAdd));
 131.221 -                    setPairs (list);
 131.222 -                } else {
 131.223 -                    ic.add (new Integer (1));
 131.224 -                }
 131.225 -            }
 131.226 -        }
 131.227 -        
 131.228 -        BeforeL lookup = new BeforeL ();
 131.229 -        
 131.230 -        lookup.toAdd = "First";
 131.231 -        assertEquals ("First if found", "First", lookup.lookup (String.class));
 131.232 -        
 131.233 -        lookup.toAdd = "2";
 131.234 -        assertEquals ("2 is not first", "2", lookup.lookup (String.class));
 131.235 -        
 131.236 -        Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
 131.237 -        for (int i = 3; i < 20; i++) {
 131.238 -            lookup.toAdd = String.valueOf (i);
 131.239 -            assertEquals (i + " items are now there", i, res.allInstances ().size ());
 131.240 -        }
 131.241 -        for (int i = 20; i < 35; i++) {
 131.242 -            lookup.toAdd = String.valueOf (i);
 131.243 -            assertEquals (i + " items are now there", i, res.allItems ().size ());
 131.244 -        }
 131.245 -        
 131.246 -        assertEquals ("Just strings are there now", 1, res.allClasses ().size ());
 131.247 -        lookup.toAdd = null; // this will add integer
 131.248 -        assertEquals ("Two classes now", 2, res.allClasses ().size ());
 131.249 -    }
 131.250 -
 131.251 -    public void testInconsistentAfterDeserIssue71744() throws Exception {
 131.252 -        InheritanceTree inhTree = new InheritanceTree();
 131.253 -
 131.254 -        AbstractLookup al = new AbstractLookup(new AbstractLookup.Content(), inhTree);
 131.255 -        {
 131.256 -
 131.257 -            Collection r = al.lookup(new Lookup.Template(Integer.class)).allInstances();
 131.258 -            assertEquals("None", 0, r.size());
 131.259 -        }
 131.260 -
 131.261 -        ICP item = new ICP(new Integer(10));
 131.262 -        al.addPair(item);
 131.263 -        al.removePair(item);
 131.264 -
 131.265 -        AbstractLookup newLookup = (AbstractLookup)reserialize(al);
 131.266 -
 131.267 -        newLookup.lookup(Number.class);
 131.268 -
 131.269 -
 131.270 -        newLookup.addPair(new ICP(new Long(20)));
 131.271 -
 131.272 -        {
 131.273 -
 131.274 -            Collection r = newLookup.lookup(new Lookup.Template(Number.class)).allInstances();
 131.275 -            assertEquals("one", 1, r.size());
 131.276 -/*
 131.277 -            Iterator it = r.iterator();
 131.278 -            assertEquals(new Integer(10), it.next());
 131.279 -            assertEquals(new Long(20), it.next());*/
 131.280 -        }
 131.281 -    }
 131.282 -
 131.283 -    public void testMatchesIssue130673() {
 131.284 -        class BrokenPairReturningNullID extends Pair<Object> {
 131.285 -            @Override
 131.286 -            protected boolean instanceOf(Class<?> c) {
 131.287 -                return false;
 131.288 -            }
 131.289 -
 131.290 -            @Override
 131.291 -            protected boolean creatorOf(Object obj) {
 131.292 -                return false;
 131.293 -            }
 131.294 -
 131.295 -            @Override
 131.296 -            public Object getInstance() {
 131.297 -                return null;
 131.298 -            }
 131.299 -
 131.300 -            @Override
 131.301 -            public Class<? extends Object> getType() {
 131.302 -                return null;
 131.303 -            }
 131.304 -
 131.305 -            @Override
 131.306 -            public String getId() {
 131.307 -                return null;
 131.308 -            }
 131.309 -
 131.310 -            @Override
 131.311 -            public String getDisplayName() {
 131.312 -                return null;
 131.313 -            }
 131.314 -        }
 131.315 -        BrokenPairReturningNullID broken = new BrokenPairReturningNullID();
 131.316 -        
 131.317 -        
 131.318 -        Lookup.Template<String> t = new Lookup.Template<String>(String.class, "ID", null);
 131.319 -        boolean not = AbstractLookup.matches(t, broken, true);
 131.320 -        assertFalse("Does not match the template, but throws no exception", not);
 131.321 -    }
 131.322 -    
 131.323 -    private static final class ICP extends AbstractLookup.Pair {
 131.324 -        private Number s;
 131.325 -
 131.326 -        public ICP (Number s) {
 131.327 -            this.s = s;
 131.328 -        }
 131.329 -
 131.330 -
 131.331 -        protected boolean instanceOf(Class c) {
 131.332 -            return c.isInstance(s);
 131.333 -        }
 131.334 -
 131.335 -        protected boolean creatorOf(Object obj) {
 131.336 -            return s == obj;
 131.337 -        }
 131.338 -
 131.339 -        public Object getInstance() {
 131.340 -            return s;
 131.341 -        }
 131.342 -
 131.343 -        public Class getType() {
 131.344 -            return s.getClass();
 131.345 -        }
 131.346 -
 131.347 -        public String getId() {
 131.348 -            return s.toString();
 131.349 -        }
 131.350 -
 131.351 -        public String getDisplayName() {
 131.352 -            return getId();
 131.353 -        }
 131.354 -
 131.355 -    }
 131.356 -}
   132.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   132.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.3 @@ -1,228 +0,0 @@
   132.4 -/*
   132.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   132.6 - *
   132.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   132.8 - *
   132.9 - * The contents of this file are subject to the terms of either the GNU
  132.10 - * General Public License Version 2 only ("GPL") or the Common
  132.11 - * Development and Distribution License("CDDL") (collectively, the
  132.12 - * "License"). You may not use this file except in compliance with the
  132.13 - * License. You can obtain a copy of the License at
  132.14 - * http://www.netbeans.org/cddl-gplv2.html
  132.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  132.16 - * specific language governing permissions and limitations under the
  132.17 - * License.  When distributing the software, include this License Header
  132.18 - * Notice in each file and include the License file at
  132.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  132.20 - * particular file as subject to the "Classpath" exception as provided
  132.21 - * by Sun in the GPL Version 2 section of the License file that
  132.22 - * accompanied this code. If applicable, add the following below the
  132.23 - * License Header, with the fields enclosed by brackets [] replaced by
  132.24 - * your own identifying information:
  132.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  132.26 - *
  132.27 - * Contributor(s):
  132.28 - *
  132.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  132.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  132.31 - * Microsystems, Inc. All Rights Reserved.
  132.32 - *
  132.33 - * If you wish your version of this file to be governed by only the CDDL
  132.34 - * or only the GPL Version 2, indicate your decision by adding
  132.35 - * "[Contributor] elects to include this software in this distribution
  132.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  132.37 - * single choice of license, a recipient has the option to distribute
  132.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  132.39 - * to extend the choice of license to its licensees as provided above.
  132.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  132.41 - * Version 2 license, then the option applies only if the new code is
  132.42 - * made subject to such option by the copyright holder.
  132.43 - */
  132.44 -
  132.45 -package org.openide.util.lookup;
  132.46 -
  132.47 -import java.util.*;
  132.48 -import org.openide.util.Lookup;
  132.49 -
  132.50 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
  132.51 - */
  132.52 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  132.53 -public class ExcludingLookupTest extends AbstractLookupBaseHid
  132.54 -implements AbstractLookupBaseHid.Impl {
  132.55 -    public ExcludingLookupTest(java.lang.String testName) {
  132.56 -        super(testName, null);
  132.57 -    }
  132.58 -
  132.59 -    public Lookup createLookup (final Lookup lookup) {
  132.60 -        return Lookups.exclude (lookup, new Class[0]);
  132.61 -    }
  132.62 -    
  132.63 -    public Lookup createInstancesLookup (InstanceContent ic) {
  132.64 -        return new AbstractLookup (ic);
  132.65 -    }
  132.66 -
  132.67 -    public void clearCaches () {
  132.68 -    }    
  132.69 -    
  132.70 -    public void testWeCanRemoveInteger () throws Exception {
  132.71 -        doBasicFilteringTest (Integer.class, Integer.class, 0);
  132.72 -    }
  132.73 -    
  132.74 -    public void testWeCanRemoveIntegersEvenByAskingForRemoveOfAllNumbers () throws Exception {
  132.75 -        doBasicFilteringTest (Number.class, Integer.class, 0);
  132.76 -    }
  132.77 -    public void testFunWithInterfaces () throws Exception {
  132.78 -        doBasicFilteringTest (java.io.Serializable.class, Integer.class, 0);
  132.79 -    }
  132.80 -    
  132.81 -    public void testWeCanGetInstanceOfSerializableEvenItIsExcludedIfWeAskForClassNotExtendingIt () throws Exception {
  132.82 -        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { java.io.Serializable.class });
  132.83 -        Lookup.Template t = new Lookup.Template (Object.class);
  132.84 -        Lookup.Result res = lookup.lookup (t);
  132.85 -        
  132.86 -        LL ll = new LL ();
  132.87 -        res.addLookupListener (ll);
  132.88 -        assertEquals ("Nothing is there", 0, res.allItems ().size ());
  132.89 -        
  132.90 -        Object inst = new Integer (3);
  132.91 -        ic.add (inst);
  132.92 -        
  132.93 -        assertEquals ("Not Filtered out", inst, lookup.lookup (Object.class));
  132.94 -        assertEquals ("Not Filtered out2", inst, lookup.lookupItem (t).getInstance ());
  132.95 -        assertEquals ("One is there - 2", 1, res.allItems ().size ());
  132.96 -        assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
  132.97 -        assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
  132.98 -        assertEquals ("Right # of events", 1, ll.getCount ());
  132.99 -        
 132.100 -        ic.remove (inst);
 132.101 -        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
 132.102 -        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
 132.103 -        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
 132.104 -        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
 132.105 -        assertEquals ("Of course it is not there", null, lookup.lookup (Object.class));
 132.106 -        assertEquals ("Right # of events", 1, ll.getCount ());
 132.107 -    }
 132.108 -    
 132.109 -    public void testIntegersQueriedThruObject () throws Exception {
 132.110 -        doBasicFilteringTest (Number.class, Object.class, 1);
 132.111 -    }
 132.112 -    
 132.113 -    private void doBasicFilteringTest (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
 132.114 -        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
 132.115 -        Lookup.Template t = new Lookup.Template (theQuery);
 132.116 -        Lookup.Result res = lookup.lookup (t);
 132.117 -        
 132.118 -        LL ll = new LL ();
 132.119 -        res.addLookupListener (ll);
 132.120 -        assertEquals ("Nothing is there", 0, res.allItems ().size ());
 132.121 -        
 132.122 -        Object inst = new Integer (3);
 132.123 -        ic.add (inst);
 132.124 -        
 132.125 -        assertEquals ("Filtered out", null, lookup.lookup (theQuery));
 132.126 -        assertEquals ("Filtered out2", null, lookup.lookupItem (t));
 132.127 -        assertEquals ("Nothing is there - 2", 0, res.allItems ().size ());
 132.128 -        assertEquals ("Nothing is there - 2a", 0, res.allInstances ().size ());
 132.129 -        assertEquals ("Nothing is there - 2b", 0, res.allClasses ().size ());
 132.130 -        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
 132.131 -        
 132.132 -        ic.remove (inst);
 132.133 -        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
 132.134 -        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
 132.135 -        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
 132.136 -        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
 132.137 -        assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
 132.138 -        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
 132.139 -        
 132.140 -    }
 132.141 -    
 132.142 -    public void testSizeOfTheLookup () throws Exception {
 132.143 -        Class exclude = String.class;
 132.144 -        
 132.145 -        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { exclude });
 132.146 -
 132.147 -        assertSize ("Should be pretty lightweight", Collections.singleton (lookup), 16, 
 132.148 -                new Object[] { this.instanceLookup, exclude });
 132.149 -    }
 132.150 -    public void testSizeOfTheLookupForMultipleFiltersIsHigher () throws Exception {
 132.151 -        Class exclude = String.class;
 132.152 -        Class exclude2 = Integer.class;
 132.153 -        Class[] arr = new Class[] { exclude, exclude2 };
 132.154 -        
 132.155 -        Lookup lookup = Lookups.exclude (this.instanceLookup, arr);
 132.156 -
 132.157 -        assertSize ("Is fatter", Collections.singleton (lookup), 40, 
 132.158 -                new Object[] { this.instanceLookup, exclude, exclude2 });
 132.159 -        assertSize ("But only due to the array", Collections.singleton (lookup), 16, 
 132.160 -                new Object[] { this.instanceLookup, exclude, exclude2, arr });
 132.161 -    }
 132.162 -    
 132.163 -    public void testFilteringOfSomething () throws Exception {
 132.164 -        doFilteringOfSomething (Runnable.class, java.io.Serializable.class, 1);
 132.165 -    }
 132.166 -    
 132.167 -    private void doFilteringOfSomething (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
 132.168 -        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
 132.169 -        Lookup.Template t = new Lookup.Template (theQuery);
 132.170 -        Lookup.Result res = lookup.lookup (t);
 132.171 -        
 132.172 -        LL ll = new LL ();
 132.173 -        res.addLookupListener (ll);
 132.174 -        assertEquals ("Nothing is there", 0, res.allItems ().size ());
 132.175 -        
 132.176 -        Object inst = new Integer (3);
 132.177 -        ic.add (inst);
 132.178 -        
 132.179 -        assertEquals ("Accepted", inst, lookup.lookup (theQuery));
 132.180 -        assertNotNull ("Accepted too", lookup.lookupItem (t));
 132.181 -        assertEquals ("One is there - 2", 1, res.allItems ().size ());
 132.182 -        assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
 132.183 -        assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
 132.184 -        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
 132.185 -
 132.186 -        Object inst2 = new Thread (); // implements Runnable
 132.187 -        ic.add (inst2);
 132.188 -        assertEquals ("Accepted - 2", inst, lookup.lookup (theQuery));
 132.189 -        assertNotNull ("Accepted too -2", lookup.lookupItem (t));
 132.190 -        assertEquals ("One is there - 3", 1, res.allItems ().size ());
 132.191 -        assertEquals ("One is there - 3a", 1, res.allInstances ().size ());
 132.192 -        assertEquals ("One is there - 3b", 1, res.allClasses ().size ());
 132.193 -        assertEquals ("Right # of events", 0, ll.getCount ());
 132.194 -        
 132.195 -        
 132.196 -        ic.remove (inst);
 132.197 -        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
 132.198 -        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
 132.199 -        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
 132.200 -        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
 132.201 -        assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
 132.202 -        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
 132.203 -    }
 132.204 -
 132.205 -    public void testTheBehaviourAsRequestedByDavidAndDescribedByJesse () throws Exception {
 132.206 -        class C implements Runnable, java.io.Serializable {
 132.207 -            public void run () {}
 132.208 -        }
 132.209 -        Object c = new C();
 132.210 -        Lookup l1 = Lookups.singleton(c);
 132.211 -        Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
 132.212 -        assertNull(l2.lookup(Runnable.class));
 132.213 -        assertEquals(c, l2.lookup(java.io.Serializable.class));
 132.214 -    }
 132.215 -    
 132.216 -    public void testTheBehaviourAsRequestedByDavidAndDescribedByJesseWithUsageOfResult () throws Exception {
 132.217 -        class C implements Runnable, java.io.Serializable {
 132.218 -            public void run () {}
 132.219 -        }
 132.220 -        Object c = new C();
 132.221 -        Lookup l1 = Lookups.singleton(c);
 132.222 -        Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
 132.223 -        
 132.224 -        Lookup.Result run = l2.lookup (new Lookup.Template (Runnable.class));
 132.225 -        Lookup.Result ser = l2.lookup (new Lookup.Template (java.io.Serializable.class));
 132.226 -        
 132.227 -        assertEquals ("Runnables filtered out", 0, run.allItems ().size ());
 132.228 -        assertEquals ("One serialiazble", 1, ser.allItems ().size ());
 132.229 -        assertEquals ("And it is c", c, ser.allInstances ().iterator ().next ());
 132.230 -    }
 132.231 -}
   133.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/InheritanceTreeTest.java	Thu Dec 10 19:23:25 2009 -0500
   133.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.3 @@ -1,77 +0,0 @@
   133.4 -/*
   133.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   133.6 - *
   133.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   133.8 - *
   133.9 - * The contents of this file are subject to the terms of either the GNU
  133.10 - * General Public License Version 2 only ("GPL") or the Common
  133.11 - * Development and Distribution License("CDDL") (collectively, the
  133.12 - * "License"). You may not use this file except in compliance with the
  133.13 - * License. You can obtain a copy of the License at
  133.14 - * http://www.netbeans.org/cddl-gplv2.html
  133.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  133.16 - * specific language governing permissions and limitations under the
  133.17 - * License.  When distributing the software, include this License Header
  133.18 - * Notice in each file and include the License file at
  133.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  133.20 - * particular file as subject to the "Classpath" exception as provided
  133.21 - * by Sun in the GPL Version 2 section of the License file that
  133.22 - * accompanied this code. If applicable, add the following below the
  133.23 - * License Header, with the fields enclosed by brackets [] replaced by
  133.24 - * your own identifying information:
  133.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  133.26 - *
  133.27 - * Contributor(s):
  133.28 - *
  133.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  133.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  133.31 - * Microsystems, Inc. All Rights Reserved.
  133.32 - *
  133.33 - * If you wish your version of this file to be governed by only the CDDL
  133.34 - * or only the GPL Version 2, indicate your decision by adding
  133.35 - * "[Contributor] elects to include this software in this distribution
  133.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  133.37 - * single choice of license, a recipient has the option to distribute
  133.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  133.39 - * to extend the choice of license to its licensees as provided above.
  133.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  133.41 - * Version 2 license, then the option applies only if the new code is
  133.42 - * made subject to such option by the copyright holder.
  133.43 - */
  133.44 -package org.openide.util.lookup;
  133.45 -
  133.46 -import junit.framework.TestCase;
  133.47 -import junit.framework.*;
  133.48 -import org.openide.util.Lookup;
  133.49 -import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
  133.50 -import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
  133.51 -import java.io.*;
  133.52 -import java.lang.ref.WeakReference;
  133.53 -import java.util.*;
  133.54 -
  133.55 -/**
  133.56 - *
  133.57 - * @author Jaroslav Tulach
  133.58 - */
  133.59 -public class InheritanceTreeTest extends TestCase {
  133.60 -
  133.61 -    public InheritanceTreeTest(String testName) {
  133.62 -        super(testName);
  133.63 -    }
  133.64 -
  133.65 -    protected void setUp() throws Exception {
  133.66 -    }
  133.67 -
  133.68 -    protected void tearDown() throws Exception {
  133.69 -    }
  133.70 -
  133.71 -    public void testDeserOfNode() {
  133.72 -        InheritanceTree inh = new InheritanceTree();
  133.73 -        InheritanceTree.Node n = new InheritanceTree.Node(String.class);
  133.74 -        n.markDeserialized();
  133.75 -        n.markDeserialized();
  133.76 -
  133.77 -        n.assignItem(inh, new InstanceContent.SimpleItem("Ahoj"));
  133.78 -    }
  133.79 -    
  133.80 -}
   134.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/InitializationBug44134Test.java	Thu Dec 10 19:23:25 2009 -0500
   134.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.3 @@ -1,126 +0,0 @@
   134.4 -/*
   134.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   134.6 - *
   134.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   134.8 - *
   134.9 - * The contents of this file are subject to the terms of either the GNU
  134.10 - * General Public License Version 2 only ("GPL") or the Common
  134.11 - * Development and Distribution License("CDDL") (collectively, the
  134.12 - * "License"). You may not use this file except in compliance with the
  134.13 - * License. You can obtain a copy of the License at
  134.14 - * http://www.netbeans.org/cddl-gplv2.html
  134.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  134.16 - * specific language governing permissions and limitations under the
  134.17 - * License.  When distributing the software, include this License Header
  134.18 - * Notice in each file and include the License file at
  134.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  134.20 - * particular file as subject to the "Classpath" exception as provided
  134.21 - * by Sun in the GPL Version 2 section of the License file that
  134.22 - * accompanied this code. If applicable, add the following below the
  134.23 - * License Header, with the fields enclosed by brackets [] replaced by
  134.24 - * your own identifying information:
  134.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  134.26 - *
  134.27 - * Contributor(s):
  134.28 - *
  134.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  134.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  134.31 - * Microsystems, Inc. All Rights Reserved.
  134.32 - *
  134.33 - * If you wish your version of this file to be governed by only the CDDL
  134.34 - * or only the GPL Version 2, indicate your decision by adding
  134.35 - * "[Contributor] elects to include this software in this distribution
  134.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  134.37 - * single choice of license, a recipient has the option to distribute
  134.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  134.39 - * to extend the choice of license to its licensees as provided above.
  134.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  134.41 - * Version 2 license, then the option applies only if the new code is
  134.42 - * made subject to such option by the copyright holder.
  134.43 - */
  134.44 -
  134.45 -package org.openide.util.lookup;
  134.46 -
  134.47 -import java.util.*;
  134.48 -import org.netbeans.junit.*;
  134.49 -import org.openide.util.Lookup;
  134.50 -
  134.51 -public class InitializationBug44134Test extends NbTestCase {
  134.52 -    public InitializationBug44134Test (java.lang.String testName) {
  134.53 -        super(testName);
  134.54 -    }
  134.55 -
  134.56 -    public static void main(java.lang.String[] args) {
  134.57 -        junit.textui.TestRunner.run(new NbTestSuite(InitializationBug44134Test.class));
  134.58 -    }
  134.59 -
  134.60 -    public void testThereShouldBe18Integers () throws Exception {
  134.61 -        FooManifestLookup foo = new FooManifestLookup ();
  134.62 -        
  134.63 -        Collection items = foo.lookup (new Lookup.Template (Integer.class)).allItems ();
  134.64 -        
  134.65 -        assertEquals ("18 of them", 18, items.size ());
  134.66 -        
  134.67 -        Iterator it = items.iterator ();
  134.68 -        while (it.hasNext()) {
  134.69 -            Lookup.Item t = (Lookup.Item)it.next ();
  134.70 -            assertEquals ("Is Integer", Integer.class, t.getInstance ().getClass ());
  134.71 -        }
  134.72 -    }
  134.73 -
  134.74 -    
  134.75 -    public class FooManifestLookup extends AbstractLookup {
  134.76 -        public FooManifestLookup() {
  134.77 -            super();
  134.78 -        }
  134.79 -        
  134.80 -        @Override
  134.81 -        protected void initialize() {
  134.82 -            for (int i=0; i<18; i++) {
  134.83 -                try {
  134.84 -                    String id= "__" + i;
  134.85 -                    
  134.86 -                    addPair(new FooLookupItem(new Integer(i),id));
  134.87 -                }
  134.88 -                catch (Exception e) {
  134.89 -                }
  134.90 -            }
  134.91 -        }
  134.92 -        
  134.93 -        public class FooLookupItem extends AbstractLookup.Pair {
  134.94 -            public FooLookupItem(Integer data, String id) {
  134.95 -                super();
  134.96 -                this.data=data;
  134.97 -                this.id=id;
  134.98 -            }
  134.99 -            
 134.100 -            protected boolean creatorOf(Object obj) {
 134.101 -                return obj == data;
 134.102 -            }
 134.103 -            
 134.104 -            public String getDisplayName() {
 134.105 -                return data.toString();
 134.106 -            }
 134.107 -            
 134.108 -            public Class getType () {
 134.109 -                return Integer.class;
 134.110 -            }
 134.111 -            
 134.112 -            protected boolean instanceOf (Class c) {
 134.113 -                return c.isInstance(data);
 134.114 -            }
 134.115 -            
 134.116 -            public Object getInstance() {
 134.117 -                return data;
 134.118 -            }
 134.119 -            
 134.120 -            public String getId() {
 134.121 -                return id;
 134.122 -            }
 134.123 -            
 134.124 -            private Integer data;
 134.125 -            private String id;
 134.126 -        }
 134.127 -    }
 134.128 -    
 134.129 -}
   135.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/KomrskaLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   135.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.3 @@ -1,177 +0,0 @@
   135.4 -/*
   135.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   135.6 - *
   135.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
   135.8 - *
   135.9 - * The contents of this file are subject to the terms of either the GNU
  135.10 - * General Public License Version 2 only ("GPL") or the Common
  135.11 - * Development and Distribution License("CDDL") (collectively, the
  135.12 - * "License"). You may not use this file except in compliance with the
  135.13 - * License. You can obtain a copy of the License at
  135.14 - * http://www.netbeans.org/cddl-gplv2.html
  135.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  135.16 - * specific language governing permissions and limitations under the
  135.17 - * License.  When distributing the software, include this License Header
  135.18 - * Notice in each file and include the License file at
  135.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  135.20 - * particular file as subject to the "Classpath" exception as provided
  135.21 - * by Sun in the GPL Version 2 section of the License file that
  135.22 - * accompanied this code. If applicable, add the following below the
  135.23 - * License Header, with the fields enclosed by brackets [] replaced by
  135.24 - * your own identifying information:
  135.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  135.26 - *
  135.27 - * If you wish your version of this file to be governed by only the CDDL
  135.28 - * or only the GPL Version 2, indicate your decision by adding
  135.29 - * "[Contributor] elects to include this software in this distribution
  135.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  135.31 - * single choice of license, a recipient has the option to distribute
  135.32 - * your version of this file under either the CDDL, the GPL Version 2 or
  135.33 - * to extend the choice of license to its licensees as provided above.
  135.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  135.35 - * Version 2 license, then the option applies only if the new code is
  135.36 - * made subject to such option by the copyright holder.
  135.37 - *
  135.38 - * Contributor(s):
  135.39 - *
  135.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  135.41 - */
  135.42 -package org.openide.util.lookup;
  135.43 -
  135.44 -import org.junit.After;
  135.45 -import org.junit.Before;
  135.46 -import org.junit.Test;
  135.47 -import org.openide.util.Lookup;
  135.48 -import org.openide.util.LookupEvent;
  135.49 -import org.openide.util.LookupListener;
  135.50 -import static org.junit.Assert.*;
  135.51 -
  135.52 -/**
  135.53 - * Test donated by Mr. Komrska. Seems to pass with 6.5.
  135.54 - * @author komrska
  135.55 - */
  135.56 -public final class KomrskaLookupTest {
  135.57 -    private TestLookupManager lookupManager=null;
  135.58 -    private StringBuffer result=null;
  135.59 -    
  135.60 -    //
  135.61 -    
  135.62 -    private void addToLookup(final TestLookupItemA object) {
  135.63 -        result.append('A');
  135.64 -        lookupManager.add(object);
  135.65 -    }
  135.66 -    private void removeFromLookup(final TestLookupItemA object) {
  135.67 -        result.append('A');
  135.68 -        lookupManager.remove(object);
  135.69 -    }
  135.70 -
  135.71 -    private void addToLookup(final TestLookupItemB object) {
  135.72 -        result.append('B');
  135.73 -        lookupManager.add(object);
  135.74 -    }
  135.75 -    private void removeFromLookup(final TestLookupItemB object) {
  135.76 -        result.append('B');
  135.77 -        lookupManager.remove(object);
  135.78 -    }
  135.79 -    
  135.80 -    public String getResult() {
  135.81 -        return result.toString();
  135.82 -    }
  135.83 -    
  135.84 -    //
  135.85 -
  135.86 -    @Before
  135.87 -    public void setUp() {
  135.88 -        lookupManager=new TestLookupManager();
  135.89 -        result=new StringBuffer();
  135.90 -    }
  135.91 -    
  135.92 -    @After
  135.93 -    public void tearDown() {
  135.94 -        lookupManager=null;
  135.95 -        result=null;
  135.96 -    }
  135.97 -    
  135.98 -    @Test
  135.99 -    public void testLookupBug() {
 135.100 -        TestLookupItemA itemA1=new TestLookupItemA();
 135.101 -        TestLookupItemB itemB1=new TestLookupItemB();
 135.102 -        //
 135.103 -        addToLookup(itemA1);
 135.104 -        addToLookup(itemB1);
 135.105 -        removeFromLookup(itemA1);
 135.106 -        removeFromLookup(itemB1);
 135.107 -        addToLookup(itemB1);
 135.108 -        removeFromLookup(itemB1);
 135.109 -        //
 135.110 -        addToLookup(itemA1);
 135.111 -        addToLookup(itemB1);
 135.112 -        removeFromLookup(itemA1);
 135.113 -        removeFromLookup(itemB1);
 135.114 -        addToLookup(itemB1);
 135.115 -        removeFromLookup(itemB1);
 135.116 -        //
 135.117 -        addToLookup(itemA1);
 135.118 -        addToLookup(itemB1);
 135.119 -        removeFromLookup(itemA1);
 135.120 -        removeFromLookup(itemB1);
 135.121 -        addToLookup(itemB1);
 135.122 -        removeFromLookup(itemB1);
 135.123 -        //
 135.124 -        assertEquals(getResult(),lookupManager.getResult());
 135.125 -    }
 135.126 -
 135.127 -    public static final class TestLookupItemA {}
 135.128 -    public static final class TestLookupItemB {}
 135.129 -    public static final class TestLookupManager {
 135.130 -        private InstanceContent instanceContent=new InstanceContent();
 135.131 -        private AbstractLookup abstractLookup=new AbstractLookup(instanceContent);
 135.132 -
 135.133 -        private Lookup.Result<TestLookupItemA> resultA=null;
 135.134 -        private Lookup.Result<TestLookupItemB> resultB=null;
 135.135 -
 135.136 -        private LookupListener listenerA=new LookupListener() {
 135.137 -            public void resultChanged(LookupEvent event) {
 135.138 -                result.append('A');
 135.139 -            }
 135.140 -        };
 135.141 -        private LookupListener listenerB=new LookupListener() {
 135.142 -            public void resultChanged(LookupEvent event) {
 135.143 -                result.append('B');
 135.144 -            }
 135.145 -        };
 135.146 -
 135.147 -        private StringBuffer result=new StringBuffer();
 135.148 -
 135.149 -        //
 135.150 -
 135.151 -        public TestLookupManager() {
 135.152 -            Lookup.Template<TestLookupItemA> templateA=
 135.153 -                new Lookup.Template<TestLookupItemA>(TestLookupItemA.class);
 135.154 -            resultA=abstractLookup.lookup(templateA);
 135.155 -            resultA.addLookupListener(listenerA);
 135.156 -            resultA.allInstances().size();
 135.157 -            //
 135.158 -            Lookup.Template<TestLookupItemB> templateB=
 135.159 -                new Lookup.Template<TestLookupItemB>(TestLookupItemB.class);
 135.160 -            resultB=abstractLookup.lookup(templateB);
 135.161 -            resultB.addLookupListener(listenerB);
 135.162 -            resultB.allInstances().size();
 135.163 -            // WORKAROUND
 135.164 -            // instanceContent.add(Boolean.TRUE);
 135.165 -        }
 135.166 -
 135.167 -        //
 135.168 -
 135.169 -        public void add(Object item) {
 135.170 -            instanceContent.add(item);
 135.171 -        }
 135.172 -        public void remove(Object item) {
 135.173 -            instanceContent.remove(item);
 135.174 -        }
 135.175 -        public String getResult() {
 135.176 -            return result.toString();
 135.177 -        }
 135.178 -    }
 135.179 -
 135.180 -}
   136.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/LookupBugTest.java	Thu Dec 10 19:23:25 2009 -0500
   136.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.3 @@ -1,79 +0,0 @@
   136.4 -package org.openide.util.lookup;
   136.5 -
   136.6 -import java.util.logging.Logger;
   136.7 -import org.junit.Before;
   136.8 -import org.junit.Test;
   136.9 -import org.openide.util.Lookup;
  136.10 -import org.openide.util.LookupEvent;
  136.11 -import org.openide.util.LookupListener;
  136.12 -import static org.junit.Assert.*;
  136.13 -
  136.14 -/**
  136.15 - * Test of a Lookup bug seen in NetBeans platforms 6.0-6.5M1.
  136.16 - * @author rlee
  136.17 - */
  136.18 -public class LookupBugTest implements LookupListener
  136.19 -{
  136.20 -    private static final int MAX_LOOPS = 1000;
  136.21 -    
  136.22 -    private AbstractLookup lookup;
  136.23 -    private InstanceContent content;
  136.24 -    private Lookup.Result<String> wordResult;
  136.25 -    private Lookup.Result<Integer> numberResult;
  136.26 -    private String word;
  136.27 -    private Integer number;
  136.28 -    private Logger LOG;
  136.29 -    
  136.30 -    private boolean fired;
  136.31 -    private int i;
  136.32 -
  136.33 -    @Before
  136.34 -    public void setUp()
  136.35 -    {
  136.36 -        LOG = Logger.getLogger("test.LookupBugTest");
  136.37 -        content = new InstanceContent();
  136.38 -        lookup = new AbstractLookup(content);
  136.39 -        wordResult = lookup.lookupResult(java.lang.String.class);
  136.40 -        wordResult.addLookupListener(this);
  136.41 -        numberResult = lookup.lookupResult(java.lang.Integer.class);
  136.42 -        numberResult.addLookupListener(this);
  136.43 -        
  136.44 -        fired = false;
  136.45 -    }
  136.46 -    
  136.47 -    @Test
  136.48 -    public void lookupTest()
  136.49 -    {
  136.50 -        for(i = 0; i < MAX_LOOPS; i++ )
  136.51 -        {
  136.52 -            word = String.valueOf(i);
  136.53 -            number = new Integer(i);
  136.54 -            content.add(word);
  136.55 -            assertTrue( "word on loop " + i, checkLookupEventFired() );
  136.56 -            content.add(number);
  136.57 -            assertTrue( "number on loop " + i, checkLookupEventFired() );
  136.58 -            content.remove(word);
  136.59 -            assertTrue( "remove word on loop " + i, checkLookupEventFired() );
  136.60 -            content.remove(number);
  136.61 -            assertTrue( "remove number on loop " + i, checkLookupEventFired() );
  136.62 -
  136.63 -            assertTrue("The lookup still needs to stay simple", AbstractLookup.isSimple(lookup));
  136.64 -        }
  136.65 -    }
  136.66 -
  136.67 -    public void resultChanged(LookupEvent ev)
  136.68 -    {
  136.69 -        fired = true;
  136.70 -    }
  136.71 -    
  136.72 -    public boolean checkLookupEventFired()
  136.73 -    {
  136.74 -        LOG.fine("  round: " + i + " word = " + word + " number = " + number);
  136.75 -        if( fired )
  136.76 -        {
  136.77 -            fired = false;
  136.78 -            return true;
  136.79 -        }
  136.80 -        else return false;
  136.81 -    }
  136.82 -}
   137.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/LookupsProxyTest.java	Thu Dec 10 19:23:25 2009 -0500
   137.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.3 @@ -1,282 +0,0 @@
   137.4 -/*
   137.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   137.6 - *
   137.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   137.8 - *
   137.9 - * The contents of this file are subject to the terms of either the GNU
  137.10 - * General Public License Version 2 only ("GPL") or the Common
  137.11 - * Development and Distribution License("CDDL") (collectively, the
  137.12 - * "License"). You may not use this file except in compliance with the
  137.13 - * License. You can obtain a copy of the License at
  137.14 - * http://www.netbeans.org/cddl-gplv2.html
  137.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  137.16 - * specific language governing permissions and limitations under the
  137.17 - * License.  When distributing the software, include this License Header
  137.18 - * Notice in each file and include the License file at
  137.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  137.20 - * particular file as subject to the "Classpath" exception as provided
  137.21 - * by Sun in the GPL Version 2 section of the License file that
  137.22 - * accompanied this code. If applicable, add the following below the
  137.23 - * License Header, with the fields enclosed by brackets [] replaced by
  137.24 - * your own identifying information:
  137.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  137.26 - *
  137.27 - * Contributor(s):
  137.28 - *
  137.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  137.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  137.31 - * Microsystems, Inc. All Rights Reserved.
  137.32 - *
  137.33 - * If you wish your version of this file to be governed by only the CDDL
  137.34 - * or only the GPL Version 2, indicate your decision by adding
  137.35 - * "[Contributor] elects to include this software in this distribution
  137.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  137.37 - * single choice of license, a recipient has the option to distribute
  137.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  137.39 - * to extend the choice of license to its licensees as provided above.
  137.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  137.41 - * Version 2 license, then the option applies only if the new code is
  137.42 - * made subject to such option by the copyright holder.
  137.43 - */
  137.44 -
  137.45 -package org.openide.util.lookup;
  137.46 -
  137.47 -import java.io.Serializable;
  137.48 -
  137.49 -import java.util.*;
  137.50 -import org.netbeans.junit.*;
  137.51 -import org.openide.util.Lookup;
  137.52 -import org.openide.util.LookupEvent;
  137.53 -import org.openide.util.LookupListener;
  137.54 -
  137.55 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
  137.56 - */
  137.57 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  137.58 -public class LookupsProxyTest extends AbstractLookupBaseHid
  137.59 -implements AbstractLookupBaseHid.Impl {
  137.60 -    public LookupsProxyTest(java.lang.String testName) {
  137.61 -        super(testName, null);
  137.62 -    }
  137.63 -
  137.64 -    public static void main(java.lang.String[] args) {
  137.65 -        junit.textui.TestRunner.run(new NbTestSuite (LookupsProxyTest.class));
  137.66 -    }
  137.67 -    
  137.68 -    /** Creates an lookup for given lookup. This class just returns 
  137.69 -     * the object passed in, but subclasses can be different.
  137.70 -     * @param lookup in lookup
  137.71 -     * @return a lookup to use
  137.72 -     */
  137.73 -    public Lookup createLookup (final Lookup lookup) {
  137.74 -        return org.openide.util.lookup.Lookups.proxy (
  137.75 -            new Lookup.Provider () {
  137.76 -                public Lookup getLookup () {
  137.77 -                    return lookup;
  137.78 -                }
  137.79 -            }
  137.80 -        );
  137.81 -    }
  137.82 -    
  137.83 -    public Lookup createInstancesLookup (InstanceContent ic) {
  137.84 -        return new AbstractLookup (ic);
  137.85 -    }
  137.86 -
  137.87 -    public void clearCaches () {
  137.88 -    }    
  137.89 -    
  137.90 -    
  137.91 -   
  137.92 -    /** Check whether setLookups method does not fire when there is no
  137.93 -     * change in the lookups.
  137.94 -     */
  137.95 -    public void testProxyListener () {
  137.96 -        Changer ch = new Changer (Lookup.EMPTY);
  137.97 -        
  137.98 -        Lookup lookup = Lookups.proxy(ch);
  137.99 -        Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
 137.100 -        
 137.101 -        LL ll = new LL ();
 137.102 -        res.addLookupListener (ll);
 137.103 -        Collection allRes = res.allInstances ();
 137.104 -
 137.105 -        ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
 137.106 -        lookup.lookup (Object.class); // does the refresh
 137.107 -        
 137.108 -        assertEquals("Replacing an empty by empty does not generate an event", 0, ll.getCount());
 137.109 -        
 137.110 -        InstanceContent content = new InstanceContent ();
 137.111 -        AbstractLookup del = new AbstractLookup (content);
 137.112 -        content.add (this);
 137.113 -        ch.setLookup (del);
 137.114 -        lookup.lookup (Object.class);
 137.115 -        
 137.116 -        if (ll.getCount () != 1) {
 137.117 -            fail ("Changing lookups with different content generates an event");
 137.118 -        }
 137.119 -        
 137.120 -        ch.setLookup (del);
 137.121 -        lookup.lookup (Object.class);
 137.122 -        
 137.123 -        if (ll.getCount () != 0) {
 137.124 -           fail ("Not changing the lookups does not generate any event");
 137.125 -        }
 137.126 -    }
 137.127 -
 137.128 -    
 137.129 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
 137.130 -        doListeningAndQueryingByTwoListenersSetLookups(0, 1, false);
 137.131 -    }
 137.132 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
 137.133 -        doListeningAndQueryingByTwoListenersSetLookups(1, 1, false);        
 137.134 -    }
 137.135 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
 137.136 -        doListeningAndQueryingByTwoListenersSetLookups(2, 1, false);
 137.137 -    }
 137.138 -    
 137.139 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
 137.140 -        doListeningAndQueryingByTwoListenersSetLookups(0, 2, false);
 137.141 -    }
 137.142 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
 137.143 -        doListeningAndQueryingByTwoListenersSetLookups(1, 2, false);        
 137.144 -    }
 137.145 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
 137.146 -        doListeningAndQueryingByTwoListenersSetLookups(2, 2, false);
 137.147 -    }
 137.148 -
 137.149 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookupsWithProxy() {
 137.150 -        doListeningAndQueryingByTwoListenersSetLookups(0, 1, true);
 137.151 -    }
 137.152 -    public void testListeningAndQueryingByTwoListenersClassesSetLookupsWithProxy() {
 137.153 -        doListeningAndQueryingByTwoListenersSetLookups(1, 1, true);        
 137.154 -    }
 137.155 -    public void testListeningAndQueryingByTwoListenersItemsSetLookupsWithProxy() {
 137.156 -        doListeningAndQueryingByTwoListenersSetLookups(2, 1, true);
 137.157 -    }
 137.158 -    
 137.159 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2WithProxy() {
 137.160 -        doListeningAndQueryingByTwoListenersSetLookups(0, 2, true);
 137.161 -    }
 137.162 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups2WithProxy() {
 137.163 -        doListeningAndQueryingByTwoListenersSetLookups(1, 2, true);        
 137.164 -    }
 137.165 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups2WithProxy() {
 137.166 -        doListeningAndQueryingByTwoListenersSetLookups(2, 2, true);
 137.167 -    }
 137.168 -    
 137.169 -    /* XXX: these are pretty slow, seems there is a performance problem 2^22
 137.170 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
 137.171 -        doListeningAndQueryingByTwoListenersSetLookups(0, 22);
 137.172 -    }
 137.173 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
 137.174 -        doListeningAndQueryingByTwoListenersSetLookups(1, 22);        
 137.175 -    }
 137.176 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
 137.177 -        doListeningAndQueryingByTwoListenersSetLookups(2, 22);
 137.178 -    }
 137.179 -     */
 137.180 -    
 137.181 -    private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth, boolean cacheOnTop) {
 137.182 -        Changer orig = new Changer(Lookup.EMPTY);
 137.183 -        Lookup on = Lookups.proxy(orig);
 137.184 -        Lookup first = on;
 137.185 -        
 137.186 -        while (--depth > 0) {
 137.187 -            Changer next = new Changer(on);
 137.188 -            on = Lookups.proxy(next);
 137.189 -        }
 137.190 -        
 137.191 -        
 137.192 -        final Lookup lookup = cacheOnTop ? new ProxyLookup(new Lookup[] { on }) : on;
 137.193 -        
 137.194 -        class L implements LookupListener {
 137.195 -            Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
 137.196 -            Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
 137.197 -            Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
 137.198 -            
 137.199 -            {
 137.200 -                integer.addLookupListener(this);
 137.201 -                number.addLookupListener(this);
 137.202 -                serial.addLookupListener(this);
 137.203 -            }
 137.204 -            
 137.205 -            int round;
 137.206 -            
 137.207 -            public void resultChanged(LookupEvent ev) {
 137.208 -                Collection c1 = get(type, integer);
 137.209 -                Collection c2 = get(type, number);
 137.210 -                Collection c3 = get(type, serial);
 137.211 -                
 137.212 -                assertEquals("round " + round + " c1 vs. c2", c1, c2);
 137.213 -                assertEquals("round " + round + " c1 vs. c3", c1, c3);
 137.214 -                assertEquals("round " + round + " c2 vs. c3", c2, c3);
 137.215 -                
 137.216 -                round++;
 137.217 -            }            
 137.218 -
 137.219 -            private Collection get(int type, Lookup.Result res) {
 137.220 -                Collection c;
 137.221 -                switch(type) {
 137.222 -                    case 0: c = res.allInstances(); break;
 137.223 -                    case 1: c = res.allClasses(); break;
 137.224 -                    case 2: c = res.allItems(); break;
 137.225 -                    default: c = null; fail("Type: " + type); break;
 137.226 -                }
 137.227 -                
 137.228 -                assertNotNull(c);
 137.229 -                return new ArrayList(c);
 137.230 -            }
 137.231 -        }
 137.232 -        
 137.233 -        L listener = new L();
 137.234 -        listener.resultChanged(null);
 137.235 -        ArrayList arr = new ArrayList();
 137.236 -        for(int i = 0; i < 100; i++) {
 137.237 -            arr.add(new Integer(i));
 137.238 -            
 137.239 -            orig.lookup = Lookups.fixed(arr.toArray());
 137.240 -            // do the refresh
 137.241 -            first.lookup((Class)null);
 137.242 -        }
 137.243 -        
 137.244 -        assertEquals("3x100+1 checks", 301, listener.round);
 137.245 -    }
 137.246 -    
 137.247 -    
 137.248 -    public void testRefreshWithoutAllInstances103300 () {
 137.249 -        Changer ch = new Changer (Lookup.EMPTY);
 137.250 -        
 137.251 -        Lookup lookup = Lookups.proxy(ch);
 137.252 -
 137.253 -        ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
 137.254 -        assertNull("Nothing there", lookup.lookup (Object.class)); // does the refresh
 137.255 -        
 137.256 -        InstanceContent content = new InstanceContent ();
 137.257 -        AbstractLookup del = new AbstractLookup (content);
 137.258 -        content.add (this);
 137.259 -        ch.setLookup (del);
 137.260 -        assertEquals("Can see me", this, lookup.lookup (Object.class));
 137.261 -        
 137.262 -        ch.setLookup (del);
 137.263 -        assertEquals("Still can see me", this, lookup.lookup (Object.class));
 137.264 -
 137.265 -        assertEquals("I am visible", this, lookup.lookup(LookupsProxyTest.class));
 137.266 -    }
 137.267 -
 137.268 -
 137.269 -    private static final class Changer implements Lookup.Provider {
 137.270 -        private Lookup lookup;
 137.271 -        
 137.272 -        public Changer (Lookup lookup) {
 137.273 -            setLookup (lookup);
 137.274 -        }
 137.275 -        
 137.276 -        public void setLookup (Lookup lookup) {
 137.277 -            this.lookup = lookup;
 137.278 -        }
 137.279 -        
 137.280 -        public Lookup getLookup() {
 137.281 -            return lookup;
 137.282 -        }
 137.283 -    }
 137.284 -
 137.285 -}
   138.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   138.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.3 @@ -1,535 +0,0 @@
   138.4 -/*
   138.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   138.6 - *
   138.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   138.8 - *
   138.9 - * The contents of this file are subject to the terms of either the GNU
  138.10 - * General Public License Version 2 only ("GPL") or the Common
  138.11 - * Development and Distribution License("CDDL") (collectively, the
  138.12 - * "License"). You may not use this file except in compliance with the
  138.13 - * License. You can obtain a copy of the License at
  138.14 - * http://www.netbeans.org/cddl-gplv2.html
  138.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  138.16 - * specific language governing permissions and limitations under the
  138.17 - * License.  When distributing the software, include this License Header
  138.18 - * Notice in each file and include the License file at
  138.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  138.20 - * particular file as subject to the "Classpath" exception as provided
  138.21 - * by Sun in the GPL Version 2 section of the License file that
  138.22 - * accompanied this code. If applicable, add the following below the
  138.23 - * License Header, with the fields enclosed by brackets [] replaced by
  138.24 - * your own identifying information:
  138.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  138.26 - *
  138.27 - * Contributor(s):
  138.28 - *
  138.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  138.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  138.31 - * Microsystems, Inc. All Rights Reserved.
  138.32 - *
  138.33 - * If you wish your version of this file to be governed by only the CDDL
  138.34 - * or only the GPL Version 2, indicate your decision by adding
  138.35 - * "[Contributor] elects to include this software in this distribution
  138.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  138.37 - * single choice of license, a recipient has the option to distribute
  138.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  138.39 - * to extend the choice of license to its licensees as provided above.
  138.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  138.41 - * Version 2 license, then the option applies only if the new code is
  138.42 - * made subject to such option by the copyright holder.
  138.43 - */
  138.44 -
  138.45 -package org.openide.util.lookup;
  138.46 -
  138.47 -import java.io.ByteArrayInputStream;
  138.48 -import java.io.File;
  138.49 -import java.io.FileOutputStream;
  138.50 -import java.io.IOException;
  138.51 -import java.io.InputStream;
  138.52 -import java.io.InputStreamReader;
  138.53 -import java.lang.ref.Reference;
  138.54 -import java.lang.ref.WeakReference;
  138.55 -import java.net.URL;
  138.56 -import java.net.URLClassLoader;
  138.57 -import java.net.URLConnection;
  138.58 -import java.net.URLStreamHandler;
  138.59 -import java.util.ArrayList;
  138.60 -import java.util.Collection;
  138.61 -import java.util.Collections;
  138.62 -import java.util.Comparator;
  138.63 -import java.util.Enumeration;
  138.64 -import java.util.HashSet;
  138.65 -import java.util.Iterator;
  138.66 -import java.util.List;
  138.67 -import java.util.Map;
  138.68 -import java.util.Set;
  138.69 -import java.util.TreeSet;
  138.70 -import java.util.WeakHashMap;
  138.71 -import java.util.concurrent.atomic.AtomicBoolean;
  138.72 -import java.util.jar.JarEntry;
  138.73 -import java.util.jar.JarOutputStream;
  138.74 -import java.util.logging.Level;
  138.75 -import java.util.logging.Logger;
  138.76 -import java.util.regex.Matcher;
  138.77 -import java.util.regex.Pattern;
  138.78 -import org.bar.Comparator2;
  138.79 -import org.netbeans.junit.MockServices;
  138.80 -import org.netbeans.junit.NbTestCase;
  138.81 -import org.openide.util.Enumerations;
  138.82 -import org.openide.util.Exceptions;
  138.83 -import org.openide.util.Lookup;
  138.84 -import org.openide.util.LookupEvent;
  138.85 -import org.openide.util.LookupListener;
  138.86 -import org.openide.util.test.MockLookup;
  138.87 -
  138.88 -/** Test finding services from manifest.
  138.89 - * @author Jesse Glick
  138.90 - */
  138.91 -public class MetaInfServicesLookupTest extends NbTestCase {
  138.92 -    private Logger LOG;
  138.93 -    private Map<ClassLoader,Lookup> lookups = new WeakHashMap<ClassLoader,Lookup>();
  138.94 -    
  138.95 -    public MetaInfServicesLookupTest(String name) {
  138.96 -        super(name);
  138.97 -        LOG = Logger.getLogger("Test." + name);
  138.98 -    }
  138.99 -
 138.100 -    protected String prefix() {
 138.101 -        return "META-INF/services/";
 138.102 -    }
 138.103 -    
 138.104 -    protected Lookup createLookup(ClassLoader c) {
 138.105 -        return Lookups.metaInfServices(c);
 138.106 -    }
 138.107 -    
 138.108 -    @Override
 138.109 -    protected Level logLevel() {
 138.110 -        return Level.INFO;
 138.111 -    }
 138.112 -
 138.113 -    private Lookup getTestedLookup(ClassLoader c) {
 138.114 -        MockServices.setServices();
 138.115 -        Lookup l = lookups.get(c);
 138.116 -        if (l == null) {
 138.117 -            l = createLookup(c);
 138.118 -            lookups.put(c, l);
 138.119 -        }
 138.120 -        return l;
 138.121 -    }
 138.122 -
 138.123 -    private URL findJar(String n) throws IOException {
 138.124 -        LOG.info("Looking for " + n);
 138.125 -        File jarDir = new File(getWorkDir(), "jars");
 138.126 -        jarDir.mkdirs();
 138.127 -        File jar = new File(jarDir, n);
 138.128 -        if (jar.exists()) {
 138.129 -            return jar.toURI().toURL();
 138.130 -        }
 138.131 -        
 138.132 -        LOG.info("generating " + jar);
 138.133 -        
 138.134 -        URL data = MetaInfServicesLookupTest.class.getResource(n.replaceAll("\\.jar", "\\.txt"));
 138.135 -        assertNotNull("Data found", data);
 138.136 -        StringBuffer sb = new StringBuffer();
 138.137 -        InputStreamReader r = new InputStreamReader(data.openStream());
 138.138 -        for(;;) {
 138.139 -            int ch = r.read();
 138.140 -            if (ch == -1) {
 138.141 -                break;
 138.142 -            }
 138.143 -            sb.append((char)ch);
 138.144 -        }
 138.145 -        
 138.146 -        JarOutputStream os = new JarOutputStream(new FileOutputStream(jar));
 138.147 -        
 138.148 -        Pattern p = Pattern.compile(":([^:]+):([^:]*)", Pattern.MULTILINE | Pattern.DOTALL);
 138.149 -        Matcher m = p.matcher(sb);
 138.150 -        Pattern foobar = Pattern.compile("^(org\\.(foo|bar)\\..*)$", Pattern.MULTILINE);
 138.151 -        Set<String> names = new TreeSet<String>();
 138.152 -        while (m.find()) {
 138.153 -            assert m.groupCount() == 2;
 138.154 -            String entryName = prefix() + m.group(1);
 138.155 -            LOG.info("putting there entry: " + entryName);
 138.156 -            os.putNextEntry(new JarEntry(entryName));
 138.157 -            os.write(m.group(2).getBytes());
 138.158 -            os.closeEntry();
 138.159 -            
 138.160 -            Matcher fb = foobar.matcher(m.group(2));
 138.161 -            while (fb.find()) {
 138.162 -                String clazz = fb.group(1).replace('.', '/') + ".class";
 138.163 -                LOG.info("will copy " + clazz);
 138.164 -                names.add(clazz);
 138.165 -            }
 138.166 -        }
 138.167 -        
 138.168 -        for (String copy : names) {
 138.169 -            os.putNextEntry(new JarEntry(copy));
 138.170 -            LOG.info("copying " + copy);
 138.171 -            InputStream from = MetaInfServicesLookupTest.class.getResourceAsStream("/" + copy);
 138.172 -            assertNotNull(copy, from);
 138.173 -            for (;;) {
 138.174 -                int ch = from.read();
 138.175 -                if (ch == -1) {
 138.176 -                    break;
 138.177 -                }
 138.178 -                os.write(ch);
 138.179 -            }
 138.180 -            from.close();
 138.181 -            os.closeEntry();
 138.182 -        }
 138.183 -        os.close();
 138.184 -        LOG.info("done " + jar);
 138.185 -        return jar.toURI().toURL();
 138.186 -    }
 138.187 -
 138.188 -    ClassLoader c1, c2, c2a, c3, c4;
 138.189 -
 138.190 -    @Override
 138.191 -    protected void setUp() throws Exception {
 138.192 -        clearWorkDir();
 138.193 -        ClassLoader app = getClass().getClassLoader().getParent();
 138.194 -        ClassLoader c0 = app;
 138.195 -        
 138.196 -        c1 = new URLClassLoader(new URL[] {
 138.197 -            findJar("services-jar-1.jar"),
 138.198 -        }, c0);
 138.199 -        c2 = new URLClassLoader(new URL[] {
 138.200 -            findJar("services-jar-2.jar"),
 138.201 -        }, c1);
 138.202 -        c2a = new URLClassLoader(new URL[] {
 138.203 -            findJar("services-jar-2.jar"),
 138.204 -        }, c1);
 138.205 -        c3 = new URLClassLoader(new URL[] { findJar("services-jar-2.jar") },
 138.206 -            c0
 138.207 -        );
 138.208 -        c4 = new URLClassLoader(new URL[] {
 138.209 -            findJar("services-jar-1.jar"),
 138.210 -            findJar("services-jar-2.jar"),
 138.211 -        }, c0);
 138.212 -    }
 138.213 -
 138.214 -    @Override
 138.215 -    protected void tearDown() throws Exception {
 138.216 -        Set<Reference<Lookup>> weak = new HashSet<Reference<Lookup>>();
 138.217 -        for (Lookup l : lookups.values()) {
 138.218 -            weak.add(new WeakReference<Lookup>(l));
 138.219 -        }
 138.220 -        
 138.221 -        lookups = null;
 138.222 -        
 138.223 -        for(Reference<Lookup> ref : weak) {
 138.224 -            assertGC("Lookup can disappear", ref);
 138.225 -        }
 138.226 -    }
 138.227 -
 138.228 -    public void testBasicUsage() throws Exception {
 138.229 -        Lookup l = getTestedLookup(c2);
 138.230 -        Class<?> xface = c1.loadClass("org.foo.Interface");
 138.231 -        List<?> results = new ArrayList<Object>(l.lookupAll(xface));
 138.232 -        assertEquals("Two items in result: " + results, 2, results.size());
 138.233 -        // Note that they have to be in order:
 138.234 -        assertEquals("org.foo.impl.Implementation1", results.get(0).getClass().getName());
 138.235 -        assertEquals("org.bar.Implementation2", results.get(1).getClass().getName());
 138.236 -        // Make sure it does not gratuitously replace items:
 138.237 -        List<?> results2 = new ArrayList<Object>(l.lookupAll(xface));
 138.238 -        assertEquals(results, results2);
 138.239 -    }
 138.240 -
 138.241 -    public void testLoaderSkew() throws Exception {
 138.242 -        Class<?> xface1 = c1.loadClass("org.foo.Interface");
 138.243 -        Lookup l3 = getTestedLookup(c3);
 138.244 -        // If we cannot load Interface, there should be no impls of course... quietly!
 138.245 -        assertEquals(Collections.emptyList(),
 138.246 -                new ArrayList<Object>(l3.lookupAll(xface1)));
 138.247 -        Lookup l4 = getTestedLookup(c4);
 138.248 -        // If we can load Interface but it is the wrong one, ignore it.
 138.249 -        assertEquals(Collections.emptyList(),
 138.250 -                new ArrayList<Object>(l4.lookupAll(xface1)));
 138.251 -        // Make sure l4 is really OK - it can load from its own JARs.
 138.252 -        Class<?> xface4 = c4.loadClass("org.foo.Interface");
 138.253 -        assertEquals(2, l4.lookupAll(xface4).size());
 138.254 -    }
 138.255 -
 138.256 -    public void testStability() throws Exception {
 138.257 -        Lookup l = getTestedLookup(c2);
 138.258 -        Class<?> xface = c1.loadClass("org.foo.Interface");
 138.259 -        Object first = l.lookup(xface);
 138.260 -        assertEquals(first, l.lookupAll(xface).iterator().next());
 138.261 -        l = getTestedLookup(c2a);
 138.262 -        Object second = l.lookup(xface);
 138.263 -        assertEquals(first, second);
 138.264 -    }
 138.265 -
 138.266 -    public void testMaskingOfResources() throws Exception {
 138.267 -        Lookup l1 = getTestedLookup(c1);
 138.268 -        Lookup l2 = getTestedLookup(c2);
 138.269 -        Lookup l4 = getTestedLookup(c4);
 138.270 -
 138.271 -        assertNotNull("services1.jar defines a class that implements runnable", l1.lookup(Runnable.class));
 138.272 -        assertNull("services2.jar does not defines a class that implements runnable", l2.lookup(Runnable.class));
 138.273 -        assertNull("services1.jar defines Runnable, but services2.jar masks it out", l4.lookup(Runnable.class));
 138.274 -    }
 138.275 -
 138.276 -    public void testOrdering() throws Exception {
 138.277 -        Lookup l = getTestedLookup(c1);
 138.278 -        Class<?> xface = c1.loadClass("java.util.Comparator");
 138.279 -        List<?> results = new ArrayList<Object>(l.lookupAll(xface));
 138.280 -        assertEquals(1, results.size());
 138.281 -
 138.282 -        l = getTestedLookup(c2);
 138.283 -        xface = c2.loadClass("java.util.Comparator");
 138.284 -        results = new ArrayList<Object>(l.lookupAll(xface));
 138.285 -        assertEquals(2, results.size());
 138.286 -        // Test order:
 138.287 -        assertEquals("org.bar.Comparator2", results.get(0).getClass().getName());
 138.288 -        assertEquals("org.foo.impl.Comparator1", results.get(1).getClass().getName());
 138.289 -
 138.290 -        // test that items without position are always at the end
 138.291 -        l = getTestedLookup(c2);
 138.292 -        xface = c2.loadClass("java.util.Iterator");
 138.293 -        results = new ArrayList<Object>(l.lookupAll(xface));
 138.294 -        assertEquals(2, results.size());
 138.295 -        // Test order:
 138.296 -        assertEquals("org.bar.Iterator2", results.get(0).getClass().getName());
 138.297 -        assertEquals("org.foo.impl.Iterator1", results.get(1).getClass().getName());
 138.298 -    }
 138.299 -
 138.300 -    public void testNoCallToGetResourceForObjectIssue65124() throws Exception {
 138.301 -        class Loader extends ClassLoader {
 138.302 -            private int counter;
 138.303 -
 138.304 -            @Override
 138.305 -            protected URL findResource(String name) {
 138.306 -                if (name.equals(prefix() + "java.lang.Object")) {
 138.307 -                    counter++;
 138.308 -                }
 138.309 -
 138.310 -                URL retValue;
 138.311 -
 138.312 -                retValue = super.findResource(name);
 138.313 -                return retValue;
 138.314 -            }
 138.315 -
 138.316 -            @Override
 138.317 -            protected Enumeration<URL> findResources(String name) throws IOException {
 138.318 -                if (name.equals(prefix() + "java.lang.Object")) {
 138.319 -                    counter++;
 138.320 -                }
 138.321 -                return super.findResources(name);
 138.322 -            }
 138.323 -        }
 138.324 -        Loader loader = new Loader();
 138.325 -        Lookup l = getTestedLookup(loader);
 138.326 -
 138.327 -        Object no = l.lookup(String.class);
 138.328 -        assertNull("Not found of course", no);
 138.329 -        assertEquals("No lookup of Object", 0, loader.counter);
 138.330 -    }
 138.331 -
 138.332 -    public void testCanGarbageCollectClasses() throws Exception {
 138.333 -        class Loader extends ClassLoader {
 138.334 -            public Loader() {
 138.335 -                super(Loader.class.getClassLoader().getParent());
 138.336 -            }
 138.337 -
 138.338 -            @Override
 138.339 -            protected URL findResource(String name) {
 138.340 -                if (name.equals(prefix() + "java.lang.Runnable")) {
 138.341 -                    return Loader.class.getResource("MetaInfServicesLookupTestRunnable.txt");
 138.342 -                }
 138.343 -
 138.344 -                URL retValue;
 138.345 -
 138.346 -                retValue = super.findResource(name);
 138.347 -                return retValue;
 138.348 -            }
 138.349 -
 138.350 -            @Override
 138.351 -            protected Class<?> findClass(String name) throws ClassNotFoundException {
 138.352 -                if (name.equals("org.openide.util.lookup.MetaInfServicesLookupTestRunnable")) {
 138.353 -                    try {
 138.354 -                        InputStream is = getClass().getResourceAsStream("MetaInfServicesLookupTestRunnable.class");
 138.355 -                        byte[] arr = new byte[is.available()];
 138.356 -                        int read = is.read(arr);
 138.357 -                        assertEquals("Fully read", arr.length, read);
 138.358 -                        return defineClass(name, arr, 0, arr.length);
 138.359 -                    } catch (IOException ex) {
 138.360 -                        throw new ClassNotFoundException("Cannot load", ex);
 138.361 -                    }
 138.362 -                }
 138.363 -                throw new ClassNotFoundException();
 138.364 -            }
 138.365 -
 138.366 -
 138.367 -
 138.368 -            @Override
 138.369 -            protected Enumeration<URL> findResources(String name) throws IOException {
 138.370 -                if (name.equals(prefix() + "java.lang.Runnable")) {
 138.371 -                    return Collections.enumeration(Collections.singleton(findResource(name)));
 138.372 -                }
 138.373 -                return super.findResources(name);
 138.374 -            }
 138.375 -        }
 138.376 -        Loader loader = new Loader();
 138.377 -        Lookup l = getTestedLookup(loader);
 138.378 -
 138.379 -
 138.380 -        Object no = l.lookup(Runnable.class);
 138.381 -        assertNotNull("Found of course", no);
 138.382 -        assertEquals("The right name", "MetaInfServicesLookupTestRunnable", no.getClass().getSimpleName());
 138.383 -        if (no.getClass().getClassLoader() != loader) {
 138.384 -            fail("Wrong classloader: " + no.getClass().getClassLoader());
 138.385 -        }
 138.386 -
 138.387 -        WeakReference<Object> ref = new WeakReference<Object>(no.getClass());
 138.388 -        loader = null;
 138.389 -        no = null;
 138.390 -        l = null;
 138.391 -        lookups.clear();
 138.392 -        MockLookup.setInstances();
 138.393 -        Thread.currentThread().setContextClassLoader(null);
 138.394 -        assertGC("Class can be garbage collected", ref);
 138.395 -    }
 138.396 -
 138.397 -    public void testSuperTypes() throws Exception {
 138.398 -        doTestSuperTypes(createLookup(c2));
 138.399 -        doTestSuperTypes(new ProxyLookup(createLookup(c2)));
 138.400 -    }
 138.401 -    private void doTestSuperTypes(Lookup l) throws Exception {
 138.402 -        final Class<?> xface = c1.loadClass("org.foo.Interface");
 138.403 -        final Lookup.Result<Object> res = l.lookupResult(Object.class);
 138.404 -        assertEquals("Nothing yet", 0, res.allInstances().size());
 138.405 -        final AtomicBoolean event = new AtomicBoolean();
 138.406 -        final Thread here = Thread.currentThread();
 138.407 -        res.addLookupListener(new LookupListener() {
 138.408 -            public void resultChanged(LookupEvent ev) {
 138.409 -                if (Thread.currentThread() == here) {
 138.410 -                    event.set(true);
 138.411 -                }
 138.412 -            }
 138.413 -        });
 138.414 -        assertNotNull("Interface found", l.lookup(xface));
 138.415 -        assertFalse(event.get());
 138.416 -        MetaInfServicesLookup.RP.post(new Runnable() {public void run() {}}).waitFinished();
 138.417 -        assertEquals("Now two", 2, res.allInstances().size());
 138.418 -    }
 138.419 -    
 138.420 -    public void testWrongOrderAsInIssue100320() throws Exception {
 138.421 -        ClassLoader app = getClass().getClassLoader().getParent();
 138.422 -        ClassLoader c0 = app;
 138.423 -        ClassLoader ctmp = new URLClassLoader(new URL[] {
 138.424 -            findJar("problem100320.jar"),
 138.425 -        }, c0);
 138.426 -        Lookup lookup = Lookups.metaInfServices(ctmp, prefix());
 138.427 -
 138.428 -        Collection<?> colAWT = lookup.lookupAll(IOException.class);
 138.429 -        assertEquals("There is enough objects to switch to InheritanceTree", 12, colAWT.size());
 138.430 -        
 138.431 -        
 138.432 -        List<?> col1 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
 138.433 -        assertEquals("Two", 2, col1.size());
 138.434 -        Collection<?> col2 = lookup.lookupAll(ctmp.loadClass(Comparator2.class.getName()));
 138.435 -        assertEquals("One", 1, col2.size());
 138.436 -        List<?> col3 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
 138.437 -        assertEquals("Two2", 2, col3.size());
 138.438 -        
 138.439 -        Iterator<?> it1 = col1.iterator();
 138.440 -        Iterator<?> it3 = col3.iterator();
 138.441 -        if (
 138.442 -            it1.next() != it3.next() || 
 138.443 -            it1.next() != it3.next() 
 138.444 -        ) {
 138.445 -            fail("Collections are different:\nFirst: " + col1 + "\nLast:  " + col3);
 138.446 -        }
 138.447 -    }
 138.448 -
 138.449 -    public void testContentionWhenLoadingMetainfServices() throws Exception {
 138.450 -        class My extends ClassLoader implements Runnable {
 138.451 -            Lookup query;
 138.452 -            Integer value;
 138.453 -
 138.454 -            public void run() {
 138.455 -                value = query.lookup(Integer.class);
 138.456 -            }
 138.457 -
 138.458 -
 138.459 -            @Override
 138.460 -            protected URL findResource(String name) {
 138.461 -                waitForTask(name);
 138.462 -                return super.findResource(name);
 138.463 -            }
 138.464 -
 138.465 -            @Override
 138.466 -            protected Enumeration<URL> findResources(String name) throws IOException {
 138.467 -                waitForTask(name);
 138.468 -                return super.findResources(name);
 138.469 -            }
 138.470 -
 138.471 -            private synchronized void waitForTask(String name) {
 138.472 -                if (name.startsWith(prefix()) && Thread.currentThread().getName().contains("block")) {
 138.473 -                    try {
 138.474 -                        wait();
 138.475 -                    } catch (InterruptedException ex) {
 138.476 -                        Exceptions.printStackTrace(ex);
 138.477 -                    }
 138.478 -                }
 138.479 -            }
 138.480 -        }
 138.481 -
 138.482 -        My loader = new My();
 138.483 -        loader.query = createLookup(loader);
 138.484 -        Thread t = new Thread(loader, "block when querying");
 138.485 -        t.start();
 138.486 -        t.join(1000);
 138.487 -
 138.488 -        // this blocks waiting for the waitForTask to finish
 138.489 -        // right now
 138.490 -        Float f = loader.query.lookup(Float.class);
 138.491 -        assertNull("Nothing found", f);
 138.492 -
 138.493 -        synchronized (loader) {
 138.494 -            loader.notifyAll();
 138.495 -        }
 138.496 -        t.join();
 138.497 -
 138.498 -        assertNull("Nothing found", loader.value);
 138.499 -    }
 138.500 -
 138.501 -    public void testInitializerRobustness() throws Exception { // #174055
 138.502 -        check(Broken1.class.getName());
 138.503 -        check(Broken2.class.getName());
 138.504 -    }
 138.505 -    private void check(final String n) {
 138.506 -        assertNull(Lookups.metaInfServices(new ClassLoader() {
 138.507 -            protected @Override Enumeration<URL> findResources(String name) throws IOException {
 138.508 -                if (name.equals("META-INF/services/java.lang.Object")) {
 138.509 -                    return Enumerations.singleton(new URL(null, "dummy:stuff", new URLStreamHandler() {
 138.510 -                        protected URLConnection openConnection(URL u) throws IOException {
 138.511 -                            return new URLConnection(u) {
 138.512 -                                public void connect() throws IOException {}
 138.513 -                                public @Override InputStream getInputStream() throws IOException {
 138.514 -                                    return new ByteArrayInputStream(n.getBytes("UTF-8"));
 138.515 -                                }
 138.516 -                            };
 138.517 -                        }
 138.518 -                    }));
 138.519 -                } else {
 138.520 -                    return Enumerations.empty();
 138.521 -                }
 138.522 -            }
 138.523 -        }).lookup(Object.class));
 138.524 -    }
 138.525 -    public static class Broken1 {
 138.526 -        public Broken1() {
 138.527 -            throw new NullPointerException("broken1");
 138.528 -        }
 138.529 -    }
 138.530 -    public static class Broken2 {
 138.531 -        static {
 138.532 -            if (true) { // otherwise javac complains
 138.533 -                throw new NullPointerException("broken2");
 138.534 -            }
 138.535 -        }
 138.536 -    }
 138.537 -
 138.538 -}
   139.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.java	Thu Dec 10 19:23:25 2009 -0500
   139.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.3 @@ -1,50 +0,0 @@
   139.4 -/*
   139.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   139.6 - *
   139.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   139.8 - *
   139.9 - * The contents of this file are subject to the terms of either the GNU
  139.10 - * General Public License Version 2 only ("GPL") or the Common
  139.11 - * Development and Distribution License("CDDL") (collectively, the
  139.12 - * "License"). You may not use this file except in compliance with the
  139.13 - * License. You can obtain a copy of the License at
  139.14 - * http://www.netbeans.org/cddl-gplv2.html
  139.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  139.16 - * specific language governing permissions and limitations under the
  139.17 - * License.  When distributing the software, include this License Header
  139.18 - * Notice in each file and include the License file at
  139.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  139.20 - * particular file as subject to the "Classpath" exception as provided
  139.21 - * by Sun in the GPL Version 2 section of the License file that
  139.22 - * accompanied this code. If applicable, add the following below the
  139.23 - * License Header, with the fields enclosed by brackets [] replaced by
  139.24 - * your own identifying information:
  139.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  139.26 - *
  139.27 - * Contributor(s):
  139.28 - *
  139.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  139.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  139.31 - * Microsystems, Inc. All Rights Reserved.
  139.32 - *
  139.33 - * If you wish your version of this file to be governed by only the CDDL
  139.34 - * or only the GPL Version 2, indicate your decision by adding
  139.35 - * "[Contributor] elects to include this software in this distribution
  139.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  139.37 - * single choice of license, a recipient has the option to distribute
  139.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  139.39 - * to extend the choice of license to its licensees as provided above.
  139.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  139.41 - * Version 2 license, then the option applies only if the new code is
  139.42 - * made subject to such option by the copyright holder.
  139.43 - */
  139.44 -
  139.45 -package org.openide.util.lookup;
  139.46 -
  139.47 -
  139.48 -/**
  139.49 - */
  139.50 -public final class MetaInfServicesLookupTestRunnable implements Runnable {
  139.51 -    public void run() {
  139.52 -    }
  139.53 -}
   140.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.txt	Thu Dec 10 19:23:25 2009 -0500
   140.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   140.3 @@ -1,1 +0,0 @@
   140.4 -org.openide.util.lookup.MetaInfServicesLookupTestRunnable
   141.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/NamedServicesLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   141.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   141.3 @@ -1,85 +0,0 @@
   141.4 -/*
   141.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   141.6 - *
   141.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   141.8 - *
   141.9 - * The contents of this file are subject to the terms of either the GNU
  141.10 - * General Public License Version 2 only ("GPL") or the Common
  141.11 - * Development and Distribution License("CDDL") (collectively, the
  141.12 - * "License"). You may not use this file except in compliance with the
  141.13 - * License. You can obtain a copy of the License at
  141.14 - * http://www.netbeans.org/cddl-gplv2.html
  141.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  141.16 - * specific language governing permissions and limitations under the
  141.17 - * License.  When distributing the software, include this License Header
  141.18 - * Notice in each file and include the License file at
  141.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  141.20 - * particular file as subject to the "Classpath" exception as provided
  141.21 - * by Sun in the GPL Version 2 section of the License file that
  141.22 - * accompanied this code. If applicable, add the following below the
  141.23 - * License Header, with the fields enclosed by brackets [] replaced by
  141.24 - * your own identifying information:
  141.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  141.26 - *
  141.27 - * Contributor(s):
  141.28 - *
  141.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  141.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  141.31 - * Microsystems, Inc. All Rights Reserved.
  141.32 - *
  141.33 - * If you wish your version of this file to be governed by only the CDDL
  141.34 - * or only the GPL Version 2, indicate your decision by adding
  141.35 - * "[Contributor] elects to include this software in this distribution
  141.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  141.37 - * single choice of license, a recipient has the option to distribute
  141.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  141.39 - * to extend the choice of license to its licensees as provided above.
  141.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  141.41 - * Version 2 license, then the option applies only if the new code is
  141.42 - * made subject to such option by the copyright holder.
  141.43 - */
  141.44 -
  141.45 -package org.openide.util.lookup;
  141.46 -
  141.47 -import org.openide.util.Lookup;
  141.48 -import org.openide.util.test.MockLookup;
  141.49 -
  141.50 -
  141.51 -/** Test finding services from manifest.
  141.52 - * @author Jaroslav Tulach
  141.53 - */
  141.54 -public class NamedServicesLookupTest extends MetaInfServicesLookupTest {
  141.55 -    static {
  141.56 -        MockLookup.init();
  141.57 -    }
  141.58 -    public NamedServicesLookupTest(String name) {
  141.59 -        super(name);
  141.60 -    }
  141.61 -
  141.62 -    @Override
  141.63 -    protected String prefix() {
  141.64 -        return "META-INF/namedservices/sub/path/";
  141.65 -    }
  141.66 -    
  141.67 -    @Override
  141.68 -    protected Lookup createLookup(ClassLoader c) {
  141.69 -        MockLookup.setInstances(c);
  141.70 -        Thread.currentThread().setContextClassLoader(c);
  141.71 -        Lookup l = Lookups.forPath("sub/path");
  141.72 -        return l;
  141.73 -    }
  141.74 -    
  141.75 -    //
  141.76 -    // this is not much inheriting test, as we mask most of the tested methods
  141.77 -    // anyway, but the infrastructure to generate the JAR files is useful
  141.78 -    //
  141.79 -    
  141.80 -    public @Override void testLoaderSkew() {}
  141.81 -    public @Override void testStability() throws Exception {}
  141.82 -    public @Override void testMaskingOfResources() throws Exception {}
  141.83 -    public @Override void testOrdering() throws Exception {}
  141.84 -    public @Override void testNoCallToGetResourceForObjectIssue65124() throws Exception {}
  141.85 -    public @Override void testSuperTypes() throws Exception {}
  141.86 -    public @Override void testWrongOrderAsInIssue100320() throws Exception {}
  141.87 -    
  141.88 -}
   142.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/PathInLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   142.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   142.3 @@ -1,112 +0,0 @@
   142.4 -/*
   142.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   142.6 - *
   142.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   142.8 - *
   142.9 - * The contents of this file are subject to the terms of either the GNU
  142.10 - * General Public License Version 2 only ("GPL") or the Common
  142.11 - * Development and Distribution License("CDDL") (collectively, the
  142.12 - * "License"). You may not use this file except in compliance with the
  142.13 - * License. You can obtain a copy of the License at
  142.14 - * http://www.netbeans.org/cddl-gplv2.html
  142.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  142.16 - * specific language governing permissions and limitations under the
  142.17 - * License.  When distributing the software, include this License Header
  142.18 - * Notice in each file and include the License file at
  142.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  142.20 - * particular file as subject to the "Classpath" exception as provided
  142.21 - * by Sun in the GPL Version 2 section of the License file that
  142.22 - * accompanied this code. If applicable, add the following below the
  142.23 - * License Header, with the fields enclosed by brackets [] replaced by
  142.24 - * your own identifying information:
  142.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  142.26 - *
  142.27 - * Contributor(s):
  142.28 - *
  142.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  142.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  142.31 - * Microsystems, Inc. All Rights Reserved.
  142.32 - *
  142.33 - * If you wish your version of this file to be governed by only the CDDL
  142.34 - * or only the GPL Version 2, indicate your decision by adding
  142.35 - * "[Contributor] elects to include this software in this distribution
  142.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  142.37 - * single choice of license, a recipient has the option to distribute
  142.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  142.39 - * to extend the choice of license to its licensees as provided above.
  142.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  142.41 - * Version 2 license, then the option applies only if the new code is
  142.42 - * made subject to such option by the copyright holder.
  142.43 - */
  142.44 -
  142.45 -package org.openide.util.lookup;
  142.46 -
  142.47 -import java.util.logging.Level;
  142.48 -import org.netbeans.junit.MockServices;
  142.49 -import org.netbeans.junit.NbTestCase;
  142.50 -import org.netbeans.modules.openide.util.NamedServicesProvider;
  142.51 -import org.openide.util.Lookup;
  142.52 -
  142.53 -/** 
  142.54 - * @author Jaroslav Tulach
  142.55 - */
  142.56 -public class PathInLookupTest extends NbTestCase {
  142.57 -    static {
  142.58 -        System.setProperty("org.openide.util.Lookup.paths", "MyServices:YourServices");
  142.59 -        MockServices.setServices(P.class);
  142.60 -        Lookup.getDefault();
  142.61 -    }
  142.62 -
  142.63 -    public PathInLookupTest(String name) {
  142.64 -        super(name);
  142.65 -    }
  142.66 -
  142.67 -    @Override
  142.68 -    protected Level logLevel() {
  142.69 -        return Level.FINE;
  142.70 -    }
  142.71 -    
  142.72 -    public void testInterfaceFoundInMyServices() throws Exception {
  142.73 -        assertNull("not found", Lookup.getDefault().lookup(Shared.class));
  142.74 -        Shared v = new Shared();
  142.75 -        P.ic1.add(v);
  142.76 -        assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
  142.77 -        P.ic1.remove(v);
  142.78 -        assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
  142.79 -    }
  142.80 -    public void testInterfaceFoundInMyServices2() throws Exception {
  142.81 -        assertNull("not found", Lookup.getDefault().lookup(Shared.class));
  142.82 -        Shared v = new Shared();
  142.83 -        P.ic2.add(v);
  142.84 -        assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
  142.85 -        P.ic2.remove(v);
  142.86 -        assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
  142.87 -    }
  142.88 -
  142.89 -    static final class Shared extends Object {}
  142.90 -
  142.91 -    public static final class P extends NamedServicesProvider {
  142.92 -        static InstanceContent ic1 = new InstanceContent();
  142.93 -        static InstanceContent ic2 = new InstanceContent();
  142.94 -        static AbstractLookup[] arr = {
  142.95 -            new AbstractLookup(ic1), new AbstractLookup(ic2)
  142.96 -        };
  142.97 -
  142.98 -
  142.99 -        @Override
 142.100 -        public Lookup create(String path) {
 142.101 -            int indx = -1;
 142.102 -            if (path.equals("MyServices/")) {
 142.103 -                indx = 0;
 142.104 -            }
 142.105 -            if (path.equals("YourServices/")) {
 142.106 -                indx = 1;
 142.107 -            }
 142.108 -            if (indx == -1) {
 142.109 -                fail("Unexpected lookup query: " + path);
 142.110 -            }
 142.111 -            return arr[indx];
 142.112 -        }
 142.113 -    }
 142.114 -
 142.115 -}
   143.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/PrefixServicesLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   143.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.3 @@ -1,63 +0,0 @@
   143.4 -/*
   143.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   143.6 - *
   143.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   143.8 - *
   143.9 - * The contents of this file are subject to the terms of either the GNU
  143.10 - * General Public License Version 2 only ("GPL") or the Common
  143.11 - * Development and Distribution License("CDDL") (collectively, the
  143.12 - * "License"). You may not use this file except in compliance with the
  143.13 - * License. You can obtain a copy of the License at
  143.14 - * http://www.netbeans.org/cddl-gplv2.html
  143.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  143.16 - * specific language governing permissions and limitations under the
  143.17 - * License.  When distributing the software, include this License Header
  143.18 - * Notice in each file and include the License file at
  143.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  143.20 - * particular file as subject to the "Classpath" exception as provided
  143.21 - * by Sun in the GPL Version 2 section of the License file that
  143.22 - * accompanied this code. If applicable, add the following below the
  143.23 - * License Header, with the fields enclosed by brackets [] replaced by
  143.24 - * your own identifying information:
  143.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  143.26 - *
  143.27 - * Contributor(s):
  143.28 - *
  143.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  143.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  143.31 - * Microsystems, Inc. All Rights Reserved.
  143.32 - *
  143.33 - * If you wish your version of this file to be governed by only the CDDL
  143.34 - * or only the GPL Version 2, indicate your decision by adding
  143.35 - * "[Contributor] elects to include this software in this distribution
  143.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  143.37 - * single choice of license, a recipient has the option to distribute
  143.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  143.39 - * to extend the choice of license to its licensees as provided above.
  143.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  143.41 - * Version 2 license, then the option applies only if the new code is
  143.42 - * made subject to such option by the copyright holder.
  143.43 - */
  143.44 -
  143.45 -package org.openide.util.lookup;
  143.46 -
  143.47 -import org.openide.util.Lookup;
  143.48 -
  143.49 -
  143.50 -/** Test finding services from manifest.
  143.51 - * @author Jaroslav Tulach
  143.52 - */
  143.53 -public class PrefixServicesLookupTest extends MetaInfServicesLookupTest {
  143.54 -    public PrefixServicesLookupTest(String name) {
  143.55 -        super(name);
  143.56 -    }
  143.57 -    
  143.58 -    protected String prefix() {
  143.59 -        return "META-INF/netbeans/prefix/services/test/";
  143.60 -    }
  143.61 -    
  143.62 -    protected Lookup createLookup(ClassLoader c) {
  143.63 -        return Lookups.metaInfServices(c, prefix());
  143.64 -    }
  143.65 -    
  143.66 -}
   144.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/ProxyLookup173975Test.java	Thu Dec 10 19:23:25 2009 -0500
   144.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.3 @@ -1,108 +0,0 @@
   144.4 -/*
   144.5 - * To change this template, choose Tools | Templates
   144.6 - * and open the template in the editor.
   144.7 - */
   144.8 -package org.openide.util.lookup;
   144.9 -
  144.10 -import java.util.Collection;
  144.11 -import java.util.Collections;
  144.12 -import org.junit.Assert;
  144.13 -import org.junit.Test;
  144.14 -import org.openide.util.Lookup;
  144.15 -import org.openide.util.LookupEvent;
  144.16 -import org.openide.util.LookupListener;
  144.17 -import org.openide.util.lookup.AbstractLookup.Storage;
  144.18 -
  144.19 -public class ProxyLookup173975Test {
  144.20 -
  144.21 -    public ProxyLookup173975Test() {
  144.22 -    }
  144.23 -
  144.24 -    boolean called = false;
  144.25 -
  144.26 -    @Test
  144.27 -    public void testAbstractLookupWithoutAllInstances() {
  144.28 -        registerLookupListenerAndAddSomething(false, false, false);
  144.29 -    }
  144.30 -
  144.31 -    @Test
  144.32 -    public void testAbstractLookupWithAllInstances() {
  144.33 -        registerLookupListenerAndAddSomething(false, true, false);
  144.34 -    }
  144.35 -
  144.36 -    @Test
  144.37 -    public void testAbstractLookupInheritanceTreeWithoutAllInstances() {
  144.38 -        registerLookupListenerAndAddSomething(false, false, true);
  144.39 -    }
  144.40 -
  144.41 -    @Test
  144.42 -    public void testAbstractLookupInheritanceTreeWithAllInstances() {
  144.43 -        registerLookupListenerAndAddSomething(false, true, true);
  144.44 -    }
  144.45 -
  144.46 -    @Test
  144.47 -    public void testProxyLookupWithoutAllInstances() {
  144.48 -        registerLookupListenerAndAddSomething(true, false, false);
  144.49 -    }
  144.50 -
  144.51 -    @Test
  144.52 -    public void testProxyLookupWithAllInstances() {
  144.53 -        registerLookupListenerAndAddSomething(true, true, false);
  144.54 -    }
  144.55 -
  144.56 -    @Test
  144.57 -    public void testProxyLookupInheritanceTreeWithoutAllInstances() {
  144.58 -        registerLookupListenerAndAddSomething(true, false, true);
  144.59 -    }
  144.60 -
  144.61 -    @Test
  144.62 -    public void testProxyLookupInheritanceTreeWithAllInstances() {
  144.63 -        registerLookupListenerAndAddSomething(true, true, true);
  144.64 -    }
  144.65 -
  144.66 -    private void registerLookupListenerAndAddSomething(boolean useProxy, boolean callAllInstances, boolean inheritanceTree) {
  144.67 -        called = false;
  144.68 -        InstanceContent aInstanceContent = new InstanceContent();
  144.69 -        Storage<?> s = inheritanceTree ? new InheritanceTree() : new ArrayStorage();
  144.70 -        Lookup aLookup = new AbstractLookup(aInstanceContent, s);
  144.71 -        if (useProxy) {
  144.72 -            aLookup = new ProxyLookup(aLookup);
  144.73 -        }
  144.74 -        Lookup.Result<ObjectInLookup> result = aLookup.lookupResult(ObjectInLookup.class);
  144.75 -        if (callAllInstances) {
  144.76 -            result.allInstances(); // TO GET SUCCESS
  144.77 -        }
  144.78 -        result.addLookupListener(new LookupListener() {
  144.79 -
  144.80 -            public void resultChanged(LookupEvent ev) {
  144.81 -                Lookup.Result aResult = (Lookup.Result) ev.getSource();
  144.82 -                Collection c = aResult.allInstances();
  144.83 -                if (!c.isEmpty()) {
  144.84 -                    called = true;
  144.85 -                }
  144.86 -            }
  144.87 -        });
  144.88 -
  144.89 -        aInstanceContent.set(Collections.singleton(
  144.90 -                new ObjectInLookup("Set Object in Lookup)")), null);
  144.91 -        Assert.assertTrue("Listener was notified", called);
  144.92 -    }
  144.93 -
  144.94 -    public class ObjectInLookup {
  144.95 -
  144.96 -        private final String name;
  144.97 -
  144.98 -        public ObjectInLookup(String name) {
  144.99 -            this.name = name;
 144.100 -        }
 144.101 -
 144.102 -        public String getName() {
 144.103 -            return this.name;
 144.104 -        }
 144.105 -
 144.106 -        @Override
 144.107 -        public String toString() {
 144.108 -            return "objectinlookup:" + getName();
 144.109 -        }
 144.110 -    }
 144.111 -}
   145.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupEventIssue136866Test.java	Thu Dec 10 19:23:25 2009 -0500
   145.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.3 @@ -1,56 +0,0 @@
   145.4 -package org.openide.util.lookup;
   145.5 -
   145.6 -import junit.framework.TestCase;
   145.7 -import org.openide.util.Lookup;
   145.8 -import org.openide.util.LookupEvent;
   145.9 -import org.openide.util.LookupListener;
  145.10 -
  145.11 -/**
  145.12 - * Test case which demonstrates that ProxyLookup does not fire
  145.13 - * an event when it should.
  145.14 - */
  145.15 -public class ProxyLookupEventIssue136866Test extends TestCase {
  145.16 -
  145.17 -    public ProxyLookupEventIssue136866Test(String testName) {
  145.18 -        super(testName);
  145.19 -    }
  145.20 -
  145.21 -    public void testAbstractLookupFiresEventWhenContentChanged() {
  145.22 -        InstanceContent ic = new InstanceContent();
  145.23 -        AbstractLookup al = new AbstractLookup(ic);
  145.24 -
  145.25 -        final int[] counts = {0}; // Number of items observed upon a LookupEvent
  145.26 -        final Lookup.Result<String> result = al.lookupResult(String.class);
  145.27 -
  145.28 -        result.addLookupListener(new LookupListener() {
  145.29 -            public void resultChanged(LookupEvent ev) {
  145.30 -                // this gets called as expected
  145.31 -                assertSame(result, ev.getSource());
  145.32 -                counts[0] = result.allInstances().size();
  145.33 -            }
  145.34 -        });
  145.35 -        
  145.36 -        ic.add("hello1");
  145.37 -        assertEquals(1, counts[0]);
  145.38 -    }
  145.39 -    
  145.40 -    public void testProxyLookupFailsToFireEventWhenProxiedLookupChanged() {
  145.41 -        InstanceContent ic = new InstanceContent();
  145.42 -//        AbstractLookup al = new AbstractLookup(ic);
  145.43 -        Lookup proxy = new AbstractLookup(ic);
  145.44 -
  145.45 -        final int[] counts = {0}; // Number of items observed upon a LookupEvent
  145.46 -        final Lookup.Result<String> result = proxy.lookupResult(String.class);
  145.47 -
  145.48 -        result.addLookupListener(new LookupListener() {
  145.49 -            public void resultChanged(LookupEvent ev) {
  145.50 -                // this should be called but never is
  145.51 -                assertSame(result, ev.getSource());
  145.52 -                counts[0] = result.allInstances().size();
  145.53 -            }
  145.54 -        });
  145.55 -        
  145.56 -        ic.add("hello1");
  145.57 -        assertEquals(1, counts[0]);
  145.58 -    }
  145.59 -}
   146.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   146.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.3 @@ -1,655 +0,0 @@
   146.4 -/*
   146.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   146.6 - *
   146.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   146.8 - *
   146.9 - * The contents of this file are subject to the terms of either the GNU
  146.10 - * General Public License Version 2 only ("GPL") or the Common
  146.11 - * Development and Distribution License("CDDL") (collectively, the
  146.12 - * "License"). You may not use this file except in compliance with the
  146.13 - * License. You can obtain a copy of the License at
  146.14 - * http://www.netbeans.org/cddl-gplv2.html
  146.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  146.16 - * specific language governing permissions and limitations under the
  146.17 - * License.  When distributing the software, include this License Header
  146.18 - * Notice in each file and include the License file at
  146.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  146.20 - * particular file as subject to the "Classpath" exception as provided
  146.21 - * by Sun in the GPL Version 2 section of the License file that
  146.22 - * accompanied this code. If applicable, add the following below the
  146.23 - * License Header, with the fields enclosed by brackets [] replaced by
  146.24 - * your own identifying information:
  146.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  146.26 - *
  146.27 - * Contributor(s):
  146.28 - *
  146.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  146.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  146.31 - * Microsystems, Inc. All Rights Reserved.
  146.32 - *
  146.33 - * If you wish your version of this file to be governed by only the CDDL
  146.34 - * or only the GPL Version 2, indicate your decision by adding
  146.35 - * "[Contributor] elects to include this software in this distribution
  146.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  146.37 - * single choice of license, a recipient has the option to distribute
  146.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  146.39 - * to extend the choice of license to its licensees as provided above.
  146.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  146.41 - * Version 2 license, then the option applies only if the new code is
  146.42 - * made subject to such option by the copyright holder.
  146.43 - */
  146.44 -
  146.45 -package org.openide.util.lookup;
  146.46 -
  146.47 -import java.io.Serializable;
  146.48 -
  146.49 -import java.lang.ref.Reference;
  146.50 -import java.lang.ref.WeakReference;
  146.51 -import java.util.*;
  146.52 -import java.util.concurrent.Executor;
  146.53 -import junit.framework.*;
  146.54 -import org.netbeans.junit.*;
  146.55 -import org.netbeans.modules.openide.util.ActiveQueue;
  146.56 -import org.openide.util.Lookup;
  146.57 -import org.openide.util.Lookup.Result;
  146.58 -import org.openide.util.LookupEvent;
  146.59 -import org.openide.util.LookupListener;
  146.60 -
  146.61 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
  146.62 - */
  146.63 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  146.64 -public class ProxyLookupTest extends AbstractLookupBaseHid
  146.65 -implements AbstractLookupBaseHid.Impl {
  146.66 -    public ProxyLookupTest(java.lang.String testName) {
  146.67 -        super(testName, null);
  146.68 -    }
  146.69 -
  146.70 -    public static Test suite() {
  146.71 -        return new NbTestSuite (ProxyLookupTest.class);
  146.72 -//        return new ProxyLookupTest("testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679");
  146.73 -    }
  146.74 -    
  146.75 -    /** Creates an lookup for given lookup. This class just returns 
  146.76 -     * the object passed in, but subclasses can be different.
  146.77 -     * @param lookup in lookup
  146.78 -     * @return a lookup to use
  146.79 -     */
  146.80 -    public Lookup createLookup (Lookup lookup) {
  146.81 -        return new ProxyLookup (new Lookup[] { lookup });
  146.82 -    }
  146.83 -    
  146.84 -    public Lookup createInstancesLookup (InstanceContent ic) {
  146.85 -        return new AbstractLookup (ic);
  146.86 -    }
  146.87 -    
  146.88 -
  146.89 -    public void clearCaches () {
  146.90 -    }    
  146.91 -    
  146.92 -    
  146.93 -    /** Check whether setLookups method does not fire when there is no
  146.94 -     * change in the lookups.
  146.95 -     */
  146.96 -    public void testProxyListener () {
  146.97 -        ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
  146.98 -
  146.99 -        final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
 146.100 -        final Object[] IGNORE = {
 146.101 -            ProxyLookup.ImmutableInternalData.EMPTY,
 146.102 -            ProxyLookup.ImmutableInternalData.EMPTY_ARR,
 146.103 -            ActiveQueue.queue(),
 146.104 -            Collections.emptyMap(),
 146.105 -            Collections.emptyList(),
 146.106 -            Collections.emptySet()
 146.107 -        };
 146.108 -        
 146.109 -        assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
 146.110 -        
 146.111 -        Lookup.Result<Object> res = lookup.lookup (template);
 146.112 -
 146.113 -        assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
 146.114 -        
 146.115 -        LL ll = new LL ();
 146.116 -        res.addLookupListener (ll);
 146.117 -        Collection allRes = res.allInstances ();
 146.118 -        
 146.119 -        lookup.setLookups (new Lookup[0]);
 146.120 -        
 146.121 -        if (ll.getCount () != 0) {
 146.122 -           fail ("Calling setLookups (emptyarray) fired a change");
 146.123 -        }
 146.124 -        
 146.125 -        InstanceContent t = new InstanceContent();
 146.126 -        Lookup del = new AbstractLookup (t);
 146.127 -        t.add("Ahoj");
 146.128 -        lookup.setLookups (new Lookup[] { del });
 146.129 -        
 146.130 -        if (ll.getCount () != 1) {
 146.131 -            fail ("Changing lookups did not generate an event");
 146.132 -        }
 146.133 -        
 146.134 -        lookup.setLookups (new Lookup[] { del });
 146.135 -        
 146.136 -        if (ll.getCount () != 0) {
 146.137 -           fail ("Calling setLookups (thesamearray) fired a change");
 146.138 -        }
 146.139 -    }
 146.140 -    
 146.141 -    public void testNoListenersProxyListener () {
 146.142 -        ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
 146.143 -        class E implements Executor {
 146.144 -            Runnable r;
 146.145 -            public void execute(Runnable command) {
 146.146 -                assertNull("NO previous", r);
 146.147 -                r = command;
 146.148 -            }
 146.149 -            public void perform() {
 146.150 -                assertNotNull("We shall have a runnable", r);
 146.151 -                r.run();
 146.152 -                r = null;
 146.153 -            }
 146.154 -        }
 146.155 -        E executor = new E();
 146.156 -                
 146.157 -
 146.158 -        final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
 146.159 -        final Object[] IGNORE = {
 146.160 -            ProxyLookup.ImmutableInternalData.EMPTY,
 146.161 -            ProxyLookup.ImmutableInternalData.EMPTY_ARR,
 146.162 -            ActiveQueue.queue(),
 146.163 -            Collections.emptyMap(),
 146.164 -            Collections.emptyList(),
 146.165 -            Collections.emptySet()
 146.166 -        };
 146.167 -        
 146.168 -        assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
 146.169 -        
 146.170 -        Lookup.Result<Object> res = lookup.lookup (template);
 146.171 -
 146.172 -        assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
 146.173 -        
 146.174 -        LL ll = new LL ();
 146.175 -        res.addLookupListener (ll);
 146.176 -        Collection allRes = res.allInstances ();
 146.177 -        
 146.178 -        lookup.setLookups (executor, new Lookup[0]);
 146.179 -        if (ll.getCount () != 0) {
 146.180 -           fail ("Calling setLookups (emptyarray) fired a change");
 146.181 -        }
 146.182 -        
 146.183 -        InstanceContent t = new InstanceContent();
 146.184 -        Lookup del = new AbstractLookup (t);
 146.185 -        t.add("Ahoj");
 146.186 -        lookup.setLookups (executor, new Lookup[] { del });
 146.187 -        assertEquals("No change yet", 0, ll.getCount());
 146.188 -        executor.perform();
 146.189 -        if (ll.getCount () != 1) {
 146.190 -            fail ("Changing lookups did not generate an event");
 146.191 -        }
 146.192 -        
 146.193 -        lookup.setLookups (executor, new Lookup[] { del });
 146.194 -        if (ll.getCount () != 0) {
 146.195 -           fail ("Calling setLookups (thesamearray) fired a change");
 146.196 -        }
 146.197 -    }
 146.198 -
 146.199 -    public void testSetLookups () throws Exception {
 146.200 -        AbstractLookup a1 = new AbstractLookup (new InstanceContent ());
 146.201 -        AbstractLookup a2 = new AbstractLookup (new InstanceContent ());
 146.202 -        
 146.203 -        InstanceContent i3 = new InstanceContent ();
 146.204 -        i3.add (i3);
 146.205 -        AbstractLookup a3 = new AbstractLookup (i3);
 146.206 -
 146.207 -        final ProxyLookup p = new ProxyLookup (new Lookup[] { a1, a2 });
 146.208 -        final Lookup.Result res1 = p.lookup (new Lookup.Template (Object.class));
 146.209 -        Collection c1 = res1.allInstances();
 146.210 -        
 146.211 -        Lookup.Result res2 = p.lookup (new Lookup.Template (String.class));
 146.212 -        Collection c2 = res2.allInstances ();
 146.213 -        
 146.214 -        
 146.215 -        assertTrue ("We need two results", res1 != res2);
 146.216 -
 146.217 -        final Object blocked = new Object ();
 146.218 -
 146.219 -        class L extends Object implements LookupListener {
 146.220 -            public void resultChanged (LookupEvent ev) {
 146.221 -                try {
 146.222 -                    res1.removeLookupListener(this);
 146.223 -                    
 146.224 -                    // waiting for second thread to start #111#
 146.225 -                    blocked.wait ();
 146.226 -
 146.227 -                } catch (Exception ex) {
 146.228 -                    ex.printStackTrace();
 146.229 -                    fail ("An exception occured ");
 146.230 -                }
 146.231 -            }
 146.232 -        }
 146.233 -        
 146.234 -        final L listener1 = new L ();
 146.235 -        res1.addLookupListener (listener1);
 146.236 -        
 146.237 -
 146.238 -        Runnable newLookupSetter = new Runnable() {
 146.239 -            public void run () {
 146.240 -                synchronized (blocked) {
 146.241 -                    try {
 146.242 -                        p.setLookups (new Lookup[0]);
 146.243 -                    } catch (Exception ex) {
 146.244 -                        ex.printStackTrace();
 146.245 -                        fail ("setLookups failed.");
 146.246 -                    } finally {
 146.247 -                        // starts the main thread #111#
 146.248 -                        blocked.notify ();
 146.249 -                    }
 146.250 -                }
 146.251 -            }
 146.252 -        };
 146.253 -        
 146.254 -        synchronized (blocked) {
 146.255 -            new Thread (newLookupSetter).start ();
 146.256 -            
 146.257 -            p.setLookups (new Lookup[] { a1, a2, a3 });
 146.258 -        }
 146.259 -    }
 146.260 -    
 146.261 -    public void testProxyLookupTemplateCaching(){
 146.262 -        Lookup lookups[] = new Lookup[1];
 146.263 -        doProxyLookupTemplateCaching(lookups, false);
 146.264 -    }
 146.265 -    
 146.266 -    public void testProxyLookupTemplateCachingOnSizeTwoArray() {
 146.267 -        Lookup lookups[] = new Lookup[2];
 146.268 -        lookups[1] = Lookup.EMPTY;
 146.269 -        doProxyLookupTemplateCaching(lookups, false);
 146.270 -    }
 146.271 -    public void testProxyLookupShallNotAllowModificationOfGetLookups(){
 146.272 -        Lookup lookups[] = new Lookup[1];
 146.273 -        doProxyLookupTemplateCaching(lookups, true);
 146.274 -    }
 146.275 -    
 146.276 -    public void testProxyLookupShallNotAllowModificationOfGetLookupsOnSizeTwoArray() {
 146.277 -        Lookup lookups[] = new Lookup[2];
 146.278 -        lookups[1] = Lookup.EMPTY;
 146.279 -        doProxyLookupTemplateCaching(lookups, true);
 146.280 -    }
 146.281 -    
 146.282 -    /** Index 0 of lookups will be modified, the rest is up to the 
 146.283 -     * setup code.
 146.284 -     */
 146.285 -    private void doProxyLookupTemplateCaching(Lookup[] lookups, boolean reget) {
 146.286 -        // Create MyProxyLookup with one lookup containing the String object
 146.287 -        InstanceContent inst = new InstanceContent();
 146.288 -        inst.add(new String("Hello World")); //NOI18N
 146.289 -        lookups[0] = new AbstractLookup(inst);
 146.290 -        ProxyLookup proxy = new ProxyLookup(lookups);
 146.291 -        if (reget) {
 146.292 -            lookups = proxy.getLookups();
 146.293 -        }
 146.294 -        
 146.295 -        // Performing template lookup for String object
 146.296 -        Lookup.Result result = proxy.lookup(new Lookup.Template(String.class, null, null));
 146.297 -        int stringTemplateResultSize = result.allInstances().size();
 146.298 -        assertEquals ("Ensure, there is only one instance of String.class in proxyLookup:", //NOI18N
 146.299 -                1, stringTemplateResultSize);
 146.300 -        
 146.301 -        // Changing lookup in proxy lookup, now it will contain 
 146.302 -        // StringBuffer Object instead of String
 146.303 -        InstanceContent ic2 = new InstanceContent();
 146.304 -        ic2.add(new Integer(1234567890));
 146.305 -        lookups[0] = new AbstractLookup(ic2);
 146.306 -        proxy.setLookups(lookups);
 146.307 -        
 146.308 -        assertEquals ("the old result is updated", 0, result.allInstances().size());
 146.309 -
 146.310 -        // Instance of String.class should not appear in proxyLookup
 146.311 -        Lookup.Result r2 = proxy.lookup(new Lookup.Template(String.class, null, null));
 146.312 -        assertEquals ("Instance of String.class should not appear in proxyLookup:", //NOI18N
 146.313 -                0, r2.allInstances().size());
 146.314 -
 146.315 -        Lookup.Result r3 = proxy.lookup(new Lookup.Template(Integer.class, null, null));
 146.316 -        assertEquals ("There is only one instance of Integer.class in proxyLookup:", //NOI18N
 146.317 -                1, r3.allInstances().size());
 146.318 -    }
 146.319 -    
 146.320 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
 146.321 -        doListeningAndQueryingByTwoListenersSetLookups(0, 1);
 146.322 -    }
 146.323 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
 146.324 -        doListeningAndQueryingByTwoListenersSetLookups(1, 1);        
 146.325 -    }
 146.326 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
 146.327 -        doListeningAndQueryingByTwoListenersSetLookups(2, 1);
 146.328 -    }
 146.329 -    
 146.330 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
 146.331 -        doListeningAndQueryingByTwoListenersSetLookups(0, 2);
 146.332 -    }
 146.333 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
 146.334 -        doListeningAndQueryingByTwoListenersSetLookups(1, 2);        
 146.335 -    }
 146.336 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
 146.337 -        doListeningAndQueryingByTwoListenersSetLookups(2, 2);
 146.338 -    }
 146.339 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
 146.340 -        doListeningAndQueryingByTwoListenersSetLookups(0, 22);
 146.341 -    }
 146.342 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
 146.343 -        doListeningAndQueryingByTwoListenersSetLookups(1, 22);        
 146.344 -    }
 146.345 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
 146.346 -        doListeningAndQueryingByTwoListenersSetLookups(2, 22);
 146.347 -    }
 146.348 -    
 146.349 -    private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth) {
 146.350 -        ProxyLookup orig = new ProxyLookup();
 146.351 -        ProxyLookup on = orig;
 146.352 -        
 146.353 -        while (--depth > 0) {
 146.354 -            on = new ProxyLookup(new Lookup[] { on });
 146.355 -        }
 146.356 -        
 146.357 -        
 146.358 -        final ProxyLookup lookup = on;
 146.359 -        
 146.360 -        class L implements LookupListener {
 146.361 -            Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
 146.362 -            Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
 146.363 -            Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
 146.364 -            
 146.365 -            {
 146.366 -                integer.addLookupListener(this);
 146.367 -                number.addLookupListener(this);
 146.368 -                serial.addLookupListener(this);
 146.369 -            }
 146.370 -            
 146.371 -            int round;
 146.372 -            
 146.373 -            public void resultChanged(LookupEvent ev) {
 146.374 -                Collection c1 = get(type, integer);
 146.375 -                Collection c2 = get(type, number);
 146.376 -                Collection c3 = get(type, serial);
 146.377 -                
 146.378 -                assertEquals("round " + round + " c1 vs. c2", c1, c2);
 146.379 -                assertEquals("round " + round + " c1 vs. c3", c1, c3);
 146.380 -                assertEquals("round " + round + " c2 vs. c3", c2, c3);
 146.381 -                
 146.382 -                round++;
 146.383 -            }            
 146.384 -
 146.385 -            private Collection get(int type, Lookup.Result res) {
 146.386 -                Collection c;
 146.387 -                switch(type) {
 146.388 -                    case 0: c = res.allInstances(); break;
 146.389 -                    case 1: c = res.allClasses(); break;
 146.390 -                    case 2: c = res.allItems(); break;
 146.391 -                    default: c = null; fail("Type: " + type); break;
 146.392 -                }
 146.393 -                
 146.394 -                assertNotNull(c);
 146.395 -                return new ArrayList(c);
 146.396 -            }
 146.397 -        }
 146.398 -        
 146.399 -        L listener = new L();
 146.400 -        listener.resultChanged(null);
 146.401 -        ArrayList arr = new ArrayList();
 146.402 -        for(int i = 0; i < 100; i++) {
 146.403 -            arr.add(new Integer(i));
 146.404 -            
 146.405 -            orig.setLookups(new Lookup[] { Lookups.fixed(arr.toArray()) });
 146.406 -        }
 146.407 -        
 146.408 -        assertEquals("3x100+1 checks", 301, listener.round);
 146.409 -    }
 146.410 -
 146.411 -    static Object holder;
 146.412 -    
 146.413 -    public void testProxyWithLiveResultCanBeCollected() {
 146.414 -        Lookup layer0 = Lookups.singleton("Hello");
 146.415 -        Lookup layer1 = new ProxyLookup(new Lookup[] { layer0 });
 146.416 -        Lookup layer2 = new ProxyLookup(new Lookup[] { layer1 });
 146.417 -        Lookup.Result result1 = layer1.lookup(new Lookup.Template(String.class));
 146.418 -
 146.419 -        assertEquals("One instance", 1, result1.allInstances().size());
 146.420 -
 146.421 -        // this will create ProxyLookup$R which listens on origResult
 146.422 -        Lookup.Result result2 = layer2.lookup(new Lookup.Template(String.class));
 146.423 -        
 146.424 -        // this line is necessary. W/o actually querying the result,
 146.425 -        // it will nether compute it nor attach the listener.
 146.426 -        assertEquals("One instance", 1, result2.allInstances().size());
 146.427 -        
 146.428 -        result2.addLookupListener(new LookupListener() {
 146.429 -            public void resultChanged(LookupEvent ev) {}
 146.430 -        });
 146.431 -        
 146.432 -        Reference ref = new WeakReference(layer2);
 146.433 -        layer2 = null;
 146.434 -        result2 = null;
 146.435 -        try {
 146.436 -            holder = result1;
 146.437 -            assertGC ("The proxy lookup not been garbage collected!", ref);
 146.438 -        } finally {
 146.439 -            holder = null;
 146.440 -        }
 146.441 -    }
 146.442 -    
 146.443 -    public void testArrayIndexAsInIssue119292() throws Exception {
 146.444 -        final ProxyLookup pl = new ProxyLookup();
 146.445 -        final int[] cnt = { 0 };
 146.446 -        
 146.447 -        class L extends Lookup {
 146.448 -            L[] set;
 146.449 -            Lookup l;
 146.450 -            
 146.451 -            public L(String s) {
 146.452 -                l = Lookups.singleton(s);
 146.453 -            }
 146.454 -            
 146.455 -            @Override
 146.456 -            public <T> T lookup(Class<T> clazz) {
 146.457 -                return l.lookup(clazz);
 146.458 -            }
 146.459 -
 146.460 -            @Override
 146.461 -            public <T> Result<T> lookup(Template<T> template) {
 146.462 -                return l.lookup(template);
 146.463 -            }
 146.464 -
 146.465 -            @Override
 146.466 -            @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
 146.467 -            public boolean equals(Object obj) {
 146.468 -                if (set != null) {
 146.469 -                    cnt[0]++;
 146.470 -                    pl.setLookups(set);
 146.471 -                }
 146.472 -                return super.equals(obj);
 146.473 -            }
 146.474 -
 146.475 -            @Override
 146.476 -            public int hashCode() {
 146.477 -                int hash = 3;
 146.478 -                return hash;
 146.479 -            }
 146.480 -        }
 146.481 -
 146.482 -        Result<String> res = pl.lookupResult(String.class);
 146.483 -        assertEquals(Collections.EMPTY_LIST, res.allItems());
 146.484 -        
 146.485 -        L[] old = { new L("A"), new L("B") };
 146.486 -        L[] now = { new L("C") };
 146.487 -        
 146.488 -        pl.setLookups(old);
 146.489 -        cnt[0] = 0;
 146.490 -        
 146.491 -        old[0].set = new L[0];
 146.492 -        pl.setLookups(now);
 146.493 -
 146.494 -        assertEquals("No call to equals", 0, cnt[0]);
 146.495 -        
 146.496 -        assertEquals("Still assigned to C", Collections.singletonList("C"), res.allInstances());
 146.497 -    }
 146.498 -    
 146.499 -    public void testArrayIndexWithAddRemoveListenerAsInIssue119292() throws Exception {
 146.500 -        final ProxyLookup pl = new ProxyLookup();
 146.501 -        final int[] cnt = { 0 };
 146.502 -        
 146.503 -        class L extends Lookup {
 146.504 -            L[] set;
 146.505 -            Lookup l;
 146.506 -            
 146.507 -            public L(String s) {
 146.508 -                l = Lookups.singleton(s);
 146.509 -            }
 146.510 -            
 146.511 -            @Override
 146.512 -            public <T> T lookup(Class<T> clazz) {
 146.513 -                return l.lookup(clazz);
 146.514 -            }
 146.515 -
 146.516 -            @Override
 146.517 -            public <T> Result<T> lookup(Template<T> template) {
 146.518 -                Result<T> r = l.lookup(template);
 146.519 -                return new R<T>(r);
 146.520 -            }
 146.521 -
 146.522 -            final class R<T> extends Result<T> {
 146.523 -                private Result<T> delegate;
 146.524 -
 146.525 -                public R(Result<T> delegate) {
 146.526 -                    this.delegate = delegate;
 146.527 -                }
 146.528 -                
 146.529 -                @Override
 146.530 -                public void addLookupListener(LookupListener l) {
 146.531 -                    cnt[0]++;
 146.532 -                    if (set != null) {
 146.533 -                        pl.setLookups(set);
 146.534 -                    }
 146.535 -                    delegate.addLookupListener(l);
 146.536 -                }
 146.537 -
 146.538 -                @Override
 146.539 -                public void removeLookupListener(LookupListener l) {
 146.540 -                    cnt[0]++;
 146.541 -                    if (set != null) {
 146.542 -                        pl.setLookups(set);
 146.543 -                    }
 146.544 -                    delegate.removeLookupListener(l);
 146.545 -                }
 146.546 -
 146.547 -                @Override
 146.548 -                public Collection<? extends T> allInstances() {
 146.549 -                    return delegate.allInstances();
 146.550 -                }
 146.551 -            }
 146.552 -        }
 146.553 -
 146.554 -        Result<String> res = pl.lookupResult(String.class);
 146.555 -        assertEquals(Collections.EMPTY_LIST, res.allItems());
 146.556 -        
 146.557 -        L[] old = { new L("A"), new L("B") };
 146.558 -        L[] now = { new L("C") };
 146.559 -        
 146.560 -        pl.setLookups(old);
 146.561 -        cnt[0] = 0;
 146.562 -        
 146.563 -        old[0].set = new L[0];
 146.564 -        pl.setLookups(now);
 146.565 -
 146.566 -        if (cnt[0] == 0) {
 146.567 -            fail("There should be calls to listeners");
 146.568 -        }
 146.569 -        
 146.570 -        assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances());
 146.571 -    }
 146.572 -    
 146.573 -    
 146.574 -    public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception {
 146.575 -        final ProxyLookup pl = new ProxyLookup();
 146.576 -        final int[] cnt = { 0 };
 146.577 -        
 146.578 -        class L extends Lookup {
 146.579 -            L[] set;
 146.580 -            Lookup l;
 146.581 -            Collection<? extends Serializable> res;
 146.582 -            
 146.583 -            public L(String s) {
 146.584 -                l = Lookups.singleton(s);
 146.585 -            }
 146.586 -            
 146.587 -            @Override
 146.588 -            public <T> T lookup(Class<T> clazz) {
 146.589 -                return l.lookup(clazz);
 146.590 -            }
 146.591 -
 146.592 -            @Override
 146.593 -            public <T> Result<T> lookup(Template<T> template) {
 146.594 -                cnt[0]++;
 146.595 -                if (set != null) {
 146.596 -                    pl.setLookups(set);
 146.597 -                    res = pl.lookupAll(Serializable.class);
 146.598 -                }
 146.599 -                Result<T> r = l.lookup(template);
 146.600 -                return r;
 146.601 -            }
 146.602 -        }
 146.603 -
 146.604 -        L[] now = { new L("A"), new L("B") };
 146.605 -        L[] old = { new L("C") };
 146.606 -        pl.setLookups(old);
 146.607 -        old[0].set = now;
 146.608 -        
 146.609 -        Result<String> res = pl.lookupResult(String.class);
 146.610 -        assertEquals("New items visible", 2, res.allItems().size());
 146.611 -        
 146.612 -        
 146.613 -        pl.setLookups(new L("X"), new L("Y"), new L("Z"));
 146.614 -    }
 146.615 -    
 146.616 -    public void testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679() throws Exception {
 146.617 -        final ProxyLookup pl = new ProxyLookup();
 146.618 -        final int[] cnt = { 0 };
 146.619 -        
 146.620 -        class L extends Lookup {
 146.621 -            L[] set;
 146.622 -            Lookup l;
 146.623 -            Collection<? extends Serializable> res;
 146.624 -            
 146.625 -            public L(String s) {
 146.626 -                l = Lookups.singleton(s);
 146.627 -            }
 146.628 -            
 146.629 -            @Override
 146.630 -            public <T> T lookup(Class<T> clazz) {
 146.631 -                return l.lookup(clazz);
 146.632 -            }
 146.633 -
 146.634 -            @Override
 146.635 -            public <T> Result<T> lookup(Template<T> template) {
 146.636 -                cnt[0]++;
 146.637 -                if (set != null) {
 146.638 -                    pl.setLookups(set);
 146.639 -                    res = pl.lookupAll(Serializable.class);
 146.640 -                }
 146.641 -                Result<T> r = l.lookup(template);
 146.642 -                return r;
 146.643 -            }
 146.644 -        }
 146.645 -
 146.646 -        L dupl = new L("A");
 146.647 -        L[] now = { dupl };
 146.648 -        L[] old = { new L("C") };
 146.649 -        pl.setLookups(old);
 146.650 -        old[0].set = now;
 146.651 -        
 146.652 -        Result<String> res = pl.lookupResult(String.class);
 146.653 -        assertEquals("New items visible", 1, res.allItems().size());
 146.654 -        
 146.655 -        
 146.656 -        pl.setLookups(old);
 146.657 -    }
 146.658 -}
   147.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SimpleLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   147.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.3 @@ -1,351 +0,0 @@
   147.4 -/*
   147.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   147.6 - *
   147.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   147.8 - *
   147.9 - * The contents of this file are subject to the terms of either the GNU
  147.10 - * General Public License Version 2 only ("GPL") or the Common
  147.11 - * Development and Distribution License("CDDL") (collectively, the
  147.12 - * "License"). You may not use this file except in compliance with the
  147.13 - * License. You can obtain a copy of the License at
  147.14 - * http://www.netbeans.org/cddl-gplv2.html
  147.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  147.16 - * specific language governing permissions and limitations under the
  147.17 - * License.  When distributing the software, include this License Header
  147.18 - * Notice in each file and include the License file at
  147.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  147.20 - * particular file as subject to the "Classpath" exception as provided
  147.21 - * by Sun in the GPL Version 2 section of the License file that
  147.22 - * accompanied this code. If applicable, add the following below the
  147.23 - * License Header, with the fields enclosed by brackets [] replaced by
  147.24 - * your own identifying information:
  147.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  147.26 - *
  147.27 - * Contributor(s):
  147.28 - *
  147.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  147.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
  147.31 - * Microsystems, Inc. All Rights Reserved.
  147.32 - *
  147.33 - * If you wish your version of this file to be governed by only the CDDL
  147.34 - * or only the GPL Version 2, indicate your decision by adding
  147.35 - * "[Contributor] elects to include this software in this distribution
  147.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  147.37 - * single choice of license, a recipient has the option to distribute
  147.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  147.39 - * to extend the choice of license to its licensees as provided above.
  147.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  147.41 - * Version 2 license, then the option applies only if the new code is
  147.42 - * made subject to such option by the copyright holder.
  147.43 - */
  147.44 -
  147.45 -package org.openide.util.lookup;
  147.46 -
  147.47 -import java.util.ArrayList;
  147.48 -import java.util.Arrays;
  147.49 -import java.util.Collection;
  147.50 -import java.util.List;
  147.51 -import java.util.Set;
  147.52 -import org.netbeans.junit.NbTestCase;
  147.53 -import org.openide.util.Lookup;
  147.54 -
  147.55 -/**
  147.56 - * Tests for class SimpleLookup.
  147.57 - * @author David Strupl
  147.58 - */
  147.59 -public class SimpleLookupTest extends NbTestCase {
  147.60 -
  147.61 -    public SimpleLookupTest(String testName) {
  147.62 -        super(testName);
  147.63 -    }
  147.64 -
  147.65 -    public void testEmptyLookup() {
  147.66 -        assertSize("Lookup.EMPTY should be small", 8, Lookup.EMPTY);
  147.67 -    }
  147.68 -
  147.69 -    /**
  147.70 -     * Simple tests testing singleton lookup.
  147.71 -     */
  147.72 -    public void testSingleton() {
  147.73 -        //
  147.74 -        Object orig = new Object();
  147.75 -        Lookup p1 = Lookups.singleton(orig);
  147.76 -        Object obj = p1.lookup(Object.class);
  147.77 -        assertTrue(obj == orig);
  147.78 -        assertNull(p1.lookup(String.class)); 
  147.79 -        assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
  147.80 -        //
  147.81 -        Lookup p2 = Lookups.singleton("test");
  147.82 -        assertNotNull(p2.lookup(Object.class));
  147.83 -        assertNotNull(p2.lookup(String.class));
  147.84 -        assertNotNull(p2.lookup(java.io.Serializable.class));
  147.85 -    }
  147.86 -    
  147.87 -    public void testEmptyFixed() {
  147.88 -        Lookup l = Lookups.fixed();
  147.89 -        assertSize("Lookups.fixed() for empty list of items should be small", 8, l);
  147.90 -        assertSame(Lookup.EMPTY, l);
  147.91 -    }
  147.92 -
  147.93 -    public void testSingleItemFixed() {
  147.94 -        Object o = new Object();
  147.95 -        Lookup l = Lookups.fixed(o);
  147.96 -        assertSize("Lookups.fixed(o) for a single item should be small", 24, l);
  147.97 -    }
  147.98 -
  147.99 -    /**
 147.100 -     * Simple tests testing fixed lookup.
 147.101 -     */
 147.102 -    public void testFixed() {
 147.103 -        //
 147.104 -        Object[] orig = new Object[] { new Object(), new Object() };
 147.105 -        Lookup p1 = Lookups.fixed(orig);
 147.106 -        Object obj = p1.lookup(Object.class);
 147.107 -        assertTrue(obj == orig[0] || obj == orig[1]);
 147.108 -        assertNull(p1.lookup(String.class)); 
 147.109 -        //
 147.110 -        String[] s = new String[] { "test1", "test2" };
 147.111 -        Lookup p2 = Lookups.fixed((Object[]) s);
 147.112 -        Object obj2 = p2.lookup(Object.class);
 147.113 -        assertNotNull(obj2);
 147.114 -        if (obj2 != s[0] && obj2 != s[1]) {
 147.115 -            fail("Returned objects are not the originals");
 147.116 -        }
 147.117 -        assertNotNull(p2.lookup(String.class));
 147.118 -        assertNotNull(p2.lookup(java.io.Serializable.class));
 147.119 -        Lookup.Template<String> t = new Lookup.Template<String>(String.class);
 147.120 -        Lookup.Result<String> r = p2.lookup(t);
 147.121 -        Collection<? extends String> all = r.allInstances();
 147.122 -        assertTrue(all.size() == 2);
 147.123 -        for (String o : all) {
 147.124 -            assertTrue("allInstances contains wrong objects", o.equals(s[0]) || o.equals(s[1]));
 147.125 -        }
 147.126 -        
 147.127 -        try {
 147.128 -            Lookups.fixed(new Object[] {null});
 147.129 -            fail("No nulls are allowed");
 147.130 -        } catch (NullPointerException ex) {
 147.131 -            // ok, NPE is what we want
 147.132 -        }        
 147.133 -    }
 147.134 -
 147.135 -    public void testFixedSubtypes() {
 147.136 -        class A {}
 147.137 -        class B extends A {}
 147.138 -        Lookup l = Lookups.fixed(new A(), new B());
 147.139 -        assertEquals(1, l.lookupAll(B.class).size());
 147.140 -        assertEquals(2, l.lookupAll(A.class).size());
 147.141 -    }
 147.142 -
 147.143 -    /**
 147.144 -     * Simple tests testing converting lookup.
 147.145 -     */
 147.146 -    public void testConverting() {
 147.147 -        //
 147.148 -        String[] orig = new String[] { TestConvertor.TEST1, TestConvertor.TEST2 };
 147.149 -        TestConvertor convertor = new TestConvertor();
 147.150 -        Lookup p1 = Lookups.fixed(orig, convertor);
 147.151 -        assertNull("Converting from String to Integer - it should not find String in result", p1.lookup(String.class));
 147.152 -        assertNotNull(p1.lookup(Integer.class));
 147.153 -        assertNotNull(p1.lookup(Integer.class));
 147.154 -        assertTrue("Convertor should be called only once.", convertor.getNumberOfConvertCalls() == 1); 
 147.155 -        Lookup.Template<Integer> t = new Lookup.Template<Integer>(Integer.class);
 147.156 -        Lookup.Result<Integer> r = p1.lookup(t);
 147.157 -        Collection<? extends Integer> all = r.allInstances();
 147.158 -        assertTrue(all.size() == 2);
 147.159 -        for (int i : all) {
 147.160 -            assertTrue("allInstances contains wrong objects", i == TestConvertor.t1 || i == TestConvertor.t2);
 147.161 -        }
 147.162 -    }
 147.163 -    
 147.164 -    private static class TestConvertor implements InstanceContent.Convertor<String,Integer> {
 147.165 -        static final String TEST1 = "test1";
 147.166 -        static final int t1 = 1;
 147.167 -        static final String TEST2 = "test2";
 147.168 -        static final int t2 = 2;
 147.169 -        
 147.170 -        private int numberOfConvertCalls = 0;
 147.171 -        
 147.172 -        public Integer convert(String obj) {
 147.173 -            numberOfConvertCalls++;
 147.174 -            if (obj.equals(TEST1)) {
 147.175 -                return t1;
 147.176 -            }
 147.177 -            if (obj.equals(TEST2)) {
 147.178 -                return t2;
 147.179 -            }
 147.180 -            throw new IllegalArgumentException();
 147.181 -        }
 147.182 -        
 147.183 -        public String displayName(String obj) {
 147.184 -            return obj;
 147.185 -        }
 147.186 -        
 147.187 -        public String id(String obj) {
 147.188 -            if (obj.equals(TEST1)) {
 147.189 -                return TEST1;
 147.190 -            }
 147.191 -            if (obj.equals(TEST2)) {
 147.192 -                return TEST2;
 147.193 -            }
 147.194 -            return null;
 147.195 -        }
 147.196 -        
 147.197 -        public Class<? extends Integer> type(String obj) {
 147.198 -            return Integer.class;
 147.199 -        }
 147.200 -        
 147.201 -        int getNumberOfConvertCalls() { 
 147.202 -            return numberOfConvertCalls;
 147.203 -        }
 147.204 -    }
 147.205 -    
 147.206 -    public void testLookupItem() {
 147.207 -        SomeInst inst = new SomeInst();
 147.208 -        Lookup.Item item = Lookups.lookupItem(inst, "XYZ");
 147.209 -        
 147.210 -        assertTrue("Wrong instance", item.getInstance() == inst);
 147.211 -        assertTrue("Wrong instance class", item.getType() == inst.getClass());
 147.212 -        assertEquals("Wrong id", "XYZ", item.getId());
 147.213 -
 147.214 -        item = Lookups.lookupItem(inst, null);
 147.215 -        assertNotNull("Id must never be null", item.getId());
 147.216 -    }
 147.217 -
 147.218 -    public void testLookupItemEquals() {
 147.219 -        SomeInst instA = new SomeInst();
 147.220 -        SomeInst instB = new SomeInst();
 147.221 -        Lookup.Item itemA = Lookups.lookupItem(instA, null);
 147.222 -        Lookup.Item itemB = Lookups.lookupItem(instB, null);
 147.223 -        
 147.224 -        assertTrue("Lookup items shouldn't be equal", !itemA.equals(itemB) && !itemB.equals(itemA));
 147.225 -
 147.226 -        itemA = Lookups.lookupItem(instA, null);
 147.227 -        itemB = Lookups.lookupItem(instA, null); // same instance
 147.228 -
 147.229 -        assertTrue("Lookup items should be equal", itemA.equals(itemB) && itemB.equals(itemA));
 147.230 -        assertTrue("Lookup items hashcode should be same", itemA.hashCode() == itemB.hashCode());
 147.231 -
 147.232 -        itemA = Lookups.lookupItem(new String("VOKURKA"), null);
 147.233 -        itemB = Lookups.lookupItem(new String("VOKURKA"), null);
 147.234 -
 147.235 -        assertTrue("Lookup items shouldn't be equal (2)", !itemA.equals(itemB) && !itemB.equals(itemA));
 147.236 -    }
 147.237 -    
 147.238 -    public void testAllClassesIssue42399 () throws Exception {
 147.239 -        Object[] arr = { "Ahoj", new Object () };
 147.240 -        
 147.241 -        Lookup l = Lookups.fixed (arr);
 147.242 -        
 147.243 -        Set<Class<? extends Object>> s = l.lookup(new Lookup.Template<Object>(Object.class)).allClasses();
 147.244 -        
 147.245 -        assertEquals ("Two there", 2, s.size ());
 147.246 -        assertTrue ("Contains Object.class", s.contains (Object.class));
 147.247 -        assertTrue ("Contains string", s.contains (String.class));
 147.248 -        
 147.249 -    }
 147.250 -
 147.251 -    public void testLookupItemEarlyInitializationProblem() {
 147.252 -        InstanceContent ic = new InstanceContent();
 147.253 -        AbstractLookup al = new AbstractLookup(ic);
 147.254 -        LI item = new LI();
 147.255 -        List<AbstractLookup.Pair> pairs1 = new ArrayList<AbstractLookup.Pair>();
 147.256 -        List<AbstractLookup.Pair> pairs2 = new ArrayList<AbstractLookup.Pair>();
 147.257 -        
 147.258 -        assertEquals("Item's instance shouldn't be requested", 0, item.cnt);
 147.259 -
 147.260 -        pairs1.add(new ItemPair<Object>(Lookups.<Object>lookupItem(new SomeInst(), null)));
 147.261 -        pairs1.add(new ItemPair<Object>(item));
 147.262 -        pairs1.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
 147.263 -
 147.264 -        pairs2.add(new ItemPair<Object>(item));
 147.265 -        pairs2.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
 147.266 -
 147.267 -        ic.setPairs(pairs1);
 147.268 -        ic.setPairs(pairs2);
 147.269 -
 147.270 -        assertEquals("Item's instance shouldn't be requested when added to lookup", 0, item.cnt);
 147.271 -        
 147.272 -        LI item2 = al.lookup(LI.class);
 147.273 -        assertEquals("Item's instance should be requested", 1, item.cnt);
 147.274 -    }
 147.275 -
 147.276 -    public void testConvenienceMethods() throws Exception {
 147.277 -        // Just check signatures and basic behavior of #73848.
 147.278 -        Lookup l = Lookups.fixed(new Object[] {1, "hello", 2, "goodbye"});
 147.279 -        Collection<? extends Integer> ints = l.lookupAll(Integer.class);
 147.280 -        assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
 147.281 -        Lookup.Result<Integer> r = l.lookupResult(Integer.class);
 147.282 -        ints = r.allInstances();
 147.283 -        assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
 147.284 -    }
 147.285 -    
 147.286 -    private static class SomeInst { }
 147.287 -    
 147.288 -    private static class LI extends Lookup.Item<Object> {
 147.289 -
 147.290 -        public long cnt = 0;
 147.291 -        
 147.292 -        public String getDisplayName() {
 147.293 -            return getId();
 147.294 -        }
 147.295 -
 147.296 -        public String getId() {
 147.297 -            return getClass() + "@" + hashCode();
 147.298 -        }
 147.299 -
 147.300 -        public Object getInstance() {
 147.301 -            cnt++;
 147.302 -            return this;
 147.303 -        }
 147.304 -
 147.305 -        public Class<? extends Object> getType() {
 147.306 -            return getClass();
 147.307 -        }
 147.308 -    } // End of LI class
 147.309 -
 147.310 -    private static class ItemPair<T> extends AbstractLookup.Pair<T> {
 147.311 -        
 147.312 -        private AbstractLookup.Item<T> item;
 147.313 -        
 147.314 -        public ItemPair(Lookup.Item<T> i) {
 147.315 -            this.item = i;
 147.316 -        }
 147.317 -
 147.318 -        protected boolean creatorOf(Object obj) {
 147.319 -            return item.getInstance() == obj;
 147.320 -        }
 147.321 -
 147.322 -        public String getDisplayName() {
 147.323 -            return item.getDisplayName ();
 147.324 -        }
 147.325 -
 147.326 -        public String getId() {
 147.327 -            return item.getId ();
 147.328 -        }
 147.329 -
 147.330 -        public T getInstance() {
 147.331 -            return item.getInstance ();
 147.332 -        }
 147.333 -
 147.334 -        public Class<? extends T> getType() {
 147.335 -            return item.getType ();
 147.336 -        }
 147.337 -
 147.338 -        protected boolean instanceOf(Class<?> c) {
 147.339 -            return c.isAssignableFrom(getType());
 147.340 -        }
 147.341 -
 147.342 -        public @Override boolean equals(Object o) {
 147.343 -            if (o instanceof ItemPair) {
 147.344 -                ItemPair p = (ItemPair)o;
 147.345 -                return item.equals (p.item);
 147.346 -            }
 147.347 -            return false;
 147.348 -        }
 147.349 -
 147.350 -        public @Override int hashCode() {
 147.351 -            return item.hashCode ();
 147.352 -        }
 147.353 -    } // end of ItemPair
 147.354 -}
   148.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SimpleProxyLookupIssue42244Test.java	Thu Dec 10 19:23:25 2009 -0500
   148.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.3 @@ -1,120 +0,0 @@
   148.4 -/*
   148.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   148.6 - *
   148.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   148.8 - *
   148.9 - * The contents of this file are subject to the terms of either the GNU
  148.10 - * General Public License Version 2 only ("GPL") or the Common
  148.11 - * Development and Distribution License("CDDL") (collectively, the
  148.12 - * "License"). You may not use this file except in compliance with the
  148.13 - * License. You can obtain a copy of the License at
  148.14 - * http://www.netbeans.org/cddl-gplv2.html
  148.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  148.16 - * specific language governing permissions and limitations under the
  148.17 - * License.  When distributing the software, include this License Header
  148.18 - * Notice in each file and include the License file at
  148.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  148.20 - * particular file as subject to the "Classpath" exception as provided
  148.21 - * by Sun in the GPL Version 2 section of the License file that
  148.22 - * accompanied this code. If applicable, add the following below the
  148.23 - * License Header, with the fields enclosed by brackets [] replaced by
  148.24 - * your own identifying information:
  148.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  148.26 - *
  148.27 - * Contributor(s):
  148.28 - *
  148.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  148.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  148.31 - * Microsystems, Inc. All Rights Reserved.
  148.32 - *
  148.33 - * If you wish your version of this file to be governed by only the CDDL
  148.34 - * or only the GPL Version 2, indicate your decision by adding
  148.35 - * "[Contributor] elects to include this software in this distribution
  148.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  148.37 - * single choice of license, a recipient has the option to distribute
  148.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  148.39 - * to extend the choice of license to its licensees as provided above.
  148.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  148.41 - * Version 2 license, then the option applies only if the new code is
  148.42 - * made subject to such option by the copyright holder.
  148.43 - */
  148.44 -
  148.45 -package org.openide.util.lookup;
  148.46 -
  148.47 -import java.lang.ref.WeakReference;
  148.48 -import java.util.*;
  148.49 -import junit.framework.*;
  148.50 -import org.netbeans.junit.*;
  148.51 -import org.openide.util.Lookup;
  148.52 -
  148.53 -/** To simulate issue 42244.
  148.54 - */
  148.55 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  148.56 -public class SimpleProxyLookupIssue42244Test extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
  148.57 -    public SimpleProxyLookupIssue42244Test (java.lang.String testName) {
  148.58 -        super(testName, null);
  148.59 -    }
  148.60 -
  148.61 -    public static Test suite() {
  148.62 -        // return new SimpleProxyLookupIssue42244Test("testGarbageCollect");
  148.63 -        return new NbTestSuite(SimpleProxyLookupIssue42244Test.class);
  148.64 -    }
  148.65 -    
  148.66 -    /** Creates an lookup for given lookup. This class just returns 
  148.67 -     * the object passed in, but subclasses can be different.
  148.68 -     * @param lookup in lookup
  148.69 -     * @return a lookup to use
  148.70 -     */
  148.71 -    public Lookup createLookup (final Lookup lookup) {
  148.72 -        class C implements Lookup.Provider {
  148.73 -            public Lookup getLookup () {
  148.74 -                return lookup;
  148.75 -            }
  148.76 -        }
  148.77 -        return Lookups.proxy (new C ());
  148.78 -    }
  148.79 -    
  148.80 -    public Lookup createInstancesLookup (InstanceContent ic) {
  148.81 -        return new KeepResultsProxyLookup (new AbstractLookup (ic));
  148.82 -    }
  148.83 -    
  148.84 -    public void clearCaches () {
  148.85 -        KeepResultsProxyLookup k = (KeepResultsProxyLookup)this.instanceLookup;
  148.86 -        
  148.87 -        ArrayList toGC = new ArrayList ();
  148.88 -        Iterator it = k.allQueries.iterator ();
  148.89 -        while (it.hasNext ()) {
  148.90 -            Lookup.Result r = (Lookup.Result)it.next ();
  148.91 -            toGC.add (new WeakReference (r));
  148.92 -        }
  148.93 -        
  148.94 -        k.allQueries = null;
  148.95 -        
  148.96 -        it = toGC.iterator ();
  148.97 -        while (it.hasNext ()) {
  148.98 -            WeakReference r = (WeakReference)it.next ();
  148.99 -            assertGC ("Trying to release all results from memory", r);
 148.100 -        }
 148.101 -    }
 148.102 -    
 148.103 -    class KeepResultsProxyLookup extends ProxyLookup {
 148.104 -        private ArrayList allQueries = new ArrayList ();
 148.105 -        private ThreadLocal in = new ThreadLocal ();
 148.106 -        
 148.107 -        public KeepResultsProxyLookup (Lookup delegate) {
 148.108 -            super (new Lookup[] { delegate });
 148.109 -        }
 148.110 -        
 148.111 -        @Override
 148.112 -        protected void beforeLookup (org.openide.util.Lookup.Template template) {
 148.113 -            super.beforeLookup (template);
 148.114 -            if (allQueries != null && in.get () == null) {
 148.115 -                in.set (this);
 148.116 -                Lookup.Result res = lookup (template);
 148.117 -                allQueries.add (res);
 148.118 -                in.set (null);
 148.119 -            }
 148.120 -        }
 148.121 -        
 148.122 -    }
 148.123 -}
   149.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SimpleProxyLookupSpeedIssue42244Test.java	Thu Dec 10 19:23:25 2009 -0500
   149.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.3 @@ -1,118 +0,0 @@
   149.4 -/*
   149.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   149.6 - *
   149.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   149.8 - *
   149.9 - * The contents of this file are subject to the terms of either the GNU
  149.10 - * General Public License Version 2 only ("GPL") or the Common
  149.11 - * Development and Distribution License("CDDL") (collectively, the
  149.12 - * "License"). You may not use this file except in compliance with the
  149.13 - * License. You can obtain a copy of the License at
  149.14 - * http://www.netbeans.org/cddl-gplv2.html
  149.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  149.16 - * specific language governing permissions and limitations under the
  149.17 - * License.  When distributing the software, include this License Header
  149.18 - * Notice in each file and include the License file at
  149.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  149.20 - * particular file as subject to the "Classpath" exception as provided
  149.21 - * by Sun in the GPL Version 2 section of the License file that
  149.22 - * accompanied this code. If applicable, add the following below the
  149.23 - * License Header, with the fields enclosed by brackets [] replaced by
  149.24 - * your own identifying information:
  149.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  149.26 - *
  149.27 - * Contributor(s):
  149.28 - *
  149.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  149.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  149.31 - * Microsystems, Inc. All Rights Reserved.
  149.32 - *
  149.33 - * If you wish your version of this file to be governed by only the CDDL
  149.34 - * or only the GPL Version 2, indicate your decision by adding
  149.35 - * "[Contributor] elects to include this software in this distribution
  149.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  149.37 - * single choice of license, a recipient has the option to distribute
  149.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  149.39 - * to extend the choice of license to its licensees as provided above.
  149.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  149.41 - * Version 2 license, then the option applies only if the new code is
  149.42 - * made subject to such option by the copyright holder.
  149.43 - */
  149.44 -
  149.45 -package org.openide.util.lookup;
  149.46 -
  149.47 -import java.util.HashSet;
  149.48 -import java.util.Set;
  149.49 -import org.netbeans.junit.NbTestCase;
  149.50 -
  149.51 -import org.netbeans.junit.RandomlyFails;
  149.52 -import org.openide.util.Lookup;
  149.53 -
  149.54 -/**
  149.55 - * @author  Petr Nejedly, adapted to test by Jaroslav Tulach
  149.56 - */
  149.57 -@RandomlyFails // NB-Core-Build #1847
  149.58 -public class SimpleProxyLookupSpeedIssue42244Test extends NbTestCase {
  149.59 -
  149.60 -    public SimpleProxyLookupSpeedIssue42244Test (String name) {
  149.61 -        super (name);
  149.62 -    }
  149.63 -
  149.64 -    public void testCompareTheSpeed () {
  149.65 -        String content1 = "String1";
  149.66 -        String content2 = "String2";
  149.67 -        
  149.68 -        Lookup fixed1 = Lookups.singleton(content1);
  149.69 -        Lookup fixed2 = Lookups.singleton(content2);
  149.70 -        
  149.71 -        MyProvider provider = new MyProvider();
  149.72 -        provider.setLookup(fixed1);
  149.73 -        
  149.74 -        Lookup top = Lookups.proxy(provider);
  149.75 -
  149.76 -        Lookup.Result<String> r0 = top.lookupResult(String.class);
  149.77 -        r0.allInstances();
  149.78 -
  149.79 -        long time = System.currentTimeMillis();
  149.80 -        top.lookupAll(String.class);
  149.81 -        long withOneResult = System.currentTimeMillis() - time;
  149.82 -
  149.83 -     
  149.84 -        Set<Object> results = new HashSet<Object>();
  149.85 -        for (int i=0; i<10000; i++) {
  149.86 -            Lookup.Result<String> res = top.lookupResult(String.class);
  149.87 -            results.add (res);
  149.88 -            res.allInstances();
  149.89 -        }
  149.90 -        
  149.91 -        provider.setLookup(fixed2);
  149.92 -
  149.93 -        time = System.currentTimeMillis();
  149.94 -        top.lookupAll(String.class);
  149.95 -        long withManyResults = System.currentTimeMillis() - time;
  149.96 -        
  149.97 -        // if the measurement takes less then 10ms, pretend 10ms
  149.98 -        if (withManyResults < 10) {
  149.99 -            withManyResults = 10;
 149.100 -        }
 149.101 -        if (withOneResult < 10) {
 149.102 -            withOneResult = 10;
 149.103 -        }
 149.104 -
 149.105 -        if (withManyResults >= 10 * withOneResult) {
 149.106 -            fail ("With many results the test runs too long.\n With many: " + withManyResults + "\n With one : " + withOneResult);
 149.107 -        }
 149.108 -    }
 149.109 -    
 149.110 -    private static class MyProvider implements Lookup.Provider {
 149.111 -        private Lookup lookup;
 149.112 -        public Lookup getLookup() {
 149.113 -            return lookup;
 149.114 -        }
 149.115 -        
 149.116 -        void setLookup(Lookup lookup) {
 149.117 -            this.lookup = lookup;
 149.118 -        }
 149.119 -    }
 149.120 -    
 149.121 -}
   150.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SimpleProxyLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   150.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.3 @@ -1,73 +0,0 @@
   150.4 -/*
   150.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   150.6 - *
   150.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   150.8 - *
   150.9 - * The contents of this file are subject to the terms of either the GNU
  150.10 - * General Public License Version 2 only ("GPL") or the Common
  150.11 - * Development and Distribution License("CDDL") (collectively, the
  150.12 - * "License"). You may not use this file except in compliance with the
  150.13 - * License. You can obtain a copy of the License at
  150.14 - * http://www.netbeans.org/cddl-gplv2.html
  150.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  150.16 - * specific language governing permissions and limitations under the
  150.17 - * License.  When distributing the software, include this License Header
  150.18 - * Notice in each file and include the License file at
  150.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  150.20 - * particular file as subject to the "Classpath" exception as provided
  150.21 - * by Sun in the GPL Version 2 section of the License file that
  150.22 - * accompanied this code. If applicable, add the following below the
  150.23 - * License Header, with the fields enclosed by brackets [] replaced by
  150.24 - * your own identifying information:
  150.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  150.26 - *
  150.27 - * Contributor(s):
  150.28 - *
  150.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  150.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  150.31 - * Microsystems, Inc. All Rights Reserved.
  150.32 - *
  150.33 - * If you wish your version of this file to be governed by only the CDDL
  150.34 - * or only the GPL Version 2, indicate your decision by adding
  150.35 - * "[Contributor] elects to include this software in this distribution
  150.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  150.37 - * single choice of license, a recipient has the option to distribute
  150.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  150.39 - * to extend the choice of license to its licensees as provided above.
  150.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  150.41 - * Version 2 license, then the option applies only if the new code is
  150.42 - * made subject to such option by the copyright holder.
  150.43 - */
  150.44 -
  150.45 -package org.openide.util.lookup;
  150.46 -
  150.47 -import java.lang.ref.WeakReference;
  150.48 -import org.netbeans.junit.NbTestCase;
  150.49 -import org.openide.util.Lookup;
  150.50 -import org.openide.util.Lookup.Provider;
  150.51 -
  150.52 -/**
  150.53 - *
  150.54 - * @author Jan Lahoda
  150.55 - */
  150.56 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  150.57 -public class SimpleProxyLookupTest extends NbTestCase {
  150.58 -
  150.59 -    public SimpleProxyLookupTest(String testName) {
  150.60 -        super(testName);
  150.61 -    }
  150.62 -
  150.63 -    public void test69810() throws Exception {
  150.64 -        Lookup.Template t = new Lookup.Template(String.class);
  150.65 -        SimpleProxyLookup spl = new SimpleProxyLookup(new Provider() {
  150.66 -            public Lookup getLookup() {
  150.67 -                return Lookups.fixed(new Object[] {"test1", "test2"});
  150.68 -            }
  150.69 -        });
  150.70 -        
  150.71 -        assertGC("", new WeakReference(spl.lookup(t)));
  150.72 -        
  150.73 -        spl.lookup(new Lookup.Template(Object.class)).allInstances();
  150.74 -    }
  150.75 -    
  150.76 -}
   151.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SingletonLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   151.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.3 @@ -1,113 +0,0 @@
   151.4 -/*
   151.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   151.6 - * 
   151.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
   151.8 - * 
   151.9 - * The contents of this file are subject to the terms of either the GNU
  151.10 - * General Public License Version 2 only ("GPL") or the Common
  151.11 - * Development and Distribution License("CDDL") (collectively, the
  151.12 - * "License"). You may not use this file except in compliance with the
  151.13 - * License. You can obtain a copy of the License at
  151.14 - * http://www.netbeans.org/cddl-gplv2.html
  151.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  151.16 - * specific language governing permissions and limitations under the
  151.17 - * License.  When distributing the software, include this License Header
  151.18 - * Notice in each file and include the License file at
  151.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  151.20 - * particular file as subject to the "Classpath" exception as provided
  151.21 - * by Sun in the GPL Version 2 section of the License file that
  151.22 - * accompanied this code. If applicable, add the following below the
  151.23 - * License Header, with the fields enclosed by brackets [] replaced by
  151.24 - * your own identifying information:
  151.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  151.26 - * 
  151.27 - * If you wish your version of this file to be governed by only the CDDL
  151.28 - * or only the GPL Version 2, indicate your decision by adding
  151.29 - * "[Contributor] elects to include this software in this distribution
  151.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  151.31 - * single choice of license, a recipient has the option to distribute
  151.32 - * your version of this file under either the CDDL, the GPL Version 2 or
  151.33 - * to extend the choice of license to its licensees as provided above.
  151.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  151.35 - * Version 2 license, then the option applies only if the new code is
  151.36 - * made subject to such option by the copyright holder.
  151.37 - * 
  151.38 - * Contributor(s):
  151.39 - * 
  151.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  151.41 - */
  151.42 -
  151.43 -package org.openide.util.lookup;
  151.44 -
  151.45 -import java.util.Collection;
  151.46 -import org.netbeans.junit.NbTestCase;
  151.47 -import org.openide.util.Lookup;
  151.48 -
  151.49 -/**
  151.50 - * Contains tests of class {@code SingletonLookup}.
  151.51 - *
  151.52 - * @author  Marian Petras
  151.53 - */
  151.54 -public class SingletonLookupTest extends NbTestCase {
  151.55 -    
  151.56 -    public SingletonLookupTest(String testName) {
  151.57 -        super(testName);
  151.58 -    }
  151.59 -
  151.60 -    public void testBasics() {
  151.61 -        Object orig = new Object();
  151.62 -        Lookup p1 = new SingletonLookup(orig);
  151.63 -        Object obj = p1.lookup(Object.class);
  151.64 -        assertTrue(obj == orig);
  151.65 -        assertNull(p1.lookup(String.class)); 
  151.66 -        assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
  151.67 -        //
  151.68 -        Lookup p2 = new SingletonLookup("test");
  151.69 -        assertNotNull(p2.lookup(Object.class));
  151.70 -        assertNotNull(p2.lookup(String.class));
  151.71 -        assertNotNull(p2.lookup(java.io.Serializable.class));
  151.72 -    }
  151.73 -
  151.74 -    public void testId() {
  151.75 -        Object orig = new Object();
  151.76 -        Collection allInstances;
  151.77 -
  151.78 -        Lookup l = new SingletonLookup(orig, "id");
  151.79 -
  151.80 -        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, null, null)).allInstances();
  151.81 -        assertNotNull(allInstances);
  151.82 -        assertFalse(allInstances.isEmpty());
  151.83 -        assertEquals(1, allInstances.size());
  151.84 -        assertTrue(allInstances.iterator().next() == orig);
  151.85 -
  151.86 -        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "id", null)).allInstances();
  151.87 -        assertNotNull(allInstances);
  151.88 -        assertFalse(allInstances.isEmpty());
  151.89 -        assertEquals(1, allInstances.size());
  151.90 -        assertTrue(allInstances.iterator().next() == orig);
  151.91 -
  151.92 -        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "not", null)).allInstances();
  151.93 -        assertNotNull(allInstances);
  151.94 -        assertTrue(allInstances.isEmpty());
  151.95 -
  151.96 -        allInstances = l.lookup(new Lookup.Template<String>(String.class, null, null)).allInstances();
  151.97 -        assertNotNull(allInstances);
  151.98 -        assertTrue(allInstances.isEmpty());
  151.99 -
 151.100 -        allInstances = l.lookup(new Lookup.Template<String>(String.class, "id", null)).allInstances();
 151.101 -        assertNotNull(allInstances);
 151.102 -        assertTrue(allInstances.isEmpty());
 151.103 -
 151.104 -        allInstances = l.lookup(new Lookup.Template<String>(String.class, "not", null)).allInstances();
 151.105 -        assertNotNull(allInstances);
 151.106 -        assertTrue(allInstances.isEmpty());
 151.107 -    }
 151.108 -
 151.109 -    public void testSize() {
 151.110 -        final Object obj = new Object();
 151.111 -        assertSize("The singleton lookup instance should be small",
 151.112 -                   24,
 151.113 -                   new SingletonLookup(obj));
 151.114 -    }
 151.115 -
 151.116 -}
   152.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/problem100320.txt	Thu Dec 10 19:23:25 2009 -0500
   152.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.3 @@ -1,17 +0,0 @@
   152.4 -:java.io.IOException:
   152.5 -java.nio.charset.CharacterCodingException
   152.6 -java.io.EOFException
   152.7 -java.io.FileNotFoundException
   152.8 -java.io.InterruptedIOException
   152.9 -java.net.MalformedURLException
  152.10 -java.io.IOException
  152.11 -java.io.UnsupportedEncodingException
  152.12 -java.io.NotActiveException
  152.13 -java.io.StreamCorruptedException
  152.14 -java.io.UTFDataFormatException
  152.15 -java.util.zip.ZipException
  152.16 -java.util.jar.JarException
  152.17 -:java.util.Comparator:
  152.18 -org.bar.Comparator3
  152.19 -org.bar.Comparator2
  152.20 -#position=5
   153.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/services-jar-1.txt	Thu Dec 10 19:23:25 2009 -0500
   153.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.3 @@ -1,17 +0,0 @@
   153.4 -:somedummyfile:
   153.5 -org.foo.Interface
   153.6 -:java.lang.Runnable:
   153.7 -org.foo.impl.Runnable1
   153.8 -:java.util.Comparator:
   153.9 -#some comment
  153.10 -org.foo.impl.Comparator1
  153.11 -#position=10
  153.12 -#som comment2
  153.13 -:java.util.Iterator:
  153.14 -org.foo.impl.Iterator1
  153.15 -:org.foo.Interface:
  153.16 -# Some header info, maybe.
  153.17 -
  153.18 -# Our first impl here
  153.19 -org.foo.impl.Implementation1
  153.20 -
   154.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/services-jar-2.txt	Thu Dec 10 19:23:25 2009 -0500
   154.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.3 @@ -1,10 +0,0 @@
   154.4 -:java.lang.Runnable:
   154.5 -#-org.foo.impl.Runnable1
   154.6 -:java.util.Comparator:
   154.7 -org.bar.Comparator2
   154.8 -#position=5
   154.9 -:java.util.Iterator:
  154.10 -org.bar.Iterator2
  154.11 -#position=100
  154.12 -:org.foo.Interface:
  154.13 -org.bar.Implementation2
   155.1 --- a/openide.util/test/unit/src/org/openide/util/test/AnnotationProcessorTestUtils.java	Thu Dec 10 19:23:25 2009 -0500
   155.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.3 @@ -1,139 +0,0 @@
   155.4 -/*
   155.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   155.6 - *
   155.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
   155.8 - *
   155.9 - * The contents of this file are subject to the terms of either the GNU
  155.10 - * General Public License Version 2 only ("GPL") or the Common
  155.11 - * Development and Distribution License("CDDL") (collectively, the
  155.12 - * "License"). You may not use this file except in compliance with the
  155.13 - * License. You can obtain a copy of the License at
  155.14 - * http://www.netbeans.org/cddl-gplv2.html
  155.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  155.16 - * specific language governing permissions and limitations under the
  155.17 - * License.  When distributing the software, include this License Header
  155.18 - * Notice in each file and include the License file at
  155.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  155.20 - * particular file as subject to the "Classpath" exception as provided
  155.21 - * by Sun in the GPL Version 2 section of the License file that
  155.22 - * accompanied this code. If applicable, add the following below the
  155.23 - * License Header, with the fields enclosed by brackets [] replaced by
  155.24 - * your own identifying information:
  155.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  155.26 - *
  155.27 - * If you wish your version of this file to be governed by only the CDDL
  155.28 - * or only the GPL Version 2, indicate your decision by adding
  155.29 - * "[Contributor] elects to include this software in this distribution
  155.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  155.31 - * single choice of license, a recipient has the option to distribute
  155.32 - * your version of this file under either the CDDL, the GPL Version 2 or
  155.33 - * to extend the choice of license to its licensees as provided above.
  155.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  155.35 - * Version 2 license, then the option applies only if the new code is
  155.36 - * made subject to such option by the copyright holder.
  155.37 - *
  155.38 - * Contributor(s):
  155.39 - *
  155.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  155.41 - */
  155.42 -
  155.43 -package org.openide.util.test;
  155.44 -
  155.45 -import java.io.File;
  155.46 -import java.io.FileWriter;
  155.47 -import java.io.IOException;
  155.48 -import java.io.OutputStream;
  155.49 -import java.io.PrintWriter;
  155.50 -import java.io.Writer;
  155.51 -import java.util.ArrayList;
  155.52 -import java.util.List;
  155.53 -import java.util.regex.Pattern;
  155.54 -import javax.tools.JavaCompiler;
  155.55 -import javax.tools.ToolProvider;
  155.56 -import junit.framework.Assert;
  155.57 -
  155.58 -/**
  155.59 - * Utilities useful to those testing JSR 269 annotation processors.
  155.60 - * <p>If you just want to test that the output of the processor is correct,
  155.61 - * you do not need to do anything special:
  155.62 - * just use the annotation on some sample classes nested inside your unit test.
  155.63 - * They will be processed, and you check that your SPI loads them correctly.
  155.64 - * These utilities are useful mainly in case you want to check that the processor
  155.65 - * rejects erroneous sources, and that any messages it prints are reasonable;
  155.66 - * that it behaves correctly on incremental compilations; etc.
  155.67 - */
  155.68 -public class AnnotationProcessorTestUtils {
  155.69 -
  155.70 -    private AnnotationProcessorTestUtils() {}
  155.71 -
  155.72 -    /**
  155.73 -     * Create a source file.
  155.74 -     * @param dir source root
  155.75 -     * @param clazz a fully-qualified class name
  155.76 -     * @param content lines of text (skip package decl)
  155.77 -     */
  155.78 -    public static void makeSource(File dir, String clazz, String... content) throws IOException {
  155.79 -        File f = new File(dir, clazz.replace('.', File.separatorChar) + ".java");
  155.80 -        f.getParentFile().mkdirs();
  155.81 -        Writer w = new FileWriter(f);
  155.82 -        try {
  155.83 -            PrintWriter pw = new PrintWriter(w);
  155.84 -            String pkg = clazz.replaceFirst("\\.[^.]+$", "");
  155.85 -            if (!pkg.equals(clazz)) {
  155.86 -                pw.println("package " + pkg + ";");
  155.87 -            }
  155.88 -            for (String line : content) {
  155.89 -                pw.println(line);
  155.90 -            }
  155.91 -            pw.flush();
  155.92 -        } finally {
  155.93 -            w.close();
  155.94 -        }
  155.95 -    }
  155.96 -
  155.97 -    /**
  155.98 -     * Run the Java compiler.
  155.99 -     * (A JSR 199 implementation must be available.)
 155.100 -     * @param src a source root (runs javac on all *.java it finds matching {@code srcIncludes})
 155.101 -     * @param srcIncludes a pattern of source files names without path to compile (useful for testing incremental compiles), or null for all
 155.102 -     * @param dest a dest dir to compile classes to
 155.103 -     * @param cp classpath entries; if null, use Java classpath of test
 155.104 -     * @param stderr output stream to print messages to, or null for test console (i.e. do not capture)
 155.105 -     * @return true if compilation succeeded, false if it failed
 155.106 -     */
 155.107 -    public static boolean runJavac(File src, String srcIncludes, File dest, File[] cp, OutputStream stderr) {
 155.108 -        List<String> args = new ArrayList<String>();
 155.109 -        args.add("-classpath");
 155.110 -        if (cp != null) {
 155.111 -            StringBuffer b = new StringBuffer();
 155.112 -            for (File entry : cp) {
 155.113 -                b.append(File.pathSeparatorChar);
 155.114 -                b.append(entry.getAbsolutePath());
 155.115 -            }
 155.116 -            args.add(b.toString());
 155.117 -        } else {
 155.118 -            args.add(System.getProperty("java.class.path"));
 155.119 -        }
 155.120 -        args.add("-d");
 155.121 -        args.add(dest.getAbsolutePath());
 155.122 -        args.add("-sourcepath");
 155.123 -        args.add(src.getAbsolutePath());
 155.124 -        dest.mkdirs();
 155.125 -        scan(args, src, srcIncludes);
 155.126 -        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 155.127 -        Assert.assertNotNull("no JSR 199 compiler impl found; try e.g.: " +
 155.128 -                "test.unit.run.cp.extra=${nb_all}/apisupport.harness/external/openjdk-javac-6-b12.jar", compiler);
 155.129 -        //System.err.println("running javac with args: " + args);
 155.130 -        return compiler.run(null, null, stderr, args.toArray(new String[args.size()])) == 0;
 155.131 -    }
 155.132 -    private static void scan(List<String> names, File f, String includes) {
 155.133 -        if (f.isDirectory()) {
 155.134 -            for (File kid : f.listFiles()) {
 155.135 -                scan(names, kid, includes);
 155.136 -            }
 155.137 -        } else if (f.getName().endsWith(".java") && (includes == null || Pattern.compile(includes).matcher(f.getName()).find())) {
 155.138 -            names.add(f.getAbsolutePath());
 155.139 -        }
 155.140 -    }
 155.141 -
 155.142 -}
   156.1 --- a/openide.util/test/unit/src/org/openide/util/test/MockLookup.java	Thu Dec 10 19:23:25 2009 -0500
   156.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.3 @@ -1,135 +0,0 @@
   156.4 -/*
   156.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   156.6 - *
   156.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   156.8 - *
   156.9 - * The contents of this file are subject to the terms of either the GNU
  156.10 - * General Public License Version 2 only ("GPL") or the Common
  156.11 - * Development and Distribution License("CDDL") (collectively, the
  156.12 - * "License"). You may not use this file except in compliance with the
  156.13 - * License. You can obtain a copy of the License at
  156.14 - * http://www.netbeans.org/cddl-gplv2.html
  156.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  156.16 - * specific language governing permissions and limitations under the
  156.17 - * License.  When distributing the software, include this License Header
  156.18 - * Notice in each file and include the License file at
  156.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  156.20 - * particular file as subject to the "Classpath" exception as provided
  156.21 - * by Sun in the GPL Version 2 section of the License file that
  156.22 - * accompanied this code. If applicable, add the following below the
  156.23 - * License Header, with the fields enclosed by brackets [] replaced by
  156.24 - * your own identifying information:
  156.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  156.26 - *
  156.27 - * Contributor(s):
  156.28 - *
  156.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  156.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
  156.31 - * Microsystems, Inc. All Rights Reserved.
  156.32 - *
  156.33 - * If you wish your version of this file to be governed by only the CDDL
  156.34 - * or only the GPL Version 2, indicate your decision by adding
  156.35 - * "[Contributor] elects to include this software in this distribution
  156.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  156.37 - * single choice of license, a recipient has the option to distribute
  156.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  156.39 - * to extend the choice of license to its licensees as provided above.
  156.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  156.41 - * Version 2 license, then the option applies only if the new code is
  156.42 - * made subject to such option by the copyright holder.
  156.43 - */
  156.44 -
  156.45 -package org.openide.util.test;
  156.46 -
  156.47 -import java.lang.reflect.Field;
  156.48 -import java.util.Collection;
  156.49 -import static junit.framework.Assert.*;
  156.50 -import org.openide.util.Lookup;
  156.51 -import org.openide.util.lookup.Lookups;
  156.52 -import org.openide.util.lookup.ProxyLookup;
  156.53 -
  156.54 -/**
  156.55 - * Mock implementation of system default lookup suitable for use in unit tests.
  156.56 - * The initial value just contains classpath services.
  156.57 - */
  156.58 -public class MockLookup extends ProxyLookup {
  156.59 -
  156.60 -    private static MockLookup DEFAULT;
  156.61 -    private static boolean making = false;
  156.62 -    private static volatile boolean ready;
  156.63 -
  156.64 -    static {
  156.65 -        making = true;
  156.66 -        try {
  156.67 -            System.setProperty("org.openide.util.Lookup", MockLookup.class.getName());
  156.68 -            if (Lookup.getDefault().getClass() != MockLookup.class) {
  156.69 -                // Someone else initialized lookup first. Try to force our way.
  156.70 -                Field defaultLookup = Lookup.class.getDeclaredField("defaultLookup");
  156.71 -                defaultLookup.setAccessible(true);
  156.72 -                defaultLookup.set(null, null);
  156.73 -            }
  156.74 -            assertEquals(MockLookup.class, Lookup.getDefault().getClass());
  156.75 -        } catch (Exception x) {
  156.76 -            throw new ExceptionInInitializerError(x);
  156.77 -        } finally {
  156.78 -            making = false;
  156.79 -        }
  156.80 -    }
  156.81 -
  156.82 -    /** Do not call this directly! */
  156.83 -    public MockLookup() {
  156.84 -        assertTrue(making);
  156.85 -        assertNull(DEFAULT);
  156.86 -        DEFAULT = this;
  156.87 -    }
  156.88 -
  156.89 -    /**
  156.90 -     * Just ensures that this lookup is default lookup, but does not actually change its content.
  156.91 -     * Useful mainly if you have some test utility method which calls foreign code which might use default lookup,
  156.92 -     * and you want to ensure that any users of mock lookup will see the correct default lookup right away,
  156.93 -     * even if they have not yet called {@link #setLookup} or {@link #setInstances}.
  156.94 -     */
  156.95 -    public static void init() {
  156.96 -        if (!ready) {
  156.97 -            setInstances();
  156.98 -        }
  156.99 -    }
 156.100 -
 156.101 -    /**
 156.102 -     * Sets the global default lookup with zero or more delegate lookups.
 156.103 -     * Caution: if you don't include Lookups.metaInfServices, you may have trouble,
 156.104 -     * e.g. {@link #makeScratchDir} will not work.
 156.105 -     * Most of the time you should use {@link #setInstances} instead.
 156.106 -     */
 156.107 -    public static void setLookup(Lookup... lookups) {
 156.108 -        ready = true;
 156.109 -        DEFAULT.setLookups(lookups);
 156.110 -    }
 156.111 -
 156.112 -    /**
 156.113 -     * Sets the global default lookup with some fixed instances.
 156.114 -     * Will also include (at a lower priority) a {@link ClassLoader},
 156.115 -     * and services found from <code>META-INF/services/*</code> in the classpath.
 156.116 -     */
 156.117 -    public static void setInstances(Object... instances) {
 156.118 -        ClassLoader l = MockLookup.class.getClassLoader();
 156.119 -        setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
 156.120 -    }
 156.121 -    /**
 156.122 -     * Sets the global default lookup with some fixed instances and
 156.123 -     * content read from Services folder from system file system.
 156.124 -     * Will also include (at a lower priority) a {@link ClassLoader},
 156.125 -     * and services found from <code>META-INF/services/*</code> in the classpath.
 156.126 -     */
 156.127 -    public static void setLayersAndInstances(Object... instances) {
 156.128 -        ClassLoader l = MockLookup.class.getClassLoader();
 156.129 -        if (l != Lookup.getDefault().lookup(ClassLoader.class)) {
 156.130 -            setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
 156.131 -        }
 156.132 -        Lookup projects = Lookups.forPath("Services");
 156.133 -        Collection<?> initialize = projects.lookupAll(Object.class);
 156.134 -        //System.err.println("all: " + initialize);
 156.135 -        setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l), projects);
 156.136 -    }
 156.137 -
 156.138 -}
   157.1 --- a/openide.util/test/unit/src/org/openide/util/test/MockLookupTest.java	Thu Dec 10 19:23:25 2009 -0500
   157.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.3 @@ -1,66 +0,0 @@
   157.4 -/*
   157.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   157.6 - *
   157.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   157.8 - *
   157.9 - * The contents of this file are subject to the terms of either the GNU
  157.10 - * General Public License Version 2 only ("GPL") or the Common
  157.11 - * Development and Distribution License("CDDL") (collectively, the
  157.12 - * "License"). You may not use this file except in compliance with the
  157.13 - * License. You can obtain a copy of the License at
  157.14 - * http://www.netbeans.org/cddl-gplv2.html
  157.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  157.16 - * specific language governing permissions and limitations under the
  157.17 - * License.  When distributing the software, include this License Header
  157.18 - * Notice in each file and include the License file at
  157.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  157.20 - * particular file as subject to the "Classpath" exception as provided
  157.21 - * by Sun in the GPL Version 2 section of the License file that
  157.22 - * accompanied this code. If applicable, add the following below the
  157.23 - * License Header, with the fields enclosed by brackets [] replaced by
  157.24 - * your own identifying information:
  157.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  157.26 - *
  157.27 - * Contributor(s):
  157.28 - *
  157.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  157.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
  157.31 - * Microsystems, Inc. All Rights Reserved.
  157.32 - *
  157.33 - * If you wish your version of this file to be governed by only the CDDL
  157.34 - * or only the GPL Version 2, indicate your decision by adding
  157.35 - * "[Contributor] elects to include this software in this distribution
  157.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  157.37 - * single choice of license, a recipient has the option to distribute
  157.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  157.39 - * to extend the choice of license to its licensees as provided above.
  157.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  157.41 - * Version 2 license, then the option applies only if the new code is
  157.42 - * made subject to such option by the copyright holder.
  157.43 - */
  157.44 -
  157.45 -package org.openide.util.test;
  157.46 -
  157.47 -import junit.framework.TestCase;
  157.48 -import org.openide.util.Lookup;
  157.49 -
  157.50 -public class MockLookupTest extends TestCase {
  157.51 -
  157.52 -    // XXX test:
  157.53 -    // setLookup with one or more lookup args does not use M-I/s
  157.54 -    // still works if another Lookup.getDefault was set before
  157.55 -
  157.56 -    public MockLookupTest(String n) {
  157.57 -        super(n);
  157.58 -    }
  157.59 -
  157.60 -    public void testSetLookup() throws Exception {
  157.61 -        MockLookup.setInstances("hello");
  157.62 -        assertEquals("initial lookup works", "hello", Lookup.getDefault().lookup(String.class));
  157.63 -        MockLookup.setInstances("goodbye");
  157.64 -        assertEquals("modified lookup works", "goodbye", Lookup.getDefault().lookup(String.class));
  157.65 -        MockLookup.setInstances();
  157.66 -        assertEquals("cleared lookup works", null, Lookup.getDefault().lookup(String.class));
  157.67 -    }
  157.68 -
  157.69 -}