Moving lookup related classes into separate openide.util.lookup module separate-lookup-170056
authorJaroslav Tulach <jtulach@netbeans.org>
Sat, 31 Oct 2009 15:28:13 +0100
branchseparate-lookup-170056
changeset 841fd5b0861df41
parent 840 cacaeb2ec7f3
child 842 2e54b07fbdbb
Moving lookup related classes into separate openide.util.lookup module
openide.util.lookup/build.xml
openide.util.lookup/manifest.mf
openide.util.lookup/nbproject/project.properties
openide.util.lookup/nbproject/project.xml
openide.util.lookup/src/org/netbeans/modules/openide/util/ActiveQueue.java
openide.util.lookup/src/org/netbeans/modules/openide/util/NamedServicesProvider.java
openide.util.lookup/src/org/openide/util/Lookup.java
openide.util.lookup/src/org/openide/util/LookupEvent.java
openide.util.lookup/src/org/openide/util/LookupListener.java
openide.util.lookup/src/org/openide/util/lookup/ALPairComparator.java
openide.util.lookup/src/org/openide/util/lookup/AbstractLookup.java
openide.util.lookup/src/org/openide/util/lookup/ArrayStorage.java
openide.util.lookup/src/org/openide/util/lookup/Bundle.properties
openide.util.lookup/src/org/openide/util/lookup/DelegatingStorage.java
openide.util.lookup/src/org/openide/util/lookup/ExcludingLookup.java
openide.util.lookup/src/org/openide/util/lookup/InheritanceTree.java
openide.util.lookup/src/org/openide/util/lookup/InstanceContent.java
openide.util.lookup/src/org/openide/util/lookup/Lookups.java
openide.util.lookup/src/org/openide/util/lookup/MetaInfServicesLookup.java
openide.util.lookup/src/org/openide/util/lookup/ProxyLookup.java
openide.util.lookup/src/org/openide/util/lookup/ServiceProvider.java
openide.util.lookup/src/org/openide/util/lookup/ServiceProviders.java
openide.util.lookup/src/org/openide/util/lookup/SimpleLookup.java
openide.util.lookup/src/org/openide/util/lookup/SimpleProxyLookup.java
openide.util.lookup/src/org/openide/util/lookup/SingletonLookup.java
openide.util.lookup/src/org/openide/util/lookup/WaitableResult.java
openide.util.lookup/src/org/openide/util/lookup/doc-files/index.html
openide.util.lookup/src/org/openide/util/lookup/doc-files/lookup-api.html
openide.util.lookup/src/org/openide/util/lookup/doc-files/lookup-spi.html
openide.util.lookup/src/org/openide/util/lookup/package.html
openide.util.lookup/test/unit/src/org/bar/Comparator2.java
openide.util.lookup/test/unit/src/org/bar/Comparator3.java
openide.util.lookup/test/unit/src/org/bar/Implementation2.java
openide.util.lookup/test/unit/src/org/bar/Iterator2.java
openide.util.lookup/test/unit/src/org/foo/Interface.java
openide.util.lookup/test/unit/src/org/foo/impl/Comparator1.java
openide.util.lookup/test/unit/src/org/foo/impl/Implementation1.java
openide.util.lookup/test/unit/src/org/foo/impl/Iterator1.java
openide.util.lookup/test/unit/src/org/foo/impl/Runnable1.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupArrayStorageTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupAsynchExecutorTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupExecutorTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupMemoryTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/InheritanceTreeTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/InitializationBug44134Test.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/KomrskaLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/LookupBugTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/LookupsProxyTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.txt
openide.util.lookup/test/unit/src/org/openide/util/lookup/NamedServicesLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/PathInLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/PrefixServicesLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/ProxyLookupEventIssue136866Test.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/SimpleLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/SimpleProxyLookupIssue42244Test.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/SimpleProxyLookupSpeedIssue42244Test.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/SimpleProxyLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/SingletonLookupTest.java
openide.util.lookup/test/unit/src/org/openide/util/lookup/problem100320.txt
openide.util.lookup/test/unit/src/org/openide/util/lookup/services-jar-1.txt
openide.util.lookup/test/unit/src/org/openide/util/lookup/services-jar-2.txt
openide.util.lookup/test/unit/src/org/openide/util/test/MockLookup.java
openide.util.lookup/test/unit/src/org/openide/util/test/MockLookupTest.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/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/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/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/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/build.xml	Sat Oct 31 15:28:13 2009 +0100
     1.3 @@ -0,0 +1,5 @@
     1.4 +<?xml version="1.0" encoding="UTF-8"?>
     1.5 +<project basedir="." default="netbeans" name="openide.util.lookup">
     1.6 +    <description>Builds, tests, and runs the project org.openide.util.lookup</description>
     1.7 +    <import file="../nbbuild/templates/projectized.xml"/>
     1.8 +</project>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/openide.util.lookup/manifest.mf	Sat Oct 31 15:28:13 2009 +0100
     2.3 @@ -0,0 +1,5 @@
     2.4 +Manifest-Version: 1.0
     2.5 +OpenIDE-Module: org.openide.util.lookup
     2.6 +OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties
     2.7 +OpenIDE-Module-Specification-Version: 8.0
     2.8 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/openide.util.lookup/nbproject/project.properties	Sat Oct 31 15:28:13 2009 +0100
     3.3 @@ -0,0 +1,43 @@
     3.4 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3.5 +#
     3.6 +# Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
     3.7 +#
     3.8 +# The contents of this file are subject to the terms of either the GNU
     3.9 +# General Public License Version 2 only ("GPL") or the Common
    3.10 +# Development and Distribution License("CDDL") (collectively, the
    3.11 +# "License"). You may not use this file except in compliance with the
    3.12 +# License. You can obtain a copy of the License at
    3.13 +# http://www.netbeans.org/cddl-gplv2.html
    3.14 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    3.15 +# specific language governing permissions and limitations under the
    3.16 +# License.  When distributing the software, include this License Header
    3.17 +# Notice in each file and include the License file at
    3.18 +# nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    3.19 +# particular file as subject to the "Classpath" exception as provided
    3.20 +# by Sun in the GPL Version 2 section of the License file that
    3.21 +# accompanied this code. If applicable, add the following below the
    3.22 +# License Header, with the fields enclosed by brackets [] replaced by
    3.23 +# your own identifying information:
    3.24 +# "Portions Copyrighted [year] [name of copyright owner]"
    3.25 +#
    3.26 +# Contributor(s):
    3.27 +#
    3.28 +# The Original Software is NetBeans. The Initial Developer of the Original
    3.29 +# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
    3.30 +# Microsystems, Inc. All Rights Reserved.
    3.31 +#
    3.32 +# If you wish your version of this file to be governed by only the CDDL
    3.33 +# or only the GPL Version 2, indicate your decision by adding
    3.34 +# "[Contributor] elects to include this software in this distribution
    3.35 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
    3.36 +# single choice of license, a recipient has the option to distribute
    3.37 +# your version of this file under either the CDDL, the GPL Version 2 or
    3.38 +# to extend the choice of license to its licensees as provided above.
    3.39 +# However, if you add GPL Version 2 code and therefore, elected the GPL
    3.40 +# Version 2 license, then the option applies only if the new code is
    3.41 +# made subject to such option by the copyright holder.
    3.42 +
    3.43 +module.jar.dir=lib
    3.44 +is.autoload=true
    3.45 +javac.source=1.5
    3.46 +javac.compilerargs=-Xlint -Xlint:-serial
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/openide.util.lookup/nbproject/project.xml	Sat Oct 31 15:28:13 2009 +0100
     4.3 @@ -0,0 +1,28 @@
     4.4 +<?xml version="1.0" encoding="UTF-8"?>
     4.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
     4.6 +    <type>org.netbeans.modules.apisupport.project</type>
     4.7 +    <configuration>
     4.8 +        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
     4.9 +            <code-name-base>org.openide.util.lookup</code-name-base>
    4.10 +            <module-dependencies/>
    4.11 +            <test-dependencies>
    4.12 +                <test-type>
    4.13 +                    <name>unit</name>
    4.14 +                    <test-dependency>
    4.15 +                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
    4.16 +                        <compile-dependency/>
    4.17 +                    </test-dependency>
    4.18 +                    <test-dependency>
    4.19 +                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
    4.20 +                        <recursive/>
    4.21 +                        <compile-dependency/>
    4.22 +                    </test-dependency>
    4.23 +                </test-type>
    4.24 +            </test-dependencies>
    4.25 +            <public-packages>
    4.26 +                <package>org.openide.util</package>
    4.27 +                <package>org.openide.util.lookup</package>
    4.28 +            </public-packages>
    4.29 +        </data>
    4.30 +    </configuration>
    4.31 +</project>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/ActiveQueue.java	Sat Oct 31 15:28:13 2009 +0100
     5.3 @@ -0,0 +1,108 @@
     5.4 +package org.netbeans.modules.openide.util;
     5.5 +
     5.6 +import java.lang.ref.Reference;
     5.7 +import java.lang.ref.ReferenceQueue;
     5.8 +import java.util.logging.Level;
     5.9 +import java.util.logging.Logger;
    5.10 +
    5.11 +/**
    5.12 + * Implementation of the active reference queue.
    5.13 + */
    5.14 +public final class ActiveQueue extends ReferenceQueue<Object> implements Runnable {
    5.15 +
    5.16 +    private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
    5.17 +    private static ActiveQueue activeReferenceQueue;
    5.18 +    
    5.19 +    /** number of known outstanding references */
    5.20 +    private int count;
    5.21 +    private boolean deprecated;
    5.22 +
    5.23 +    ActiveQueue(boolean deprecated) {
    5.24 +        super();
    5.25 +        this.deprecated = deprecated;
    5.26 +    }
    5.27 +
    5.28 +    public static synchronized ReferenceQueue<Object> queue() {
    5.29 +        if (activeReferenceQueue == null) {
    5.30 +            activeReferenceQueue = new ActiveQueue(false);
    5.31 +        }
    5.32 +
    5.33 +        activeReferenceQueue.ping();
    5.34 +
    5.35 +        return activeReferenceQueue;
    5.36 +    }
    5.37 +
    5.38 +    @Override
    5.39 +    public Reference<Object> poll() {
    5.40 +        throw new UnsupportedOperationException();
    5.41 +    }
    5.42 +
    5.43 +    @Override
    5.44 +    public Reference<Object> remove(long timeout) throws IllegalArgumentException, InterruptedException {
    5.45 +        throw new InterruptedException();
    5.46 +    }
    5.47 +
    5.48 +    @Override
    5.49 +    public Reference<Object> remove() throws InterruptedException {
    5.50 +        throw new InterruptedException();
    5.51 +    }
    5.52 +
    5.53 +    public void run() {
    5.54 +        while (true) {
    5.55 +            try {
    5.56 +                Reference<?> ref = super.remove(0);
    5.57 +                LOGGER.finer("dequeued reference");
    5.58 +                if (!(ref instanceof Runnable)) {
    5.59 +                    LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass());
    5.60 +                    continue;
    5.61 +                }
    5.62 +                if (deprecated) {
    5.63 +                    LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue");
    5.64 +                }
    5.65 +                // do the cleanup
    5.66 +                try {
    5.67 +                    ((Runnable) ref).run();
    5.68 +                } catch (ThreadDeath td) {
    5.69 +                    throw td;
    5.70 +                } catch (Throwable t) {
    5.71 +                    // Should not happen.
    5.72 +                    // If it happens, it is a bug in client code, notify!
    5.73 +                    LOGGER.log(Level.WARNING, null, t);
    5.74 +                } finally {
    5.75 +                    // to allow GC
    5.76 +                    ref = null;
    5.77 +                }
    5.78 +            } catch (InterruptedException ex) {
    5.79 +                // Can happen during VM shutdown, it seems. Ignore.
    5.80 +                continue;
    5.81 +            }
    5.82 +            synchronized (this) {
    5.83 +                assert count > 0;
    5.84 +                count--;
    5.85 +                if (count == 0) {
    5.86 +                    // We have processed all we have to process (for now at least).
    5.87 +                    // Could be restarted later if ping() called again.
    5.88 +                    // This could also happen in case someone called queue() once and tried
    5.89 +                    // to use it for several references; in that case run() might never be called on
    5.90 +                    // the later ones to be collected. Can't really protect against that situation.
    5.91 +                    // See issue #86625 for details.
    5.92 +                    LOGGER.fine("stopping thread");
    5.93 +                    break;
    5.94 +                }
    5.95 +            }
    5.96 +        }
    5.97 +    }
    5.98 +
    5.99 +    synchronized void ping() {
   5.100 +        if (count == 0) {
   5.101 +            Thread t = new Thread(this, "Active Reference Queue Daemon");
   5.102 +            t.setPriority(Thread.MIN_PRIORITY);
   5.103 +            t.setDaemon(true);
   5.104 +            t.start();
   5.105 +            LOGGER.fine("starting thread");
   5.106 +        } else {
   5.107 +            LOGGER.finer("enqueuing reference");
   5.108 +        }
   5.109 +        count++;
   5.110 +    }
   5.111 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/openide.util.lookup/src/org/netbeans/modules/openide/util/NamedServicesProvider.java	Sat Oct 31 15:28:13 2009 +0100
     6.3 @@ -0,0 +1,81 @@
     6.4 +/*
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + *
     6.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
     6.8 + *
     6.9 + * The contents of this file are subject to the terms of either the GNU
    6.10 + * General Public License Version 2 only ("GPL") or the Common
    6.11 + * Development and Distribution License("CDDL") (collectively, the
    6.12 + * "License"). You may not use this file except in compliance with the
    6.13 + * License. You can obtain a copy of the License at
    6.14 + * http://www.netbeans.org/cddl-gplv2.html
    6.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    6.16 + * specific language governing permissions and limitations under the
    6.17 + * License.  When distributing the software, include this License Header
    6.18 + * Notice in each file and include the License file at
    6.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    6.20 + * particular file as subject to the "Classpath" exception as provided
    6.21 + * by Sun in the GPL Version 2 section of the License file that
    6.22 + * accompanied this code. If applicable, add the following below the
    6.23 + * License Header, with the fields enclosed by brackets [] replaced by
    6.24 + * your own identifying information:
    6.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    6.26 + *
    6.27 + * Contributor(s):
    6.28 + *
    6.29 + * The Original Software is NetBeans. The Initial Developer of the Original
    6.30 + * Software is Sun Microsystems, Inc.
    6.31 + *
    6.32 + * Portions Copyrighted 2006 Sun Microsystems, Inc.
    6.33 + */
    6.34 +
    6.35 +package org.netbeans.modules.openide.util;
    6.36 +
    6.37 +import java.lang.ref.Reference;
    6.38 +import java.lang.ref.WeakReference;
    6.39 +import java.util.Collections;
    6.40 +import java.util.HashMap;
    6.41 +import java.util.Map;
    6.42 +import org.openide.util.Lookup;
    6.43 +import org.openide.util.lookup.Lookups;
    6.44 +
    6.45 +/** Interface for core/startup and core/settings
    6.46 + * to provide lookup over system filesystem.
    6.47 + *
    6.48 + * @author Jaroslav Tulach
    6.49 + */
    6.50 +public abstract class NamedServicesProvider {
    6.51 +
    6.52 +    private static final Map<String,Reference<Lookup>> map = Collections.synchronizedMap(new HashMap<String,Reference<Lookup>>());
    6.53 +    
    6.54 +    public abstract Lookup create(String path);
    6.55 +    
    6.56 +    public static Lookup find(String path) {
    6.57 +        if (!path.endsWith("/")) {
    6.58 +            path = path + "/";
    6.59 +        }
    6.60 +        
    6.61 +        Reference<Lookup> ref = map.get(path);
    6.62 +        Lookup lkp = ref == null ? null : ref.get();
    6.63 +        if (lkp != null) {
    6.64 +            return lkp;
    6.65 +        }
    6.66 +        NamedServicesProvider prov = Lookup.getDefault().lookup(NamedServicesProvider.class);
    6.67 +        if (prov != null) {
    6.68 +            lkp = prov.create(path);
    6.69 +        } else {
    6.70 +            ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
    6.71 +            if (l == null) {
    6.72 +                l = Thread.currentThread().getContextClassLoader();
    6.73 +                if (l == null) {
    6.74 +                    l = NamedServicesProvider.class.getClassLoader();
    6.75 +                }
    6.76 +            }
    6.77 +            lkp = Lookups.metaInfServices(l, "META-INF/namedservices/" + path);
    6.78 +        }
    6.79 +        
    6.80 +        map.put(path, new WeakReference<Lookup>(lkp));
    6.81 +        return lkp;
    6.82 +    }
    6.83 +    
    6.84 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/openide.util.lookup/src/org/openide/util/Lookup.java	Sat Oct 31 15:28:13 2009 +0100
     7.3 @@ -0,0 +1,544 @@
     7.4 +/*
     7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.6 + *
     7.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
     7.8 + *
     7.9 + * The contents of this file are subject to the terms of either the GNU
    7.10 + * General Public License Version 2 only ("GPL") or the Common
    7.11 + * Development and Distribution License("CDDL") (collectively, the
    7.12 + * "License"). You may not use this file except in compliance with the
    7.13 + * License. You can obtain a copy of the License at
    7.14 + * http://www.netbeans.org/cddl-gplv2.html
    7.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    7.16 + * specific language governing permissions and limitations under the
    7.17 + * License.  When distributing the software, include this License Header
    7.18 + * Notice in each file and include the License file at
    7.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    7.20 + * particular file as subject to the "Classpath" exception as provided
    7.21 + * by Sun in the GPL Version 2 section of the License file that
    7.22 + * accompanied this code. If applicable, add the following below the
    7.23 + * License Header, with the fields enclosed by brackets [] replaced by
    7.24 + * your own identifying information:
    7.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    7.26 + *
    7.27 + * Contributor(s):
    7.28 + *
    7.29 + * The Original Software is NetBeans. The Initial Developer of the Original
    7.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
    7.31 + * Microsystems, Inc. All Rights Reserved.
    7.32 + *
    7.33 + * If you wish your version of this file to be governed by only the CDDL
    7.34 + * or only the GPL Version 2, indicate your decision by adding
    7.35 + * "[Contributor] elects to include this software in this distribution
    7.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    7.37 + * single choice of license, a recipient has the option to distribute
    7.38 + * your version of this file under either the CDDL, the GPL Version 2 or
    7.39 + * to extend the choice of license to its licensees as provided above.
    7.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    7.41 + * Version 2 license, then the option applies only if the new code is
    7.42 + * made subject to such option by the copyright holder.
    7.43 + */
    7.44 +
    7.45 +package org.openide.util;
    7.46 +
    7.47 +import java.util.ArrayList;
    7.48 +import java.util.Collection;
    7.49 +import java.util.Collections;
    7.50 +import java.util.Iterator;
    7.51 +import java.util.List;
    7.52 +import java.util.Set;
    7.53 +import org.openide.util.lookup.Lookups;
    7.54 +import org.openide.util.lookup.ProxyLookup;
    7.55 +import org.openide.util.lookup.ServiceProvider;
    7.56 +
    7.57 +/**
    7.58 + * A general registry permitting clients to find instances of services
    7.59 + * (implementation of a given interface).
    7.60 + * This class is inspired by the
    7.61 + * <a href="http://www.jini.org/">Jini</a>
    7.62 + * registration and lookup mechanism. The difference is that the methods do
    7.63 + * not throw checked exceptions (as they usually work only locally and not over the network)
    7.64 + * and that the Lookup API concentrates on the lookup, not on the registration
    7.65 + * (although {@link Lookup#getDefault} is strongly encouraged to support
    7.66 + * {@link Lookups#metaInfServices} for registration in addition to whatever
    7.67 + * else it decides to support).
    7.68 + * <p>
    7.69 + * For a general talk about the idea behind the lookup pattern please see
    7.70 + * <UL>
    7.71 + *      <LI><a href="lookup/doc-files/index.html">The Solution to Communication Between Components</a>
    7.72 + *      page
    7.73 + *      <LI>the introduction to the <a href="lookup/doc-files/lookup-api.html">lookup API via
    7.74 + *      use cases</a>
    7.75 + *      <LI>the examples of <a href="lookup/doc-files/lookup-spi.html">how to write your own lookup</a>
    7.76 + * </UL>
    7.77 + *
    7.78 + * @see org.openide.util.lookup.AbstractLookup
    7.79 + * @see Lookups
    7.80 + * @see LookupListener
    7.81 + * @see LookupEvent
    7.82 + * @author  Jaroslav Tulach
    7.83 + */
    7.84 +public abstract class Lookup {
    7.85 +    /** A dummy lookup that never returns any results.
    7.86 +     */
    7.87 +    public static final Lookup EMPTY = new Empty();
    7.88 +
    7.89 +    /** default instance */
    7.90 +    private static Lookup defaultLookup;
    7.91 +
    7.92 +    /** Empty constructor for use by subclasses. */
    7.93 +    public Lookup() {
    7.94 +    }
    7.95 +
    7.96 +    /** Static method to obtain the global lookup in the whole system.
    7.97 +     * The actual returned implementation can be different in different
    7.98 +     * systems, but the default one is based on
    7.99 +     * {@link org.openide.util.lookup.Lookups#metaInfServices}
   7.100 +     * with the context classloader of the first caller. Each system is
   7.101 +     * adviced to honor this and include some form of <code>metaInfServices</code>
   7.102 +     * implementation in the returned lookup as usage of <code>META-INF/services</code>
   7.103 +     * is a JDK standard.
   7.104 +     *
   7.105 +     * @return the global lookup in the system
   7.106 +     * @see ServiceProvider
   7.107 +     */
   7.108 +    public static synchronized Lookup getDefault() {
   7.109 +        if (defaultLookup != null) {
   7.110 +            return defaultLookup;
   7.111 +        }
   7.112 +
   7.113 +        // You can specify a Lookup impl using a system property if you like.
   7.114 +        String className = System.getProperty("org.openide.util.Lookup" // NOI18N
   7.115 +            );
   7.116 +
   7.117 +        if ("-".equals(className)) { // NOI18N
   7.118 +
   7.119 +            // Suppress even MetaInfServicesLookup.
   7.120 +            return EMPTY;
   7.121 +        }
   7.122 +
   7.123 +        ClassLoader l = Thread.currentThread().getContextClassLoader();
   7.124 +
   7.125 +        try {
   7.126 +            if (className != null) {
   7.127 +                defaultLookup = (Lookup) Class.forName(className, true, l).newInstance();
   7.128 +
   7.129 +                return defaultLookup;
   7.130 +            }
   7.131 +        } catch (Exception e) {
   7.132 +            // do not use ErrorManager because we are in the startup code
   7.133 +            // and ErrorManager might not be ready
   7.134 +            e.printStackTrace();
   7.135 +        }
   7.136 +
   7.137 +        // OK, none specified (successfully) in a system property.
   7.138 +        // Try MetaInfServicesLookup as a default, which may also
   7.139 +        // have a org.openide.util.Lookup line specifying the lookup.
   7.140 +        Lookup misl = Lookups.metaInfServices(l);
   7.141 +        defaultLookup = misl.lookup(Lookup.class);
   7.142 +
   7.143 +        if (defaultLookup != null) {
   7.144 +            return defaultLookup;
   7.145 +        }
   7.146 +
   7.147 +        // You may also specify a Lookup.Provider.
   7.148 +        Lookup.Provider prov = misl.lookup(Lookup.Provider.class);
   7.149 +
   7.150 +        if (prov != null) {
   7.151 +            defaultLookup = Lookups.proxy(prov);
   7.152 +
   7.153 +            return defaultLookup;
   7.154 +        }
   7.155 +
   7.156 +        DefLookup def = new DefLookup();
   7.157 +        def.init(l, misl, false);
   7.158 +        defaultLookup = def;
   7.159 +        def.init(l, misl, true);
   7.160 +        return defaultLookup;
   7.161 +    }
   7.162 +    
   7.163 +    private static final class DefLookup extends ProxyLookup {
   7.164 +        public DefLookup() {
   7.165 +            super(new Lookup[0]);
   7.166 +        }
   7.167 +        
   7.168 +        public void init(ClassLoader loader, Lookup metaInfLookup, boolean addPath) {
   7.169 +            // Had no such line, use simple impl.
   7.170 +            // It does however need to have ClassLoader available or many things will break.
   7.171 +            // Use the thread context classloader in effect now.
   7.172 +            Lookup clLookup = Lookups.singleton(loader);
   7.173 +            List<Lookup> arr = new ArrayList<Lookup>();
   7.174 +            arr.add(metaInfLookup);
   7.175 +            arr.add(clLookup);
   7.176 +            String paths = System.getProperty("org.openide.util.Lookup.paths"); // NOI18N
   7.177 +            if (addPath && paths != null) {
   7.178 +                for (String p : paths.split(":")) { // NOI18N
   7.179 +                    arr.add(Lookups.forPath(p));
   7.180 +                }
   7.181 +            }
   7.182 +            setLookups(arr.toArray(new Lookup[0]));
   7.183 +        }
   7.184 +    }
   7.185 +    
   7.186 +    /** Called from MockServices to reset default lookup in case services change
   7.187 +     */
   7.188 +    private static void resetDefaultLookup() {
   7.189 +        if (defaultLookup instanceof DefLookup) {
   7.190 +            DefLookup def = (DefLookup)defaultLookup;
   7.191 +            ClassLoader l = Thread.currentThread().getContextClassLoader();
   7.192 +            def.init(l, Lookups.metaInfServices(l), true);
   7.193 +        }
   7.194 +    }
   7.195 +
   7.196 +    /** Look up an object matching a given interface.
   7.197 +     * This is the simplest method to use.
   7.198 +     * If more than one object matches, the first will be returned.
   7.199 +     * The template class may be a class or interface; the instance is
   7.200 +     * guaranteed to be assignable to it.
   7.201 +     *
   7.202 +     * @param clazz class of the object we are searching for
   7.203 +     * @return an object implementing the given class or <code>null</code> if no such
   7.204 +     *         implementation is found
   7.205 +     */
   7.206 +    public abstract <T> T lookup(Class<T> clazz);
   7.207 +
   7.208 +    /** The general lookup method. Callers can get list of all instances and classes
   7.209 +     * that match the given <code>template</code>, request more info about
   7.210 +     * them in form of {@link Lookup.Item} and attach a listener to
   7.211 +     * this be notified about changes. The general interface does not
   7.212 +     * specify whether subsequent calls with the same template produce new
   7.213 +     * instance of the {@link Lookup.Result} or return shared instance. The
   7.214 +     * prefered behaviour however is to return shared one.
   7.215 +     *
   7.216 +     * @param template a template describing the services to look for
   7.217 +     * @return an object containing the results
   7.218 +     */
   7.219 +    public abstract <T> Result<T> lookup(Template<T> template);
   7.220 +
   7.221 +    /** Look up the first item matching a given template.
   7.222 +     * Includes not only the instance but other associated information.
   7.223 +     * @param template the template to check
   7.224 +     * @return a matching item or <code>null</code>
   7.225 +     *
   7.226 +     * @since 1.8
   7.227 +     */
   7.228 +    public <T> Item<T> lookupItem(Template<T> template) {
   7.229 +        Result<T> res = lookup(template);
   7.230 +        Iterator<? extends Item<T>> it = res.allItems().iterator();
   7.231 +        return it.hasNext() ? it.next() : null;
   7.232 +    }
   7.233 +
   7.234 +    /**
   7.235 +     * Find a result corresponding to a given class.
   7.236 +     * Equivalent to calling {@link #lookup(Lookup.Template)} but slightly more convenient.
   7.237 +     * Subclasses may override this method to produce the same semantics more efficiently.
   7.238 +     * @param clazz the supertype of the result
   7.239 +     * @return a live object representing instances of that type
   7.240 +     * @since org.openide.util 6.10
   7.241 +     */
   7.242 +    public <T> Lookup.Result<T> lookupResult(Class<T> clazz) {
   7.243 +        return lookup(new Lookup.Template<T>(clazz));
   7.244 +    }
   7.245 +
   7.246 +    /**
   7.247 +     * Find all instances corresponding to a given class.
   7.248 +     * Equivalent to calling {@link #lookupResult} and asking for {@link Lookup.Result#allInstances} but slightly more convenient.
   7.249 +     * Subclasses may override this method to produce the same semantics more efficiently.
   7.250 +     * <div class="nonnormative">
   7.251 +     * <p>Example usage:</p>
   7.252 +     * <pre>
   7.253 +     * for (MyService svc : Lookup.getDefault().lookupAll(MyService.class)) {
   7.254 +     *     svc.useMe();
   7.255 +     * }
   7.256 +     * </pre>
   7.257 +     * </div>
   7.258 +     * @param clazz the supertype of the result
   7.259 +     * @return all currently available instances of that type
   7.260 +     * @since org.openide.util 6.10
   7.261 +     */
   7.262 +    public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
   7.263 +        return lookupResult(clazz).allInstances();
   7.264 +    }
   7.265 +
   7.266 +    /**
   7.267 +     * Objects implementing interface Lookup.Provider are capable of
   7.268 +     * and willing to provide a lookup (usually bound to the object).
   7.269 +     * @since 3.6
   7.270 +     */
   7.271 +    public interface Provider {
   7.272 +        /**
   7.273 +         * Returns lookup associated with the object.
   7.274 +         * @return fully initialized lookup instance provided by this object
   7.275 +         */
   7.276 +        Lookup getLookup();
   7.277 +    }
   7.278 +
   7.279 +    /*
   7.280 +     * I expect this class to grow in the future, but for now, it is
   7.281 +     * enough to start with something simple.
   7.282 +     */
   7.283 +
   7.284 +    /** Template defining a pattern to filter instances by.
   7.285 +     */
   7.286 +    public static final class Template<T> extends Object {
   7.287 +        /** cached hash code */
   7.288 +        private int hashCode;
   7.289 +
   7.290 +        /** type of the service */
   7.291 +        private Class<T> type;
   7.292 +
   7.293 +        /** identity to search for */
   7.294 +        private String id;
   7.295 +
   7.296 +        /** instance to search for */
   7.297 +        private T instance;
   7.298 +
   7.299 +        /** General template to find all possible instances.
   7.300 +         * @deprecated Use <code>new Template (Object.class)</code> which
   7.301 +         *   is going to be better typed with JDK1.5 templates and should produce
   7.302 +         *   the same result.
   7.303 +         */
   7.304 +        @Deprecated
   7.305 +        public Template() {
   7.306 +            this(null);
   7.307 +        }
   7.308 +
   7.309 +        /** Create a simple template matching by class.
   7.310 +         * @param type the class of service we are looking for (subclasses will match)
   7.311 +         */
   7.312 +        public Template(Class<T> type) {
   7.313 +            this(type, null, null);
   7.314 +        }
   7.315 +
   7.316 +        /** Constructor to create new template.
   7.317 +         * @param type the class of service we are looking for or <code>null</code> to leave unspecified
   7.318 +         * @param id the ID of the item/service we are looking for or <code>null</code> to leave unspecified
   7.319 +         * @param instance a specific known instance to look for or <code>null</code> to leave unspecified
   7.320 +         */
   7.321 +        public Template(Class<T> type, String id, T instance) {
   7.322 +            this.type = extractType(type);
   7.323 +            this.id = id;
   7.324 +            this.instance = instance;
   7.325 +        }
   7.326 +
   7.327 +        @SuppressWarnings("unchecked")
   7.328 +        private Class<T> extractType(Class<T> type) {
   7.329 +            return (type == null) ? (Class<T>)Object.class : type;
   7.330 +        }
   7.331 +
   7.332 +        /** Get the class (or superclass or interface) to search for.
   7.333 +         * If it was not specified in the constructor, <code>Object</code> is used as
   7.334 +         * this will match any instance.
   7.335 +         * @return the class to search for
   7.336 +         */
   7.337 +        public Class<T> getType() {
   7.338 +            return type;
   7.339 +        }
   7.340 +
   7.341 +        /** Get the persistent identifier being searched for, if any.
   7.342 +         * @return the ID or <code>null</code>
   7.343 +         * @see Lookup.Item#getId
   7.344 +         *
   7.345 +         * @since 1.8
   7.346 +         */
   7.347 +        public String getId() {
   7.348 +            return id;
   7.349 +        }
   7.350 +
   7.351 +        /** Get the specific instance being searched for, if any.
   7.352 +         * Most useful for finding an <code>Item</code> when the instance
   7.353 +         * is already known.
   7.354 +         *
   7.355 +         * @return the object to find or <code>null</code>
   7.356 +         *
   7.357 +         * @since 1.8
   7.358 +         */
   7.359 +        public T getInstance() {
   7.360 +            return instance;
   7.361 +        }
   7.362 +
   7.363 +        /* Computes hashcode for this template. The hashcode is cached.
   7.364 +         * @return hashcode
   7.365 +         */
   7.366 +        @Override
   7.367 +        public int hashCode() {
   7.368 +            if (hashCode != 0) {
   7.369 +                return hashCode;
   7.370 +            }
   7.371 +
   7.372 +            hashCode = ((type == null) ? 1 : type.hashCode()) + ((id == null) ? 2 : id.hashCode()) +
   7.373 +                ((instance == null) ? 3 : 0);
   7.374 +
   7.375 +            return hashCode;
   7.376 +        }
   7.377 +
   7.378 +        /* Checks whether two templates represent the same query.
   7.379 +         * @param obj another template to check
   7.380 +         * @return true if so, false otherwise
   7.381 +         */
   7.382 +        @Override
   7.383 +        public boolean equals(Object obj) {
   7.384 +            if (!(obj instanceof Template)) {
   7.385 +                return false;
   7.386 +            }
   7.387 +
   7.388 +            Template t = (Template) obj;
   7.389 +
   7.390 +            if (hashCode() != t.hashCode()) {
   7.391 +                // this is an optimalization - the hashCodes should have been
   7.392 +                // precomputed
   7.393 +                return false;
   7.394 +            }
   7.395 +
   7.396 +            if (type != t.type) {
   7.397 +                return false;
   7.398 +            }
   7.399 +
   7.400 +            if (id == null) {
   7.401 +                if (t.id != null) {
   7.402 +                    return false;
   7.403 +                }
   7.404 +            } else {
   7.405 +                if (!id.equals(t.id)) {
   7.406 +                    return false;
   7.407 +                }
   7.408 +            }
   7.409 +
   7.410 +            if (instance == null) {
   7.411 +                return (t.instance == null);
   7.412 +            } else {
   7.413 +                return instance.equals(t.instance);
   7.414 +            }
   7.415 +        }
   7.416 +
   7.417 +        /* for debugging */
   7.418 +        @Override
   7.419 +        public String toString() {
   7.420 +            return "Lookup.Template[type=" + type + ",id=" + id + ",instance=" + instance + "]"; // NOI18N
   7.421 +        }
   7.422 +    }
   7.423 +
   7.424 +    /** Result of a lookup request.
   7.425 +     * Allows access to all matching instances at once.
   7.426 +     * Also permits listening to changes in the result.
   7.427 +     * Result can contain duplicate items.
   7.428 +     */
   7.429 +    public static abstract class Result<T> extends Object {
   7.430 +        /** Registers a listener that is invoked when there is a possible
   7.431 +         * change in this result.
   7.432 +         *
   7.433 +         * @param l the listener to add
   7.434 +         */
   7.435 +        public abstract void addLookupListener(LookupListener l);
   7.436 +
   7.437 +        /** Unregisters a listener previously added.
   7.438 +         * @param l the listener to remove
   7.439 +         */
   7.440 +        public abstract void removeLookupListener(LookupListener l);
   7.441 +
   7.442 +        /** Get all instances in the result. The return value type
   7.443 +         * should be List instead of Collection, but it is too late to change it.
   7.444 +         * @return unmodifiable collection of all instances that will never change its content
   7.445 +         */
   7.446 +        public abstract Collection<? extends T> allInstances();
   7.447 +
   7.448 +        /** Get all classes represented in the result.
   7.449 +         * That is, the set of concrete classes
   7.450 +         * used by instances present in the result.
   7.451 +         * All duplicate classes will be omitted.
   7.452 +         * @return unmodifiable set of <code>Class</code> objects that will never change its content
   7.453 +         *
   7.454 +         * @since 1.8
   7.455 +         */
   7.456 +        public Set<Class<? extends T>> allClasses() {
   7.457 +            return Collections.emptySet();
   7.458 +        }
   7.459 +
   7.460 +        /** Get all registered items.
   7.461 +         * This should include all pairs of instances together
   7.462 +         * with their classes, IDs, and so on. The return value type
   7.463 +         * should be List instead of Collection, but it is too late to change it.
   7.464 +         * @return unmodifiable collection of {@link Lookup.Item} that will never change its content
   7.465 +         *
   7.466 +         * @since 1.8
   7.467 +         */
   7.468 +        public Collection<? extends Item<T>> allItems() {
   7.469 +            return Collections.emptyList();
   7.470 +        }
   7.471 +    }
   7.472 +
   7.473 +    /** A single item in a lookup result.
   7.474 +     * This wrapper provides unified access to not just the instance,
   7.475 +     * but its class, a possible persistent identifier, and so on.
   7.476 +     *
   7.477 +     * @since 1.25
   7.478 +     */
   7.479 +    public static abstract class Item<T> extends Object {
   7.480 +        /** Get the instance itself.
   7.481 +         * @return the instance or null if the instance cannot be created
   7.482 +         */
   7.483 +        public abstract T getInstance();
   7.484 +
   7.485 +        /** Get the implementing class of the instance.
   7.486 +         * @return the class of the item
   7.487 +         */
   7.488 +        public abstract Class<? extends T> getType();
   7.489 +
   7.490 +        // XXX can it be null??
   7.491 +
   7.492 +        /** Get a persistent indentifier for the item.
   7.493 +         * This identifier should uniquely represent the item
   7.494 +         * within its containing lookup (and if possible within the
   7.495 +         * global lookup as a whole). For example, it might represent
   7.496 +         * the source of the instance as a file name. The ID may be
   7.497 +         * persisted and in a later session used to find the same instance
   7.498 +         * as was encountered earlier, by means of passing it into a
   7.499 +         * lookup template.
   7.500 +         *
   7.501 +         * @return a string ID of the item
   7.502 +         */
   7.503 +        public abstract String getId();
   7.504 +
   7.505 +        /** Get a human presentable name for the item.
   7.506 +         * This might be used when summarizing all the items found in a
   7.507 +         * lookup result in some part of a GUI.
   7.508 +         * @return the string suitable for presenting the object to a user
   7.509 +         */
   7.510 +        public abstract String getDisplayName();
   7.511 +
   7.512 +        /* show ID for debugging */
   7.513 +        @Override
   7.514 +        public String toString() {
   7.515 +            return getId();
   7.516 +        }
   7.517 +    }
   7.518 +
   7.519 +    //
   7.520 +    // Implementation of the default lookup
   7.521 +    //
   7.522 +    private static final class Empty extends Lookup {
   7.523 +        private static final Result NO_RESULT = new Result() {
   7.524 +                public void addLookupListener(LookupListener l) {
   7.525 +                }
   7.526 +
   7.527 +                public void removeLookupListener(LookupListener l) {
   7.528 +                }
   7.529 +
   7.530 +                public Collection allInstances() {
   7.531 +                    return Collections.EMPTY_SET;
   7.532 +                }
   7.533 +            };
   7.534 +
   7.535 +        Empty() {
   7.536 +        }
   7.537 +
   7.538 +        public <T> T lookup(Class<T> clazz) {
   7.539 +            return null;
   7.540 +        }
   7.541 +
   7.542 +        @SuppressWarnings("unchecked")
   7.543 +        public <T> Result<T> lookup(Template<T> template) {
   7.544 +            return NO_RESULT;
   7.545 +        }
   7.546 +    }
   7.547 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/openide.util.lookup/src/org/openide/util/LookupEvent.java	Sat Oct 31 15:28:13 2009 +0100
     8.3 @@ -0,0 +1,57 @@
     8.4 +/*
     8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     8.6 + *
     8.7 + * Copyright 1997-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 + * Contributor(s):
    8.28 + *
    8.29 + * The Original Software is NetBeans. The Initial Developer of the Original
    8.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
    8.31 + * Microsystems, Inc. All Rights Reserved.
    8.32 + *
    8.33 + * If you wish your version of this file to be governed by only the CDDL
    8.34 + * or only the GPL Version 2, indicate your decision by adding
    8.35 + * "[Contributor] elects to include this software in this distribution
    8.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    8.37 + * single choice of license, a recipient has the option to distribute
    8.38 + * your version of this file under either the CDDL, the GPL Version 2 or
    8.39 + * to extend the choice of license to its licensees as provided above.
    8.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    8.41 + * Version 2 license, then the option applies only if the new code is
    8.42 + * made subject to such option by the copyright holder.
    8.43 + */
    8.44 +package org.openide.util;
    8.45 +
    8.46 +import java.util.*;
    8.47 +
    8.48 +
    8.49 +/** An event describing the change in the lookup's result.
    8.50 + *
    8.51 + * @author  Jaroslav Tulach
    8.52 + */
    8.53 +public final class LookupEvent extends EventObject {
    8.54 +    /** Create a new lookup event.
    8.55 +     * @param source the lookup result which has changed
    8.56 +     */
    8.57 +    public LookupEvent(Lookup.Result source) {
    8.58 +        super(source);
    8.59 +    }
    8.60 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/openide.util.lookup/src/org/openide/util/LookupListener.java	Sat Oct 31 15:28:13 2009 +0100
     9.3 @@ -0,0 +1,59 @@
     9.4 +/*
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
     9.8 + *
     9.9 + * The contents of this file are subject to the terms of either the GNU
    9.10 + * General Public License Version 2 only ("GPL") or the Common
    9.11 + * Development and Distribution License("CDDL") (collectively, the
    9.12 + * "License"). You may not use this file except in compliance with the
    9.13 + * License. You can obtain a copy of the License at
    9.14 + * http://www.netbeans.org/cddl-gplv2.html
    9.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    9.16 + * specific language governing permissions and limitations under the
    9.17 + * License.  When distributing the software, include this License Header
    9.18 + * Notice in each file and include the License file at
    9.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    9.20 + * particular file as subject to the "Classpath" exception as provided
    9.21 + * by Sun in the GPL Version 2 section of the License file that
    9.22 + * accompanied this code. If applicable, add the following below the
    9.23 + * License Header, with the fields enclosed by brackets [] replaced by
    9.24 + * your own identifying information:
    9.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    9.26 + *
    9.27 + * Contributor(s):
    9.28 + *
    9.29 + * The Original Software is NetBeans. The Initial Developer of the Original
    9.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
    9.31 + * Microsystems, Inc. All Rights Reserved.
    9.32 + *
    9.33 + * If you wish your version of this file to be governed by only the CDDL
    9.34 + * or only the GPL Version 2, indicate your decision by adding
    9.35 + * "[Contributor] elects to include this software in this distribution
    9.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    9.37 + * single choice of license, a recipient has the option to distribute
    9.38 + * your version of this file under either the CDDL, the GPL Version 2 or
    9.39 + * to extend the choice of license to its licensees as provided above.
    9.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    9.41 + * Version 2 license, then the option applies only if the new code is
    9.42 + * made subject to such option by the copyright holder.
    9.43 + */
    9.44 +package org.openide.util;
    9.45 +
    9.46 +import java.util.*;
    9.47 +
    9.48 +
    9.49 +/** General listener for changes in lookup.
    9.50 + *
    9.51 + * @author  Jaroslav Tulach
    9.52 + */
    9.53 +public interface LookupListener extends EventListener {
    9.54 +    /** A change in lookup occured. Please note that this method
    9.55 +     * should never block since it might be called from lookup implementation
    9.56 +     * internal threads. If you block here you are in risk that the thread
    9.57 +     * you wait for might in turn to wait for the lookup internal thread to
    9.58 +     * finish its work.
    9.59 +     * @param ev event describing the change
    9.60 +     */
    9.61 +    public void resultChanged(LookupEvent ev);
    9.62 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ALPairComparator.java	Sat Oct 31 15:28:13 2009 +0100
    10.3 @@ -0,0 +1,88 @@
    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. Portions Copyright 1997-2006 Sun
   10.31 + * Microsystems, Inc. All Rights Reserved.
   10.32 + *
   10.33 + * If you wish your version of this file to be governed by only the CDDL
   10.34 + * or only the GPL Version 2, indicate your decision by adding
   10.35 + * "[Contributor] elects to include this software in this distribution
   10.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   10.37 + * single choice of license, a recipient has the option to distribute
   10.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   10.39 + * to extend the choice of license to its licensees as provided above.
   10.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   10.41 + * Version 2 license, then the option applies only if the new code is
   10.42 + * made subject to such option by the copyright holder.
   10.43 + */
   10.44 +package org.openide.util.lookup;
   10.45 +
   10.46 +import java.util.Comparator;
   10.47 +import org.openide.util.lookup.AbstractLookup.Pair;
   10.48 +
   10.49 +
   10.50 +/** Implementation of comparator for AbstractLookup.Pair
   10.51 + *
   10.52 + * @author  Jaroslav Tulach
   10.53 + */
   10.54 +final class ALPairComparator implements Comparator<Pair<?>> {
   10.55 +    public static final Comparator<Pair<?>> DEFAULT = new ALPairComparator();
   10.56 +
   10.57 +    /** Creates a new instance of ALPairComparator */
   10.58 +    private ALPairComparator() {
   10.59 +    }
   10.60 +
   10.61 +    /** Compares two items.
   10.62 +    */
   10.63 +    public int compare(Pair<?> i1, Pair<?> i2) {
   10.64 +        int result = i1.getIndex() - i2.getIndex();
   10.65 +
   10.66 +        if (result == 0) {
   10.67 +            if (i1 != i2) {
   10.68 +                java.io.ByteArrayOutputStream bs = new java.io.ByteArrayOutputStream();
   10.69 +                java.io.PrintStream ps = new java.io.PrintStream(bs);
   10.70 +
   10.71 +                ps.println(
   10.72 +                    "Duplicate pair in tree" + // NOI18N
   10.73 +                    "Pair1: " + i1 + " pair2: " + i2 + " index1: " + i1.getIndex() + " index2: " +
   10.74 +                    i2.getIndex() // NOI18N
   10.75 +                     +" item1: " + i1.getInstance() + " item2: " + i2.getInstance() // NOI18N
   10.76 +                     +" id1: " + Integer.toHexString(System.identityHashCode(i1)) // NOI18N
   10.77 +                     +" id2: " + Integer.toHexString(System.identityHashCode(i2)) // NOI18N
   10.78 +                );
   10.79 +
   10.80 +                //                print (ps, false);
   10.81 +                ps.close();
   10.82 +
   10.83 +                throw new IllegalStateException(bs.toString());
   10.84 +            }
   10.85 +
   10.86 +            return 0;
   10.87 +        }
   10.88 +
   10.89 +        return result;
   10.90 +    }
   10.91 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/AbstractLookup.java	Sat Oct 31 15:28:13 2009 +0100
    11.3 @@ -0,0 +1,1467 @@
    11.4 +/*
    11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.6 + *
    11.7 + * Copyright 1997-2009 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 + * Contributor(s):
   11.28 + *
   11.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   11.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   11.31 + * Microsystems, Inc. All Rights Reserved.
   11.32 + *
   11.33 + * If you wish your version of this file to be governed by only the CDDL
   11.34 + * or only the GPL Version 2, indicate your decision by adding
   11.35 + * "[Contributor] elects to include this software in this distribution
   11.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   11.37 + * single choice of license, a recipient has the option to distribute
   11.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   11.39 + * to extend the choice of license to its licensees as provided above.
   11.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   11.41 + * Version 2 license, then the option applies only if the new code is
   11.42 + * made subject to such option by the copyright holder.
   11.43 + */
   11.44 +package org.openide.util.lookup;
   11.45 +
   11.46 +import java.io.PrintStream;
   11.47 +import org.openide.util.Lookup;
   11.48 +import org.openide.util.LookupEvent;
   11.49 +import org.openide.util.LookupListener;
   11.50 +
   11.51 +import java.io.IOException;
   11.52 +import java.io.ObjectOutputStream;
   11.53 +import java.io.Serializable;
   11.54 +
   11.55 +import java.lang.ref.ReferenceQueue;
   11.56 +import java.lang.ref.WeakReference;
   11.57 +import java.util.ArrayList;
   11.58 +import java.util.Arrays;
   11.59 +import java.util.Collection;
   11.60 +import java.util.Collections;
   11.61 +import java.util.Enumeration;
   11.62 +import java.util.HashMap;
   11.63 +import java.util.HashSet;
   11.64 +import java.util.Iterator;
   11.65 +import java.util.LinkedHashSet;
   11.66 +import java.util.Map;
   11.67 +import java.util.Set;
   11.68 +import java.util.TreeSet;
   11.69 +
   11.70 +import java.util.concurrent.Executor;
   11.71 +import org.netbeans.modules.openide.util.ActiveQueue;
   11.72 +
   11.73 +
   11.74 +/** Implementation of the lookup from OpenAPIs that is based on the
   11.75 + * introduction of Item. This class should provide the default way
   11.76 + * of how to store (Class, Object) pairs in the lookups. It offers
   11.77 + * protected methods for subclasses to register the pairs.
   11.78 + * <p>Serializable since 3.27.
   11.79 + * @author  Jaroslav Tulach
   11.80 + * @since 1.9
   11.81 + */
   11.82 +public class AbstractLookup extends Lookup implements Serializable {
   11.83 +    static final long serialVersionUID = 5L;
   11.84 +
   11.85 +    /** lock for initialization of the maps of lookups */
   11.86 +    private static final Object treeLock = new Object();
   11.87 +
   11.88 +    /** the tree that registers all items (or Integer as a treshold size) */
   11.89 +    private Object tree;
   11.90 +
   11.91 +    /** count of items in to lookup */
   11.92 +    private int count;
   11.93 +
   11.94 +    /** Constructor to create this lookup and associate it with given
   11.95 +     * Content. The content than allows the creator to invoke protected
   11.96 +     * methods which are not accessible for any other user of the lookup.
   11.97 +     *
   11.98 +     * @param content the content to assciate with
   11.99 +     *
  11.100 +     * @since 1.25
  11.101 +     */
  11.102 +    public AbstractLookup(Content content) {
  11.103 +        content.attach(this);
  11.104 +    }
  11.105 +
  11.106 +    /** Constructor for testing purposes that allows specification of storage
  11.107 +     * as mechanism as well.
  11.108 +     */
  11.109 +    AbstractLookup(Content content, Storage<?> storage) {
  11.110 +        this(content);
  11.111 +        this.tree = storage;
  11.112 +        initialize();
  11.113 +    }
  11.114 +
  11.115 +    /** Constructor for testing purposes that allows specification of storage
  11.116 +     * as mechanism as well.
  11.117 +     * @param trashhold number of Pair to "remain small"
  11.118 +     */
  11.119 +    AbstractLookup(Content content, Integer trashhold) {
  11.120 +        this(content);
  11.121 +        this.tree = trashhold;
  11.122 +    }
  11.123 +
  11.124 +    /** Default constructor for subclasses that do not need to provide a content
  11.125 +     */
  11.126 +    protected AbstractLookup() {
  11.127 +    }
  11.128 +
  11.129 +    @Override
  11.130 +    public String toString() {
  11.131 +        if (tree instanceof Storage) {
  11.132 +            return "AbstractLookup" + lookup(new Lookup.Template<Object>(Object.class)).allItems(); // NOI18N
  11.133 +        } else {
  11.134 +            return super.toString();
  11.135 +        }
  11.136 +    }
  11.137 +
  11.138 +    /** Entres the storage management system.
  11.139 +     */
  11.140 +    @SuppressWarnings("unchecked")
  11.141 +    private <T> AbstractLookup.Storage<T> enterStorage() {
  11.142 +        for (;;) {
  11.143 +            synchronized (treeLock) {
  11.144 +                if (tree instanceof AbstractLookup.Storage) {
  11.145 +                    if (tree instanceof DelegatingStorage) {
  11.146 +                        // somebody is using the lookup right now
  11.147 +                        DelegatingStorage del = (DelegatingStorage) tree;
  11.148 +
  11.149 +                        // check whether there is not access from the same 
  11.150 +                        // thread (can throw exception)
  11.151 +                        del.checkForTreeModification();
  11.152 +
  11.153 +                        try {
  11.154 +                            treeLock.wait();
  11.155 +                        } catch (InterruptedException ex) {
  11.156 +                            // ignore and go on
  11.157 +                        }
  11.158 +
  11.159 +                        continue;
  11.160 +                    } else {
  11.161 +                        // ok, tree is initialized and nobody is using it yet
  11.162 +                        tree = new DelegatingStorage((Storage<T>) tree);
  11.163 +
  11.164 +                        return (Storage<T>) tree;
  11.165 +                    }
  11.166 +                }
  11.167 +
  11.168 +                // first time initialization of the tree
  11.169 +                if (tree instanceof Integer) {
  11.170 +                    tree = new ArrayStorage((Integer) tree);
  11.171 +                } else {
  11.172 +                    tree = new ArrayStorage();
  11.173 +                }
  11.174 +            }
  11.175 +
  11.176 +            // the tree has not yet been initilized, initialize and go on again
  11.177 +            initialize();
  11.178 +        }
  11.179 +    }
  11.180 +
  11.181 +    /** Exists tree ownership.
  11.182 +     */
  11.183 +    private AbstractLookup.Storage exitStorage() {
  11.184 +        synchronized (treeLock) {
  11.185 +            AbstractLookup.Storage stor = ((DelegatingStorage) tree).exitDelegate();
  11.186 +            tree = stor;
  11.187 +            treeLock.notifyAll();
  11.188 +
  11.189 +            return stor;
  11.190 +        }
  11.191 +    }
  11.192 +
  11.193 +    /** Method for subclasses to initialize them selves.
  11.194 +     */
  11.195 +    protected void initialize() {
  11.196 +    }
  11.197 +
  11.198 +    /** Notifies subclasses that a query is about to be processed.
  11.199 +     * @param template the template
  11.200 +     */
  11.201 +    protected void beforeLookup(Template<?> template) {
  11.202 +    }
  11.203 +
  11.204 +    /** The method to add instance to the lookup with.
  11.205 +     * @param pair class/instance pair
  11.206 +     */
  11.207 +    protected final void addPair(Pair<?> pair) {
  11.208 +        addPairImpl(pair, null);
  11.209 +    }
  11.210 +
  11.211 +    /** The method to add instance to the lookup with.
  11.212 +     * @param pair class/instance pair
  11.213 +     * @param notifyIn the executor that will handle the notification of events
  11.214 +     * @since 7.16
  11.215 +     */
  11.216 +    protected final void addPair(Pair<?> pair, Executor notifyIn) {
  11.217 +        addPairImpl(pair, notifyIn);
  11.218 +    }
  11.219 +
  11.220 +    private final <Transaction> void addPairImpl(Pair<?> pair, Executor notifyIn) {
  11.221 +        HashSet<R> toNotify = new HashSet<R>();
  11.222 +
  11.223 +        AbstractLookup.Storage<Transaction> t = enterStorage();
  11.224 +        Transaction transaction = null;
  11.225 +
  11.226 +        try {
  11.227 +            transaction = t.beginTransaction(-2);
  11.228 +
  11.229 +            if (t.add(pair, transaction)) {
  11.230 +                try {
  11.231 +                    pair.setIndex(t, count++);
  11.232 +                } catch (IllegalStateException ex) {
  11.233 +                    // remove the pair
  11.234 +                    t.remove(pair, transaction);
  11.235 +
  11.236 +                    // rethrow the exception
  11.237 +                    throw ex;
  11.238 +                }
  11.239 +
  11.240 +                // if the pair is newly added and was not there before
  11.241 +                t.endTransaction(transaction, toNotify);
  11.242 +            } else {
  11.243 +                // just finish the process by calling endTransaction
  11.244 +                t.endTransaction(transaction, new HashSet<R>());
  11.245 +            }
  11.246 +        } finally {
  11.247 +            exitStorage();
  11.248 +        }
  11.249 +
  11.250 +        notifyIn(notifyIn, toNotify);
  11.251 +    }
  11.252 +
  11.253 +    /** Remove instance.
  11.254 +     * @param pair class/instance pair
  11.255 +     */
  11.256 +    protected final void removePair(Pair<?> pair) {
  11.257 +        removePairImpl(pair, null);
  11.258 +    }
  11.259 +    /** Remove instance.
  11.260 +     * @param pair class/instance pair
  11.261 +     * @param notifyIn the executor that will handle the notification of events
  11.262 +     * @since 7.16
  11.263 +     */
  11.264 +    protected final void removePair(Pair<?> pair, Executor notifyIn) {
  11.265 +        removePairImpl(pair, notifyIn);
  11.266 +    }
  11.267 +
  11.268 +    private <Transaction> void removePairImpl(Pair<?> pair, Executor notifyIn) {
  11.269 +        HashSet<R> toNotify = new HashSet<R>();
  11.270 +
  11.271 +        AbstractLookup.Storage<Transaction> t = enterStorage();
  11.272 +        Transaction transaction = null;
  11.273 +
  11.274 +        try {
  11.275 +            transaction = t.beginTransaction(-1);
  11.276 +            t.remove(pair, transaction);
  11.277 +            t.endTransaction(transaction, toNotify);
  11.278 +        } finally {
  11.279 +            exitStorage();
  11.280 +        }
  11.281 +
  11.282 +        notifyIn(notifyIn, toNotify);
  11.283 +    }
  11.284 +
  11.285 +    /** Changes all pairs in the lookup to new values.
  11.286 +     * @param collection the collection of (Pair) objects
  11.287 +     */
  11.288 +    protected final void setPairs(Collection<? extends Pair> collection) {
  11.289 +        setPairs(collection, null);
  11.290 +    }
  11.291 +
  11.292 +    /** Changes all pairs in the lookup to new values, notifies listeners
  11.293 +     * using provided executor.
  11.294 +     * 
  11.295 +     * @param collection the collection of (Pair) objects
  11.296 +     * @param notifyIn the executor that will handle the notification of events
  11.297 +     * @since 7.16
  11.298 +     */
  11.299 +    protected final void setPairs(Collection<? extends Pair> collection, Executor notifyIn) {
  11.300 +        HashSet<R> listeners = setPairsAndCollectListeners(collection);
  11.301 +        notifyIn(notifyIn, listeners);
  11.302 +    }
  11.303 +    
  11.304 +    private final void notifyIn(Executor notifyIn, final HashSet<R> listeners) {
  11.305 +        NotifyListeners notify = new NotifyListeners(listeners);
  11.306 +        if (notify.shallRun()) {
  11.307 +            if (notifyIn == null) {
  11.308 +                notify.run();
  11.309 +            } else {
  11.310 +                notifyIn.execute(notify);
  11.311 +            }
  11.312 +        }
  11.313 +    }
  11.314 +    
  11.315 +    /** Getter for set of pairs. Package private contract with MetaInfServicesLookup.
  11.316 +     * @return a LinkedHashSet that can be modified
  11.317 +     */
  11.318 +    final LinkedHashSet<Pair<?>> getPairsAsLHS() {
  11.319 +        AbstractLookup.Storage<?> t = enterStorage();
  11.320 +
  11.321 +        try {
  11.322 +            Enumeration<Pair<Object>> en = t.lookup(Object.class);
  11.323 +            TreeSet<Pair<?>> arr = new TreeSet<Pair<?>>(ALPairComparator.DEFAULT);
  11.324 +            while (en.hasMoreElements()) {
  11.325 +                Pair<Object> item = en.nextElement();
  11.326 +                arr.add(item);
  11.327 +            }
  11.328 +            return new LinkedHashSet<Pair<?>>(arr);
  11.329 +        } finally {
  11.330 +            exitStorage();
  11.331 +        }
  11.332 +    }
  11.333 +
  11.334 +    /** Collects listeners without notification. Needed in MetaInfServicesLookup
  11.335 +     * right now, but maybe will become an API later.
  11.336 +     */
  11.337 +    final <Transaction> HashSet<R> setPairsAndCollectListeners(Collection<? extends Pair> collection) {
  11.338 +        HashSet<R> toNotify = new HashSet<R>(27);
  11.339 +
  11.340 +        AbstractLookup.Storage<Transaction> t = enterStorage();
  11.341 +        Transaction transaction = null;
  11.342 +
  11.343 +        try {
  11.344 +            // map between the Items and their indexes (Integer)
  11.345 +            HashMap<Item<?>,Info> shouldBeThere = new HashMap<Item<?>,Info>(collection.size() * 2);
  11.346 +
  11.347 +            count = 0;
  11.348 +
  11.349 +            Iterator it = collection.iterator();
  11.350 +            transaction = t.beginTransaction(collection.size());
  11.351 +
  11.352 +            while (it.hasNext()) {
  11.353 +                Pair item = (Pair) it.next();
  11.354 +
  11.355 +                if (t.add(item, transaction)) {
  11.356 +                    // the item has not been there yet
  11.357 +                    //t.endTransaction(transaction, toNotify);
  11.358 +                }
  11.359 +
  11.360 +                // remeber the item, because it should not be removed
  11.361 +                shouldBeThere.put(item, new Info(count++, transaction));
  11.362 +
  11.363 +                //                    arr.clear ();
  11.364 +            }
  11.365 +
  11.366 +            //            Object transaction = t.beginTransaction ();
  11.367 +            // deletes all objects that should not be there and
  11.368 +            t.retainAll(shouldBeThere, transaction);
  11.369 +
  11.370 +            // collect listeners
  11.371 +            t.endTransaction(transaction, toNotify);
  11.372 +
  11.373 +            /*
  11.374 +            // check consistency
  11.375 +            Enumeration en = t.lookup (java.lang.Object.class);
  11.376 +            boolean[] max = new boolean[count];
  11.377 +            int mistake = -1;
  11.378 +            while (en.hasMoreElements ()) {
  11.379 +                Pair item = (Pair)en.nextElement ();
  11.380 +
  11.381 +                if (max[item.index]) {
  11.382 +                    mistake = item.index;
  11.383 +                }
  11.384 +                max[item.index] = true;
  11.385 +            }
  11.386 +
  11.387 +            if (mistake != -1) {
  11.388 +                System.err.println ("Mistake at: " + mistake);
  11.389 +                tree.print (System.err, true);
  11.390 +            }
  11.391 +            */
  11.392 +        } finally {
  11.393 +            exitStorage();
  11.394 +        }
  11.395 +
  11.396 +        return toNotify;
  11.397 +    }
  11.398 +
  11.399 +    private final void writeObject(ObjectOutputStream oos)
  11.400 +    throws IOException {
  11.401 +        AbstractLookup.Storage s = enterStorage();
  11.402 +
  11.403 +        try {
  11.404 +            // #36830: Serializing only InheritanceTree no ArrayStorage
  11.405 +            s.beginTransaction(Integer.MAX_VALUE);
  11.406 +
  11.407 +            // #32040: don't write half-made changes
  11.408 +            oos.defaultWriteObject();
  11.409 +        } finally {
  11.410 +            exitStorage();
  11.411 +        }
  11.412 +    }
  11.413 +
  11.414 +    public final <T> T lookup(Class<T> clazz) {
  11.415 +        Lookup.Item<T> item = lookupItem(new Lookup.Template<T>(clazz));
  11.416 +        return (item == null) ? null : item.getInstance();
  11.417 +    }
  11.418 +
  11.419 +    @Override
  11.420 +    public final <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
  11.421 +        AbstractLookup.this.beforeLookup(template);
  11.422 +
  11.423 +        ArrayList<Pair<T>> list = null;
  11.424 +        AbstractLookup.Storage<?> t = enterStorage();
  11.425 +
  11.426 +        try {
  11.427 +            Enumeration<Pair<T>> en;
  11.428 +
  11.429 +            try {
  11.430 +                en = t.lookup(template.getType());
  11.431 +
  11.432 +                return findSmallest(en, template, false);
  11.433 +            } catch (AbstractLookup.ISE ex) {
  11.434 +                // not possible to enumerate the exception, ok, copy it 
  11.435 +                // to create new
  11.436 +                list = new ArrayList<Pair<T>>();
  11.437 +                en = t.lookup(null); // this should get all the items without any checks
  11.438 +
  11.439 +                // the checks will be done out side of the storage
  11.440 +                while (en.hasMoreElements()) {
  11.441 +                    list.add(en.nextElement());
  11.442 +                }
  11.443 +            }
  11.444 +        } finally {
  11.445 +            exitStorage();
  11.446 +        }
  11.447 +
  11.448 +        return findSmallest(Collections.enumeration(list), template, true);
  11.449 +    }
  11.450 +
  11.451 +    private static <T> Pair<T> findSmallest(Enumeration<Pair<T>> en, Lookup.Template<T> template, boolean deepCheck) {
  11.452 +        int smallest = InheritanceTree.unsorted(en) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
  11.453 +        Pair<T> res = null;
  11.454 +
  11.455 +        while (en.hasMoreElements()) {
  11.456 +            Pair<T> item = en.nextElement();
  11.457 +
  11.458 +            if (matches(template, item, deepCheck)) {
  11.459 +                if (smallest == Integer.MIN_VALUE) {
  11.460 +                    // ok, sorted enumeration the first that matches is fine
  11.461 +                    return item;
  11.462 +                } else {
  11.463 +                    // check for the smallest item
  11.464 +                    if (smallest > item.getIndex()) {
  11.465 +                        smallest = item.getIndex();
  11.466 +                        res = item;
  11.467 +                    }
  11.468 +                }
  11.469 +            }
  11.470 +        }
  11.471 +
  11.472 +        return res;
  11.473 +    }
  11.474 +
  11.475 +    public final <T> Lookup.Result<T> lookup(Lookup.Template<T> template) {
  11.476 +        for (;;) {
  11.477 +            AbstractLookup.ISE toRun = null;
  11.478 +
  11.479 +            AbstractLookup.Storage<?> t = enterStorage();
  11.480 +
  11.481 +            try {
  11.482 +                R<T> r = new R<T>();
  11.483 +                ReferenceToResult<T> newRef = new ReferenceToResult<T>(r, this, template);
  11.484 +                newRef.next = t.registerReferenceToResult(newRef);
  11.485 +
  11.486 +                return r;
  11.487 +            } catch (AbstractLookup.ISE ex) {
  11.488 +                toRun = ex;
  11.489 +            } finally {
  11.490 +                exitStorage();
  11.491 +            }
  11.492 +
  11.493 +            toRun.recover(this);
  11.494 +
  11.495 +            // and try again
  11.496 +        }
  11.497 +    }
  11.498 +
  11.499 +    /** Notifies listeners.
  11.500 +     * @param allAffectedResults set of R
  11.501 +     */
  11.502 +    static final class NotifyListeners implements Runnable {
  11.503 +        private final ArrayList<Object> evAndListeners;
  11.504 +        
  11.505 +        public NotifyListeners(Set<R> allAffectedResults) {
  11.506 +            if (allAffectedResults.isEmpty()) {
  11.507 +                evAndListeners = null;
  11.508 +                return;
  11.509 +            }
  11.510 +
  11.511 +            evAndListeners = new ArrayList<Object>();
  11.512 +            {
  11.513 +                for (R<?> result : allAffectedResults) {
  11.514 +                    result.collectFires(evAndListeners);
  11.515 +                }
  11.516 +            }
  11.517 +        }
  11.518 +
  11.519 +        public boolean shallRun() {
  11.520 +            return evAndListeners != null && !evAndListeners.isEmpty();
  11.521 +        }
  11.522 +
  11.523 +        public void run() {
  11.524 +            Iterator it = evAndListeners.iterator();
  11.525 +            while (it.hasNext()) {
  11.526 +                LookupEvent ev = (LookupEvent)it.next();
  11.527 +                LookupListener l = (LookupListener)it.next();
  11.528 +                l.resultChanged(ev);
  11.529 +            }
  11.530 +        }
  11.531 +    }
  11.532 +
  11.533 +    /**
  11.534 +     * Call resultChanged on all listeners.
  11.535 +     * @param listeners array of listeners in the format used by
  11.536 +     *        javax.swing.EventListenerList. It means that there are Class
  11.537 +     *        objects on even positions and the listeners on odd positions
  11.538 +     * @param ev the event to fire
  11.539 +     */
  11.540 +    static void notifyListeners(Object[] listeners, LookupEvent ev, Collection<Object> evAndListeners) {
  11.541 +        for (int i = listeners.length - 1; i >= 0; i--) {
  11.542 +            if (! (listeners[i] instanceof LookupListener)) {
  11.543 +                continue;
  11.544 +            }
  11.545 +            LookupListener ll = (LookupListener)listeners[i];
  11.546 +
  11.547 +            try {
  11.548 +                if (evAndListeners != null) {
  11.549 +                    if (ll instanceof WaitableResult) {
  11.550 +                        WaitableResult<?> wr = (WaitableResult<?>)ll;
  11.551 +                        wr.collectFires(evAndListeners);
  11.552 +                    } else {
  11.553 +                        evAndListeners.add(ev);
  11.554 +                        evAndListeners.add(ll);
  11.555 +                    }
  11.556 +                } else {
  11.557 +                    ll.resultChanged(ev);
  11.558 +                }
  11.559 +            } catch (StackOverflowError err) {
  11.560 +                throw new CycleError(evAndListeners); // NOI18N
  11.561 +            } catch (RuntimeException e) {
  11.562 +                // Such as e.g. occurred in #32040. Do not halt other things.
  11.563 +                e.printStackTrace();
  11.564 +            }
  11.565 +        }
  11.566 +    }
  11.567 +
  11.568 +    private static class CycleError extends StackOverflowError {
  11.569 +        private final Collection<Object> print;
  11.570 +        public CycleError(Collection<Object> evAndListeners) {
  11.571 +            this.print = evAndListeners;
  11.572 +        }
  11.573 +
  11.574 +        @Override
  11.575 +        public String getMessage() {
  11.576 +            StringBuilder sb = new StringBuilder();
  11.577 +            sb.append("StackOverflowError, here are the listeners:\n"); // NOI18N
  11.578 +            for (Object o : print) {
  11.579 +                sb.append('\n').append(o);
  11.580 +                if (sb.length() > 10000) {
  11.581 +                    break;
  11.582 +                }
  11.583 +            }
  11.584 +            return sb.toString();
  11.585 +        }
  11.586 +    } // end of CycleError
  11.587 +
  11.588 +    /** A method that defines matching between Item and Template.
  11.589 +     * @param t template providing the criteria
  11.590 +     * @param item the item to match
  11.591 +     * @param deepCheck true if type of the pair should be tested, false if it is already has been tested
  11.592 +     * @return true if item matches the template requirements, false if not
  11.593 +     */
  11.594 +    static boolean matches(Template<?> t, Pair<?> item, boolean deepCheck) {
  11.595 +        String id = t.getId();
  11.596 +
  11.597 +        if (id != null && !id.equals(item.getId())) {
  11.598 +            return false;
  11.599 +        }
  11.600 +
  11.601 +        Object instance = t.getInstance();
  11.602 +
  11.603 +        if ((instance != null) && !item.creatorOf(instance)) {
  11.604 +            return false;
  11.605 +        }
  11.606 +
  11.607 +        if (deepCheck) {
  11.608 +            return item.instanceOf(t.getType());
  11.609 +        } else {
  11.610 +            return true;
  11.611 +        }
  11.612 +    }
  11.613 +
  11.614 +    /**
  11.615 +     * Compares the array elements for equality.
  11.616 +     * @return true if all elements in the arrays are equal
  11.617 +     *  (by calling equals(Object x) method)
  11.618 +     */
  11.619 +    private static boolean compareArrays(Object[] a, Object[] b) {
  11.620 +        // handle null values
  11.621 +        if (a == null) {
  11.622 +            return (b == null);
  11.623 +        } else {
  11.624 +            if (b == null) {
  11.625 +                return false;
  11.626 +            }
  11.627 +        }
  11.628 +
  11.629 +        if (a.length != b.length) {
  11.630 +            return false;
  11.631 +        }
  11.632 +
  11.633 +        for (int i = 0; i < a.length; i++) {
  11.634 +            // handle null values for individual elements
  11.635 +            if (a[i] == null) {
  11.636 +                if (b[i] != null) {
  11.637 +                    return false;
  11.638 +                }
  11.639 +
  11.640 +                // both are null --> ok, take next
  11.641 +                continue;
  11.642 +            } else {
  11.643 +                if (b[i] == null) {
  11.644 +                    return false;
  11.645 +                }
  11.646 +            }
  11.647 +
  11.648 +            // perform the comparison
  11.649 +            if (!a[i].equals(b[i])) {
  11.650 +                return false;
  11.651 +            }
  11.652 +        }
  11.653 +
  11.654 +        return true;
  11.655 +    }
  11.656 +
  11.657 +    /** Method to be called when a result is cleared to signal that the list
  11.658 +     * of all result should be checked for clearing.
  11.659 +     * @param template the template the result was for
  11.660 +     * @return true if the hash map with all items has been cleared
  11.661 +     */
  11.662 +    <T> boolean cleanUpResult(Lookup.Template<T> template) {
  11.663 +        AbstractLookup.Storage<?> t = enterStorage();
  11.664 +
  11.665 +        try {
  11.666 +            return t.cleanUpResult(template) == null;
  11.667 +        } finally {
  11.668 +            exitStorage();
  11.669 +        }
  11.670 +    }
  11.671 +
  11.672 +    /** Storage check for tests. */
  11.673 +    static boolean isSimple(AbstractLookup l) {
  11.674 +        return DelegatingStorage.isSimple((Storage)l.tree);
  11.675 +    }
  11.676 +
  11.677 +    /** Generic support for listeners, so it can be used in other results
  11.678 +     * as well.
  11.679 +     * @param add true to add it, false to modify
  11.680 +     * @param l listener to modify
  11.681 +     * @param ref the value of the reference to listener or listener list
  11.682 +     * @return new value to the reference to listener or list
  11.683 +     */
  11.684 +    @SuppressWarnings("unchecked")
  11.685 +    static Object modifyListenerList(boolean add, LookupListener l, Object ref) {
  11.686 +        if (add) {
  11.687 +            if (ref == null) {
  11.688 +                return l;
  11.689 +            }
  11.690 +
  11.691 +            if (ref instanceof LookupListener) {
  11.692 +                ArrayList arr = new ArrayList();
  11.693 +                arr.add(ref);
  11.694 +                ref = arr;
  11.695 +            }
  11.696 +
  11.697 +            ((ArrayList) ref).add(l);
  11.698 +
  11.699 +            return ref;
  11.700 +        } else {
  11.701 +            // remove
  11.702 +            if (ref == null) {
  11.703 +                return null;
  11.704 +            }
  11.705 +
  11.706 +            if (ref == l) {
  11.707 +                return null;
  11.708 +            }
  11.709 +
  11.710 +            ArrayList arr = (ArrayList) ref;
  11.711 +            arr.remove(l);
  11.712 +
  11.713 +            if (arr.size() == 1) {
  11.714 +                return arr.iterator().next();
  11.715 +            } else {
  11.716 +                return arr;
  11.717 +            }
  11.718 +        }
  11.719 +    }
  11.720 +
  11.721 +    private static ReferenceQueue<Object> activeQueue() {
  11.722 +        return ActiveQueue.queue();
  11.723 +    }
  11.724 +
  11.725 +    /** Storage to keep the internal structure of Pairs and to answer
  11.726 +     * different queries.
  11.727 +     */
  11.728 +    interface Storage<Transaction> {
  11.729 +        /** Initializes a modification operation by creating an object
  11.730 +         * that will be passsed to all add, remove, retainAll methods
  11.731 +         * and should collect enough information about the change to
  11.732 +         * notify listeners about the transaction later
  11.733 +         *
  11.734 +         * @param ensure the amount of items that will appear in the storage
  11.735 +         *   after the modifications (-1 == remove one, -2 == add one, >= 0
  11.736 +         *   the amount of objects at the end
  11.737 +         * @return a token to identify the transaction
  11.738 +         */
  11.739 +        public Transaction beginTransaction(int ensure);
  11.740 +
  11.741 +        /** Collects all affected results R that were modified in the
  11.742 +         * given transaction.
  11.743 +         *
  11.744 +         * @param modified place to add results R to
  11.745 +         * @param transaction the transaction indentification
  11.746 +         */
  11.747 +        public void endTransaction(Transaction transaction, Set<R> modifiedResults);
  11.748 +
  11.749 +        /** Adds an item into the storage.
  11.750 +        * @param item to add
  11.751 +        * @param transaction transaction token
  11.752 +        * @return true if the Item has been added for the first time or false if some other
  11.753 +        *    item equal to this one already existed in the lookup
  11.754 +        */
  11.755 +        public boolean add(AbstractLookup.Pair<?> item, Transaction transaction);
  11.756 +
  11.757 +        /** Removes an item.
  11.758 +        */
  11.759 +        public void remove(AbstractLookup.Pair item, Transaction transaction);
  11.760 +
  11.761 +        /** Removes all items that are not present in the provided collection.
  11.762 +        * @param retain collection of Pairs to keep them in
  11.763 +        * @param transaction the transaction context
  11.764 +        */
  11.765 +        public void retainAll(Map retain, Transaction transaction);
  11.766 +
  11.767 +        /** Queries for instances of given class.
  11.768 +        * @param clazz the class to check
  11.769 +        * @return enumeration of Item
  11.770 +        * @see #unsorted
  11.771 +        */
  11.772 +        public <T> Enumeration<Pair<T>> lookup(Class<T> clazz);
  11.773 +
  11.774 +        /** Registers another reference to a result with the storage. This method
  11.775 +         * has also a special meaning.
  11.776 +         *
  11.777 +         * @param newRef the new reference to remember
  11.778 +         * @return the previous reference that was kept (null if newRef is the first one)
  11.779 +         *    the applications is expected to link from newRef to this returned
  11.780 +         *    value to form a linked list
  11.781 +         */
  11.782 +        public ReferenceToResult<?> registerReferenceToResult(ReferenceToResult<?> newRef);
  11.783 +
  11.784 +        /** Given the provided template, Do cleanup the results.
  11.785 +         * @param templ template of a result(s) that should be checked
  11.786 +         * @return null if all references for this template were cleared or one of them
  11.787 +         */
  11.788 +        public ReferenceToResult<?> cleanUpResult(Lookup.Template<?> templ);
  11.789 +    }
  11.790 +
  11.791 +    /** Extension to the default lookup item that offers additional information
  11.792 +     * for the data structures use in AbstractLookup
  11.793 +     */
  11.794 +    public static abstract class Pair<T> extends Lookup.Item<T> implements Serializable {
  11.795 +        private static final long serialVersionUID = 1L;
  11.796 +
  11.797 +        /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */
  11.798 +        private int index = -1;
  11.799 +
  11.800 +        /** For use by subclasses. */
  11.801 +        protected Pair() {
  11.802 +        }
  11.803 +
  11.804 +        final int getIndex() {
  11.805 +            return index;
  11.806 +        }
  11.807 +
  11.808 +        final void setIndex(AbstractLookup.Storage<?> tree, int x) {
  11.809 +            if (tree == null) {
  11.810 +                this.index = x;
  11.811 +
  11.812 +                return;
  11.813 +            }
  11.814 +
  11.815 +            if (this.index == -1) {
  11.816 +                this.index = x;
  11.817 +            } else {
  11.818 +                throw new IllegalStateException("You cannot use " + this + " in more than one AbstractLookup. Prev: " + this.index + " new: " + x); // NOI18N
  11.819 +            }
  11.820 +        }
  11.821 +
  11.822 +        /** Tests whether this item can produce object
  11.823 +        * of class c.
  11.824 +        */
  11.825 +        protected abstract boolean instanceOf(Class<?> c);
  11.826 +
  11.827 +        /** Method that can test whether an instance of a class has been created
  11.828 +         * by this item.
  11.829 +         *
  11.830 +         * @param obj the instance
  11.831 +         * @return if the item has already create an instance and it is the same
  11.832 +         *   as obj.
  11.833 +         */
  11.834 +        protected abstract boolean creatorOf(Object obj);
  11.835 +    }
  11.836 +
  11.837 +    /** Result based on one instance returned.
  11.838 +     */
  11.839 +    static final class R<T> extends WaitableResult<T> {
  11.840 +        /** reference our result is attached to (do not modify) */
  11.841 +        public ReferenceToResult<T> reference;
  11.842 +
  11.843 +        /** listeners on the results or pointer to one listener */
  11.844 +        private Object listeners;
  11.845 +
  11.846 +        public R() {
  11.847 +        }
  11.848 +
  11.849 +        /** Checks whether we have simple behaviour of complex.
  11.850 +         */
  11.851 +        private boolean isSimple() {
  11.852 +            Storage s = (Storage) reference.lookup.tree;
  11.853 +
  11.854 +            return DelegatingStorage.isSimple(s);
  11.855 +        }
  11.856 +
  11.857 +        //
  11.858 +        // Handling cache management for both cases, no caches
  11.859 +        // for simple (but mark that we needed them, so refresh can
  11.860 +        // be done in cloneList) and complex when all 3 types
  11.861 +        // of result are cached
  11.862 +        //
  11.863 +        private Object getFromCache(int indx) {
  11.864 +            if (isSimple()) {
  11.865 +                return null;
  11.866 +            }
  11.867 +
  11.868 +            Object maybeArray = reference.caches;
  11.869 +
  11.870 +            if (maybeArray instanceof Object[]) {
  11.871 +                return ((Object[]) maybeArray)[indx];
  11.872 +            }
  11.873 +
  11.874 +            return null;
  11.875 +        }
  11.876 +
  11.877 +        @SuppressWarnings("unchecked")
  11.878 +        private Set<Class<? extends T>> getClassesCache() {
  11.879 +            return (Set<Class<? extends T>>) getFromCache(0);
  11.880 +        }
  11.881 +
  11.882 +        private void setClassesCache(Set s) {
  11.883 +            if (isSimple()) {
  11.884 +                // mark it as being used
  11.885 +                reference.caches = reference;
  11.886 +
  11.887 +                return;
  11.888 +            }
  11.889 +
  11.890 +            if (!(reference.caches instanceof Object[])) {
  11.891 +                reference.caches = new Object[3];
  11.892 +            }
  11.893 +
  11.894 +            ((Object[]) reference.caches)[0] = s;
  11.895 +        }
  11.896 +
  11.897 +        @SuppressWarnings("unchecked")
  11.898 +        private Collection<T> getInstancesCache() {
  11.899 +            return (Collection<T>) getFromCache(1);
  11.900 +        }
  11.901 +
  11.902 +        private void setInstancesCache(Collection c) {
  11.903 +            if (isSimple()) {
  11.904 +                // mark it as being used
  11.905 +                reference.caches = reference;
  11.906 +
  11.907 +                return;
  11.908 +            }
  11.909 +
  11.910 +            if (!(reference.caches instanceof Object[])) {
  11.911 +                reference.caches = new Object[3];
  11.912 +            }
  11.913 +
  11.914 +            ((Object[]) reference.caches)[1] = c;
  11.915 +        }
  11.916 +
  11.917 +        @SuppressWarnings("unchecked")
  11.918 +        private Pair<T>[] getItemsCache() {
  11.919 +            return (Pair<T>[]) getFromCache(2);
  11.920 +        }
  11.921 +
  11.922 +        private void setItemsCache(Collection<?> c) {
  11.923 +            if (isSimple()) {
  11.924 +                // mark it as being used
  11.925 +                reference.caches = reference;
  11.926 +
  11.927 +                return;
  11.928 +            }
  11.929 +
  11.930 +            if (!(reference.caches instanceof Object[])) {
  11.931 +                reference.caches = new Object[3];
  11.932 +            }
  11.933 +
  11.934 +            ((Object[]) reference.caches)[2] = c.toArray(new Pair[0]);
  11.935 +        }
  11.936 +
  11.937 +        private void clearCaches() {
  11.938 +            if (reference.caches instanceof Object[]) {
  11.939 +                reference.caches = new Object[3];
  11.940 +            }
  11.941 +        }
  11.942 +
  11.943 +        /** Ok, register listeners to all classes and super classes.
  11.944 +         */
  11.945 +        public synchronized void addLookupListener(LookupListener l) {
  11.946 +            listeners = modifyListenerList(true, l, listeners);
  11.947 +        }
  11.948 +
  11.949 +        /** Ok, register listeners to all classes and super classes.
  11.950 +         */
  11.951 +        public synchronized void removeLookupListener(LookupListener l) {
  11.952 +            listeners = modifyListenerList(false, l, listeners);
  11.953 +        }
  11.954 +
  11.955 +        /** Delete all cached values, the template changed.
  11.956 +         */
  11.957 +        protected  void collectFires(Collection<Object> evAndListeners) {
  11.958 +            Object[] previousItems = getItemsCache();
  11.959 +            clearCaches();
  11.960 +            
  11.961 +            if (previousItems != null) {
  11.962 +                Object[] newArray = allItemsWithoutBeforeLookup().toArray();
  11.963 +
  11.964 +                if (compareArrays(previousItems, newArray)) {
  11.965 +                    // do not fire any change if nothing has been changed
  11.966 +                    return;
  11.967 +                }
  11.968 +            }
  11.969 +
  11.970 +            LookupListener[] arr;
  11.971 +
  11.972 +            synchronized (this) {
  11.973 +                if (listeners == null) {
  11.974 +                    return;
  11.975 +                }
  11.976 +
  11.977 +                if (listeners instanceof LookupListener) {
  11.978 +                    arr = new LookupListener[] { (LookupListener) listeners };
  11.979 +                } else {
  11.980 +                    ArrayList<?> l = (ArrayList<?>) listeners;
  11.981 +                    arr = l.toArray(new LookupListener[l.size()]);
  11.982 +                }
  11.983 +            }
  11.984 +
  11.985 +            final LookupListener[] ll = arr;
  11.986 +            final LookupEvent ev = new LookupEvent(this);
  11.987 +            notifyListeners(ll, ev, evAndListeners);
  11.988 +        }
  11.989 +
  11.990 +        public Collection<T> allInstances() {
  11.991 +            reference.lookup.beforeLookup(reference.template);
  11.992 +
  11.993 +            Collection<T> s = getInstancesCache();
  11.994 +
  11.995 +            if (s != null) {
  11.996 +                return s;
  11.997 +            }
  11.998 +
  11.999 +            Collection<Pair<T>> items = allItemsWithoutBeforeLookup();
 11.1000 +            ArrayList<T> list = new ArrayList<T>(items.size());
 11.1001 +
 11.1002 +            Iterator<Pair<T>> it = items.iterator();
 11.1003 +
 11.1004 +            while (it.hasNext()) {
 11.1005 +                Pair<T> item = it.next();
 11.1006 +                T obj = item.getInstance();
 11.1007 +
 11.1008 +                if (reference.template.getType().isInstance(obj)) {
 11.1009 +                    list.add(obj);
 11.1010 +                }
 11.1011 +            }
 11.1012 +            
 11.1013 +            s = Collections.unmodifiableList(list);
 11.1014 +            setInstancesCache(s);
 11.1015 +
 11.1016 +            return s;
 11.1017 +        }
 11.1018 +
 11.1019 +        /** Set of all classes.
 11.1020 +         *
 11.1021 +         */
 11.1022 +        @Override
 11.1023 +        public Set<Class<? extends T>> allClasses() {
 11.1024 +            reference.lookup.beforeLookup(reference.template);
 11.1025 +
 11.1026 +            Set<Class<? extends T>> s = getClassesCache();
 11.1027 +
 11.1028 +            if (s != null) {
 11.1029 +                return s;
 11.1030 +            }
 11.1031 +
 11.1032 +            s = new HashSet<Class<? extends T>>();
 11.1033 +
 11.1034 +            for (Pair<T> item : allItemsWithoutBeforeLookup()) {
 11.1035 +                Class<? extends T> clazz = item.getType();
 11.1036 +
 11.1037 +                if (clazz != null) {
 11.1038 +                    s.add(clazz);
 11.1039 +                }
 11.1040 +            }
 11.1041 +
 11.1042 +            s = Collections.unmodifiableSet(s);
 11.1043 +            setClassesCache(s);
 11.1044 +
 11.1045 +            return s;
 11.1046 +        }
 11.1047 +
 11.1048 +        /** Items are stored directly in the allItems.
 11.1049 +         */
 11.1050 +        @Override
 11.1051 +        public Collection<? extends Item<T>> allItems() {
 11.1052 +            reference.lookup.beforeLookup(reference.template);
 11.1053 +
 11.1054 +            return allItemsWithoutBeforeLookup();
 11.1055 +        }
 11.1056 +
 11.1057 +        /** Implements the search for allItems, but without asking for before lookup */
 11.1058 +        private Collection<Pair<T>> allItemsWithoutBeforeLookup() {
 11.1059 +            Pair<T>[] c = getItemsCache();
 11.1060 +
 11.1061 +            if (c != null) {
 11.1062 +                return Collections.unmodifiableList(Arrays.asList(c));
 11.1063 +            }
 11.1064 +
 11.1065 +            ArrayList<Pair<Object>> saferCheck = null;
 11.1066 +            AbstractLookup.Storage<?> t = reference.lookup.enterStorage();
 11.1067 +
 11.1068 +            try {
 11.1069 +                try {
 11.1070 +                    return Collections.unmodifiableCollection(initItems(t));
 11.1071 +                } catch (AbstractLookup.ISE ex) {
 11.1072 +                    // do less effective evaluation of items outside of the 
 11.1073 +                    // locked storage
 11.1074 +                    saferCheck = new ArrayList<Pair<Object>>();
 11.1075 +
 11.1076 +                    Enumeration<Pair<Object>> en = t.lookup(null); // get all Pairs
 11.1077 +
 11.1078 +                    while (en.hasMoreElements()) {
 11.1079 +                        Pair<Object> i = en.nextElement();
 11.1080 +                        saferCheck.add(i);
 11.1081 +                    }
 11.1082 +                }
 11.1083 +            } finally {
 11.1084 +                reference.lookup.exitStorage();
 11.1085 +            }
 11.1086 +            return extractPairs(saferCheck);
 11.1087 +        }
 11.1088 +
 11.1089 +        @SuppressWarnings("unchecked")
 11.1090 +        private Collection<Pair<T>> extractPairs(final ArrayList<Pair<Object>> saferCheck) {
 11.1091 +            TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
 11.1092 +            for (Pair<Object> i : saferCheck) {
 11.1093 +                if (matches(reference.template, i, false)) {
 11.1094 +                    items.add((Pair<T>)i);
 11.1095 +                }
 11.1096 +            }
 11.1097 +            return Collections.unmodifiableCollection(items);
 11.1098 +        }
 11.1099 +
 11.1100 +        /** Initializes items.
 11.1101 +         */
 11.1102 +        private Collection<Pair<T>> initItems(Storage<?> t) {
 11.1103 +            // manipulation with the tree must be synchronized
 11.1104 +            Enumeration<Pair<T>> en = t.lookup(reference.template.getType());
 11.1105 +
 11.1106 +            // InheritanceTree is comparator for AbstractLookup.Pairs
 11.1107 +            TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
 11.1108 +
 11.1109 +            while (en.hasMoreElements()) {
 11.1110 +                Pair<T> i = en.nextElement();
 11.1111 +
 11.1112 +                if (matches(reference.template, i, false)) {
 11.1113 +                    items.add(i);
 11.1114 +                }
 11.1115 +            }
 11.1116 +
 11.1117 +            // create a correctly sorted copy using the tree as the comparator
 11.1118 +            setItemsCache(items);
 11.1119 +
 11.1120 +            return items;
 11.1121 +        }
 11.1122 +
 11.1123 +        /** Used by proxy results to synchronize before lookup.
 11.1124 +         */
 11.1125 +        protected void beforeLookup(Lookup.Template t) {
 11.1126 +            if (t.getType() == reference.template.getType()) {
 11.1127 +                reference.lookup.beforeLookup(t);
 11.1128 +            }
 11.1129 +        }
 11.1130 +
 11.1131 +        /* Do not need to implement it, the default way is ok.
 11.1132 +        public boolean equals(java.lang.Object obj) {
 11.1133 +            return obj == this;
 11.1134 +        }
 11.1135 +        */
 11.1136 +        @Override
 11.1137 +        public String toString() {
 11.1138 +            return super.toString() + " for " + reference.template;
 11.1139 +        }
 11.1140 +    }
 11.1141 +     // end of R
 11.1142 +
 11.1143 +    /** A class that can be used by the creator of the AbstractLookup to
 11.1144 +     * control its content. It can be passed to AbstractLookup constructor
 11.1145 +     * and used to add and remove pairs.
 11.1146 +     *
 11.1147 +     * @since 1.25
 11.1148 +     */
 11.1149 +    public static class Content extends Object implements Serializable {
 11.1150 +        private static final long serialVersionUID = 1L;
 11.1151 +
 11.1152 +        // one of them is always null (except attach stage)
 11.1153 +
 11.1154 +        /** abstract lookup we are connected to */
 11.1155 +        private AbstractLookup al;
 11.1156 +        private transient Object notifyIn;
 11.1157 +        
 11.1158 +        /** Default constructor.
 11.1159 +         */
 11.1160 +        public Content() {
 11.1161 +            this(null);
 11.1162 +        }
 11.1163 +        
 11.1164 +        /** Creates a content associated with an executor to handle dispatch
 11.1165 +         * of changes.
 11.1166 +         * @param notifyIn the executor to notify changes in
 11.1167 +         * @since  7.16
 11.1168 +         */
 11.1169 +        public Content(Executor notifyIn) {
 11.1170 +            this.notifyIn = notifyIn;
 11.1171 +        }
 11.1172 +        
 11.1173 +        /** for testing purposes */
 11.1174 +        final void attachExecutor(Executor notifyIn) {
 11.1175 +            this.notifyIn = notifyIn;
 11.1176 +        }
 11.1177 +
 11.1178 +        /** A lookup attaches to this object.
 11.1179 +         */
 11.1180 +        final synchronized void attach(AbstractLookup al) {
 11.1181 +            if (this.al == null) {
 11.1182 +                this.al = al;
 11.1183 +
 11.1184 +                ArrayList<Pair> ep = getEarlyPairs();
 11.1185 +                if (ep != null) {
 11.1186 +                    notifyIn = null;
 11.1187 +                    setPairs(ep);
 11.1188 +                }
 11.1189 +            } else {
 11.1190 +                throw new IllegalStateException(
 11.1191 +                    "Trying to use content for " + al + " but it is already used for " + this.al
 11.1192 +                ); // NOI18N
 11.1193 +            }
 11.1194 +        }
 11.1195 +
 11.1196 +        /** The method to add instance to the lookup with.
 11.1197 +         * @param pair class/instance pair
 11.1198 +         */
 11.1199 +        public final void addPair(Pair<?> pair) {
 11.1200 +            AbstractLookup a = al;
 11.1201 +            Executor e = getExecutor();
 11.1202 +
 11.1203 +            if (a != null || e != null) {
 11.1204 +                a.addPair(pair, e);
 11.1205 +            } else {
 11.1206 +                if (notifyIn == null) {
 11.1207 +                    notifyIn = new ArrayList<Pair>(3);
 11.1208 +                }
 11.1209 +
 11.1210 +                getEarlyPairs().add(pair);
 11.1211 +            }
 11.1212 +        }
 11.1213 +
 11.1214 +        /** Remove instance.
 11.1215 +         * @param pair class/instance pair
 11.1216 +         */
 11.1217 +        public final void removePair(Pair<?> pair) {
 11.1218 +            AbstractLookup a = al;
 11.1219 +            Executor e = getExecutor();
 11.1220 +
 11.1221 +            if (a != null || e != null) {
 11.1222 +                a.removePair(pair, e);
 11.1223 +            } else {
 11.1224 +                if (notifyIn == null) {
 11.1225 +                    notifyIn = new ArrayList<Pair>(3);
 11.1226 +                }
 11.1227 +
 11.1228 +                getEarlyPairs().remove(pair);
 11.1229 +            }
 11.1230 +        }
 11.1231 +
 11.1232 +        /** Changes all pairs in the lookup to new values.
 11.1233 +         * @param c the collection of (Pair) objects
 11.1234 +         */
 11.1235 +        public final void setPairs(Collection<? extends Pair> c) {
 11.1236 +            AbstractLookup a = al;
 11.1237 +            Executor e = getExecutor();
 11.1238 +            
 11.1239 +            if (a != null || e != null) {
 11.1240 +                a.setPairs(c, e);
 11.1241 +            } else {
 11.1242 +                notifyIn = new ArrayList<Pair>(c);
 11.1243 +            }
 11.1244 +        }
 11.1245 +
 11.1246 +        @SuppressWarnings("unchecked")
 11.1247 +        private ArrayList<Pair> getEarlyPairs() {
 11.1248 +            Object o = notifyIn;
 11.1249 +            return o instanceof ArrayList ? (ArrayList<Pair>)o : null;
 11.1250 +        }
 11.1251 +        
 11.1252 +        private Executor getExecutor() {
 11.1253 +            Object o = notifyIn;
 11.1254 +            return o instanceof Executor ? (Executor)o : null;
 11.1255 +        }
 11.1256 +    }
 11.1257 +     // end of Content
 11.1258 +
 11.1259 +    /** Just a holder for index & modified values.
 11.1260 +     */
 11.1261 +    final static class Info extends Object {
 11.1262 +        public int index;
 11.1263 +        public Object transaction;
 11.1264 +
 11.1265 +        public Info(int i, Object t) {
 11.1266 +            index = i;
 11.1267 +            transaction = t;
 11.1268 +        }
 11.1269 +    }
 11.1270 +
 11.1271 +    /** Reference to a result R
 11.1272 +     */
 11.1273 +    static final class ReferenceToResult<T> extends WeakReference<R<T>> implements Runnable {
 11.1274 +        /** next refernece in chain, modified only from AbstractLookup or this */
 11.1275 +        private ReferenceToResult<?> next;
 11.1276 +
 11.1277 +        /** the template for the result */
 11.1278 +        public final Template<T> template;
 11.1279 +
 11.1280 +        /** the lookup we are attached to */
 11.1281 +        public final AbstractLookup lookup;
 11.1282 +
 11.1283 +        /** caches for results */
 11.1284 +        public Object caches;
 11.1285 +
 11.1286 +        /** Creates a weak refernece to a new result R in context of lookup
 11.1287 +         * for given template
 11.1288 +         */
 11.1289 +        private ReferenceToResult(R<T> result, AbstractLookup lookup, Template<T> template) {
 11.1290 +            super(result, activeQueue());
 11.1291 +            this.template = template;
 11.1292 +            this.lookup = lookup;
 11.1293 +            getResult().reference = this;
 11.1294 +        }
 11.1295 +
 11.1296 +        /** Returns the result or null
 11.1297 +         */
 11.1298 +        R<T> getResult() {
 11.1299 +            return get();
 11.1300 +        }
 11.1301 +
 11.1302 +        /** Cleans the reference. Implements Runnable interface, do not call
 11.1303 +         * directly.
 11.1304 +         */
 11.1305 +        public void run() {
 11.1306 +            lookup.cleanUpResult(this.template);
 11.1307 +        }
 11.1308 +
 11.1309 +        /** Clones the reference list to given Storage.
 11.1310 +         * @param storage storage to clone to
 11.1311 +         */
 11.1312 +        public void cloneList(AbstractLookup.Storage<?> storage) {
 11.1313 +            ReferenceIterator it = new ReferenceIterator(this);
 11.1314 +
 11.1315 +            while (it.next()) {
 11.1316 +                ReferenceToResult<?> current = it.current();
 11.1317 +                ReferenceToResult<?> newRef = current.cloneRef();
 11.1318 +                newRef.next = storage.registerReferenceToResult(newRef);
 11.1319 +                newRef.caches = current.caches;
 11.1320 +
 11.1321 +                if (current.caches == current) {
 11.1322 +                    current.getResult().initItems(storage);
 11.1323 +                }
 11.1324 +            }
 11.1325 +        }
 11.1326 +
 11.1327 +        private ReferenceToResult<T> cloneRef() {
 11.1328 +            return new ReferenceToResult<T>(getResult(), lookup, template);
 11.1329 +        }
 11.1330 +    }
 11.1331 +     // end of ReferenceToResult
 11.1332 +
 11.1333 +    /** Supporting class to iterate over linked list of ReferenceToResult
 11.1334 +     * Use:
 11.1335 +     * <PRE>
 11.1336 +     *  ReferenceIterator it = new ReferenceIterator (this.ref);
 11.1337 +     *  while (it.next ()) {
 11.1338 +     *    it.current (): // do some work
 11.1339 +     *  }
 11.1340 +     *  this.ref = it.first (); // remember the first one
 11.1341 +     */
 11.1342 +    static final class ReferenceIterator extends Object {
 11.1343 +        private ReferenceToResult<?> first;
 11.1344 +        private ReferenceToResult<?> current;
 11.1345 +
 11.1346 +        /** hard reference to current result, so it is not GCed meanwhile */
 11.1347 +        private R<?> currentResult;
 11.1348 +
 11.1349 +        /** Initializes the iterator with first reference.
 11.1350 +         */
 11.1351 +        public ReferenceIterator(ReferenceToResult<?> first) {
 11.1352 +            this.first = first;
 11.1353 +        }
 11.1354 +
 11.1355 +        /** Moves the current to next possition */
 11.1356 +        public boolean next() {
 11.1357 +            ReferenceToResult<?> prev;
 11.1358 +            ReferenceToResult<?> ref;
 11.1359 +
 11.1360 +            if (current == null) {
 11.1361 +                ref = first;
 11.1362 +                prev = null;
 11.1363 +            } else {
 11.1364 +                prev = current;
 11.1365 +                ref = current.next;
 11.1366 +            }
 11.1367 +
 11.1368 +            while (ref != null) {
 11.1369 +                R<?> result = ref.get();
 11.1370 +
 11.1371 +                if (result == null) {
 11.1372 +                    if (prev == null) {
 11.1373 +                        // move the head
 11.1374 +                        first = ref.next;
 11.1375 +                    } else {
 11.1376 +                        // skip over this reference
 11.1377 +                        prev.next = ref.next;
 11.1378 +                    }
 11.1379 +
 11.1380 +                    prev = ref;
 11.1381 +                    ref = ref.next;
 11.1382 +                } else {
 11.1383 +                    // we have found next item
 11.1384 +                    currentResult = result;
 11.1385 +                    current = ref;
 11.1386 +
 11.1387 +                    return true;
 11.1388 +                }
 11.1389 +            }
 11.1390 +
 11.1391 +            currentResult = null;
 11.1392 +            current = null;
 11.1393 +
 11.1394 +            return false;
 11.1395 +        }
 11.1396 +
 11.1397 +        /** Access to current reference.
 11.1398 +         */
 11.1399 +        public ReferenceToResult<?> current() {
 11.1400 +            return current;
 11.1401 +        }
 11.1402 +
 11.1403 +        /** Access to reference that is supposed to be the first one.
 11.1404 +         */
 11.1405 +        public ReferenceToResult<?> first() {
 11.1406 +            return first;
 11.1407 +        }
 11.1408 +    }
 11.1409 +
 11.1410 +    /** Signals that a lookup is being modified from a lookup query.
 11.1411 +     *
 11.1412 +     * @author  Jaroslav Tulach
 11.1413 +     */
 11.1414 +    static final class ISE extends IllegalStateException {
 11.1415 +        static final long serialVersionUID = 100L;
 11.1416 +        
 11.1417 +        /** list of jobs to execute. */
 11.1418 +        private java.util.List<Job> jobs;
 11.1419 +
 11.1420 +        /** @param msg message
 11.1421 +         */
 11.1422 +        public ISE(String msg) {
 11.1423 +            super(msg);
 11.1424 +        }
 11.1425 +
 11.1426 +        /** Registers a job to be executed partially out and partially in
 11.1427 +         * the lock over storage.
 11.1428 +         */
 11.1429 +        public void registerJob(Job job) {
 11.1430 +            if (jobs == null) {
 11.1431 +                jobs = new java.util.ArrayList<Job>();
 11.1432 +            }
 11.1433 +
 11.1434 +            jobs.add(job);
 11.1435 +        }
 11.1436 +
 11.1437 +        /** Executes the jobs outside, and then inside a locked session.
 11.1438 +         */
 11.1439 +        public void recover(AbstractLookup lookup) {
 11.1440 +            if (jobs == null) {
 11.1441 +                // no recovery plan, throw itself
 11.1442 +                throw this;
 11.1443 +            }
 11.1444 +
 11.1445 +            for (Job j : jobs) {
 11.1446 +                j.before();
 11.1447 +            }
 11.1448 +
 11.1449 +            AbstractLookup.Storage s = lookup.enterStorage();
 11.1450 +
 11.1451 +            try {
 11.1452 +                for (Job j : jobs) {
 11.1453 +                    j.inside();
 11.1454 +                }
 11.1455 +            } finally {
 11.1456 +                lookup.exitStorage();
 11.1457 +            }
 11.1458 +        }
 11.1459 +
 11.1460 +        /** A job to be executed partially outside and partially inside
 11.1461 +         * the storage lock.
 11.1462 +         */
 11.1463 +        static interface Job {
 11.1464 +            public void before();
 11.1465 +
 11.1466 +            public void inside();
 11.1467 +        }
 11.1468 +    }
 11.1469 +     // end of ISE
 11.1470 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ArrayStorage.java	Sat Oct 31 15:28:13 2009 +0100
    12.3 @@ -0,0 +1,477 @@
    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 +package org.openide.util.lookup;
   12.45 +
   12.46 +import org.openide.util.Lookup;
   12.47 +
   12.48 +
   12.49 +
   12.50 +import java.util.*;
   12.51 +import org.openide.util.lookup.AbstractLookup.Pair;
   12.52 +
   12.53 +
   12.54 +/** ArrayStorage of Pairs from AbstractLookup.
   12.55 + * @author  Jaroslav Tulach
   12.56 + */
   12.57 +final class ArrayStorage extends Object
   12.58 +implements AbstractLookup.Storage<ArrayStorage.Transaction> {
   12.59 +    /** default trashold */
   12.60 +    static final Integer DEFAULT_TRASH = new Integer(11);
   12.61 +
   12.62 +    /** list of items */
   12.63 +    private Object content;
   12.64 +
   12.65 +    /** linked list of refernces to results */
   12.66 +    private transient AbstractLookup.ReferenceToResult<?> results;
   12.67 +
   12.68 +    /** Constructor
   12.69 +     */
   12.70 +    public ArrayStorage() {
   12.71 +        this(DEFAULT_TRASH);
   12.72 +    }
   12.73 +
   12.74 +    /** Constructs new ArrayStorage */
   12.75 +    public ArrayStorage(Integer treshhold) {
   12.76 +        this.content = treshhold;
   12.77 +    }
   12.78 +
   12.79 +    /** Adds an item into the tree.
   12.80 +    * @param item to add
   12.81 +    * @return true if the Item has been added for the first time or false if some other
   12.82 +    *    item equal to this one already existed in the lookup
   12.83 +    */
   12.84 +    public boolean add(AbstractLookup.Pair<?> item, Transaction changed) {
   12.85 +        Object[] arr = changed.current;
   12.86 +
   12.87 +        if (changed.arr == null) {
   12.88 +            // just simple add of one item
   12.89 +            for (int i = 0; i < arr.length; i++) {
   12.90 +                if (arr[i] == null) {
   12.91 +                    arr[i] = item;
   12.92 +                    changed.add(item);
   12.93 +
   12.94 +                    return true;
   12.95 +                }
   12.96 +
   12.97 +                if (arr[i].equals(item)) {
   12.98 +                    // reassign the item number
   12.99 +                    item.setIndex(null, ((AbstractLookup.Pair) arr[i]).getIndex());
  12.100 +
  12.101 +                    // already there, but update it
  12.102 +                    arr[i] = item;
  12.103 +
  12.104 +                    return false;
  12.105 +                }
  12.106 +            }
  12.107 +
  12.108 +            // cannot happen as the beginTransaction ensured we can finish 
  12.109 +            // correctly
  12.110 +            throw new IllegalStateException();
  12.111 +        } else {
  12.112 +            // doing remainAll after that, let Transaction hold the new array
  12.113 +            int newIndex = changed.addPair(item);
  12.114 +
  12.115 +            for (int i = 0; i < arr.length; i++) {
  12.116 +                if (arr[i] == null) {
  12.117 +                    changed.add(item);
  12.118 +
  12.119 +                    return true;
  12.120 +                }
  12.121 +
  12.122 +                if (arr[i].equals(item)) {
  12.123 +                    // already there
  12.124 +                    if (i != newIndex) {
  12.125 +                        // change in index
  12.126 +                        changed.add(item);
  12.127 +
  12.128 +                        return false;
  12.129 +                    } else {
  12.130 +                        // no change
  12.131 +                        return false;
  12.132 +                    }
  12.133 +                }
  12.134 +            }
  12.135 +
  12.136 +            // if not found in the original array
  12.137 +            changed.add(item);
  12.138 +
  12.139 +            return true;
  12.140 +        }
  12.141 +    }
  12.142 +
  12.143 +    /** Removes an item.
  12.144 +    */
  12.145 +    public void remove(AbstractLookup.Pair item, Transaction changed) {
  12.146 +        Object[] arr = changed.current;
  12.147 +        if (arr == null) {
  12.148 +            return;
  12.149 +        }
  12.150 +
  12.151 +        int found = -1;
  12.152 +
  12.153 +        for (int i = 0; i < arr.length;) {
  12.154 +            if (arr[i] == null) {
  12.155 +                // end of task
  12.156 +                return;
  12.157 +            }
  12.158 +
  12.159 +            if ((found == -1) && arr[i].equals(item)) {
  12.160 +                // already there
  12.161 +                Pair<?> p = (Pair<?>)arr[i];
  12.162 +                p.setIndex(null, -1);
  12.163 +                changed.add(p);
  12.164 +                found = i;
  12.165 +            }
  12.166 +
  12.167 +            i++;
  12.168 +
  12.169 +            if (found != -1) {
  12.170 +                if (i < arr.length && !(arr[i] instanceof Integer)) {
  12.171 +                    // moving the array
  12.172 +                    arr[i - 1] = arr[i];
  12.173 +                } else {
  12.174 +                    arr[i - 1] = null;
  12.175 +                }
  12.176 +            }
  12.177 +        }
  12.178 +    }
  12.179 +
  12.180 +    /** Removes all items that are not present in the provided collection.
  12.181 +    * @param retain Pair -> AbstractLookup.Info map
  12.182 +    * @param notify set of Classes that has possibly changed
  12.183 +    */
  12.184 +    public void retainAll(Map retain, Transaction changed) {
  12.185 +        Object[] arr = changed.current;
  12.186 +
  12.187 +        for (int from = 0; from < arr.length; from++) {
  12.188 +            if (!(arr[from] instanceof AbstractLookup.Pair)) {
  12.189 +                // end of content
  12.190 +                break;
  12.191 +            }
  12.192 +
  12.193 +            AbstractLookup.Pair p = (AbstractLookup.Pair) arr[from];
  12.194 +
  12.195 +            AbstractLookup.Info info = (AbstractLookup.Info) retain.get(p);
  12.196 +
  12.197 +            if (info == null) {
  12.198 +                // was removed
  12.199 +
  12.200 +                /*
  12.201 +                if (info != null) {
  12.202 +                if (info.index < arr.length) {
  12.203 +                    newArr[info.index] = p;
  12.204 +                }
  12.205 +
  12.206 +                if (p.getIndex() != info.index) {
  12.207 +                    p.setIndex (null, info.index);
  12.208 +                    changed.add (p);
  12.209 +                }
  12.210 +                } else {
  12.211 +                // removed
  12.212 +                 */
  12.213 +                changed.add(p);
  12.214 +            }
  12.215 +        }
  12.216 +    }
  12.217 +
  12.218 +    /** Queries for instances of given class.
  12.219 +    * @param clazz the class to check
  12.220 +    * @return enumeration of Item
  12.221 +    * @see #unsorted
  12.222 +    */
  12.223 +    public <T> Enumeration<Pair<T>> lookup(final Class<T> clazz) {
  12.224 +        if (content instanceof Object[]) {
  12.225 +            final Enumeration<Object> all = InheritanceTree.arrayEn((Object[]) content);
  12.226 +            class JustPairs implements Enumeration<Pair<T>> {
  12.227 +                private Pair<T> next;
  12.228 +
  12.229 +                @SuppressWarnings("unchecked")
  12.230 +                private Pair<T> findNext() {
  12.231 +                    for (;;) {
  12.232 +                        if (next != null) {
  12.233 +                            return next;
  12.234 +                        }
  12.235 +                        if (!all.hasMoreElements()) {
  12.236 +                            return null;
  12.237 +                        }
  12.238 +                        Object o = all.nextElement();
  12.239 +                        boolean ok;
  12.240 +                        if (o instanceof AbstractLookup.Pair) {
  12.241 +                            ok = (clazz == null) || ((AbstractLookup.Pair<?>) o).instanceOf(clazz);
  12.242 +                        } else {
  12.243 +                            ok = false;
  12.244 +                        }
  12.245 +
  12.246 +                        next = ok ? (Pair<T>) o : null;
  12.247 +                    }
  12.248 +                }
  12.249 +                
  12.250 +                public boolean hasMoreElements() {
  12.251 +                    return findNext() != null;
  12.252 +                }
  12.253 +
  12.254 +                public Pair<T> nextElement() {
  12.255 +                    Pair<T> r = findNext();
  12.256 +                    if (r == null) {
  12.257 +                        throw new NoSuchElementException();
  12.258 +                    }
  12.259 +                    next = null;
  12.260 +                    return r;
  12.261 +                }
  12.262 +            } // end of JustPairs
  12.263 +            return new JustPairs();
  12.264 +        } else {
  12.265 +            return InheritanceTree.emptyEn();
  12.266 +        }
  12.267 +    }
  12.268 +
  12.269 +    /** Associates another result with this storage.
  12.270 +     */
  12.271 +    public AbstractLookup.ReferenceToResult registerReferenceToResult(AbstractLookup.ReferenceToResult<?> newRef) {
  12.272 +        AbstractLookup.ReferenceToResult prev = this.results;
  12.273 +        this.results = newRef;
  12.274 +
  12.275 +        return prev;
  12.276 +    }
  12.277 +
  12.278 +    /** Cleanup the references
  12.279 +     */
  12.280 +    public AbstractLookup.ReferenceToResult cleanUpResult(Lookup.Template<?> templ) {
  12.281 +        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
  12.282 +
  12.283 +        while (it.next()) {
  12.284 +            // empty
  12.285 +        }
  12.286 +
  12.287 +        return this.results = it.first();
  12.288 +    }
  12.289 +
  12.290 +    /** We use a hash set of all modified Pair to handle the transaction */
  12.291 +    public Transaction beginTransaction(int ensure) {
  12.292 +        return new Transaction(ensure, content);
  12.293 +    }
  12.294 +
  12.295 +    /** Extract all results.
  12.296 +     */
  12.297 +    public void endTransaction(Transaction changed, Set<AbstractLookup.R> modified) {
  12.298 +        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
  12.299 +
  12.300 +        if (changed.arr == null) {
  12.301 +            // either add or remove, only check the content of check HashSet
  12.302 +            while (it.next()) {
  12.303 +                AbstractLookup.ReferenceToResult ref = it.current();
  12.304 +                Iterator<Pair<?>> pairs = changed.iterator();
  12.305 +
  12.306 +                while (pairs.hasNext()) {
  12.307 +                    AbstractLookup.Pair p = (AbstractLookup.Pair) pairs.next();
  12.308 +
  12.309 +                    if (AbstractLookup.matches(ref.template, p, true)) {
  12.310 +                        modified.add(ref.getResult());
  12.311 +                    }
  12.312 +                }
  12.313 +            }
  12.314 +        } else {
  12.315 +            // do full check of changes
  12.316 +            while (it.next()) {
  12.317 +                AbstractLookup.ReferenceToResult ref = it.current();
  12.318 +
  12.319 +                int oldIndex = -1;
  12.320 +                int newIndex = -1;
  12.321 +
  12.322 +                for (;;) {
  12.323 +                    oldIndex = findMatching(ref.template, changed.current, oldIndex);
  12.324 +                    newIndex = findMatching(ref.template, changed.arr, newIndex);
  12.325 +
  12.326 +                    if ((oldIndex == -1) && (newIndex == -1)) {
  12.327 +                        break;
  12.328 +                    }
  12.329 +
  12.330 +                    if (
  12.331 +                        (oldIndex == -1) || (newIndex == -1) ||
  12.332 +                            !changed.current[oldIndex].equals(changed.arr[newIndex])
  12.333 +                    ) {
  12.334 +                        modified.add(ref.getResult());
  12.335 +
  12.336 +                        break;
  12.337 +                    }
  12.338 +                }
  12.339 +            }
  12.340 +        }
  12.341 +
  12.342 +        this.results = it.first();
  12.343 +        this.content = changed.newContent(this.content);
  12.344 +    }
  12.345 +
  12.346 +    private static int findMatching(Lookup.Template t, Object[] arr, int from) {
  12.347 +        while (++from < arr.length) {
  12.348 +            if (arr[from] instanceof AbstractLookup.Pair) {
  12.349 +                if (AbstractLookup.matches(t, (AbstractLookup.Pair) arr[from], true)) {
  12.350 +                    return from;
  12.351 +                }
  12.352 +            }
  12.353 +        }
  12.354 +
  12.355 +        return -1;
  12.356 +    }
  12.357 +
  12.358 +    /** HashSet with additional field for new array which is callocated
  12.359 +     * in case we are doing replace to hold all new items.
  12.360 +     */
  12.361 +    static final class Transaction extends HashSet<Pair<?>> {
  12.362 +        /** array with current objects */
  12.363 +        public final Object[] current;
  12.364 +
  12.365 +        /** array with new objects */
  12.366 +        public final Object[] arr;
  12.367 +
  12.368 +        /** number of objects in the array */
  12.369 +        private int cnt;
  12.370 +
  12.371 +        public Transaction(int ensure, Object currentContent) {
  12.372 +            Integer trashold;
  12.373 +            Object[] _arr;
  12.374 +
  12.375 +            if (currentContent instanceof Integer) {
  12.376 +                trashold = (Integer) currentContent;
  12.377 +                _arr = null;
  12.378 +            } else {
  12.379 +                _arr = (Object[]) currentContent;
  12.380 +
  12.381 +                if (_arr[_arr.length - 1] instanceof Integer) {
  12.382 +                    trashold = (Integer) _arr[_arr.length - 1];
  12.383 +                } else {
  12.384 +                    // nowhere to grow we have reached the limit
  12.385 +                    trashold = null;
  12.386 +                }
  12.387 +            }
  12.388 +
  12.389 +            int maxSize = (trashold == null) ? _arr.length : trashold.intValue();
  12.390 +
  12.391 +            if (ensure > maxSize) {
  12.392 +                throw new UnsupportedOperationException();
  12.393 +            }
  12.394 +
  12.395 +            if (ensure == -1) {
  12.396 +                // remove => it is ok
  12.397 +                this.current = currentContent instanceof Integer ? null : (Object[]) currentContent;
  12.398 +                this.arr = null;
  12.399 +
  12.400 +                return;
  12.401 +            }
  12.402 +
  12.403 +            if (ensure == -2) {
  12.404 +                // adding one
  12.405 +                if (_arr == null) {
  12.406 +                    // first time add, let's allocate the array
  12.407 +                    _arr = new Object[2];
  12.408 +                    _arr[1] = trashold;
  12.409 +                } else {
  12.410 +                    if (_arr[_arr.length - 1] instanceof AbstractLookup.Pair) {
  12.411 +                        // we are full
  12.412 +                        throw new UnsupportedOperationException();
  12.413 +                    } else {
  12.414 +                        // ensure we have allocated enough space
  12.415 +                        if (_arr.length < 2 || _arr[_arr.length - 2] != null) {
  12.416 +                            // double the array
  12.417 +                            int newSize = (_arr.length - 1) * 2;
  12.418 +                            
  12.419 +                            if (newSize <= 1) {
  12.420 +                                newSize = 2;
  12.421 +                            }
  12.422 +
  12.423 +                            if (newSize > maxSize) {
  12.424 +                                newSize = maxSize;
  12.425 +
  12.426 +                                if (newSize <= _arr.length) {
  12.427 +                                    // no space to get in
  12.428 +                                    throw new UnsupportedOperationException();
  12.429 +                                }
  12.430 +
  12.431 +                                _arr = new Object[newSize];
  12.432 +                            } else {
  12.433 +                                // still a lot of space
  12.434 +                                _arr = new Object[newSize + 1];
  12.435 +                                _arr[newSize] = trashold;
  12.436 +                            }
  12.437 +
  12.438 +                            // copy content of original array without the last Integer into 
  12.439 +                            // the new one
  12.440 +                            System.arraycopy(currentContent, 0, _arr, 0, ((Object[]) currentContent).length - 1);
  12.441 +                        }
  12.442 +                    }
  12.443 +                }
  12.444 +
  12.445 +                this.current = _arr;
  12.446 +                this.arr = null;
  12.447 +            } else {
  12.448 +                // allocate array for complete replacement
  12.449 +                if (ensure == maxSize) {
  12.450 +                    this.arr = new Object[ensure];
  12.451 +                } else {
  12.452 +                    this.arr = new Object[ensure + 1];
  12.453 +                    this.arr[ensure] = trashold;
  12.454 +                }
  12.455 +
  12.456 +                this.current = (currentContent instanceof Object[]) ? (Object[]) currentContent : new Object[0];
  12.457 +            }
  12.458 +        }
  12.459 +
  12.460 +        public int addPair(AbstractLookup.Pair<?> p) {
  12.461 +            p.setIndex(null, cnt);
  12.462 +            arr[cnt++] = p;
  12.463 +
  12.464 +            return p.getIndex();
  12.465 +        }
  12.466 +
  12.467 +        public Object newContent(Object prev) {
  12.468 +            if (arr == null) {
  12.469 +                if (current == null) {
  12.470 +                    return prev;
  12.471 +                } else {
  12.472 +                    return current;
  12.473 +                }
  12.474 +            } else {
  12.475 +                return arr;
  12.476 +            }
  12.477 +        }
  12.478 +    }
  12.479 +     // end of Transaction
  12.480 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/Bundle.properties	Sat Oct 31 15:28:13 2009 +0100
    13.3 @@ -0,0 +1,1 @@
    13.4 +OpenIDE-Module-Name=Lookup
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/DelegatingStorage.java	Sat Oct 31 15:28:13 2009 +0100
    14.3 @@ -0,0 +1,180 @@
    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.lookup;
   14.45 +
   14.46 +import org.openide.util.Lookup;
   14.47 +
   14.48 +import java.io.*;
   14.49 +
   14.50 +import java.lang.ref.WeakReference;
   14.51 +
   14.52 +import java.util.*;
   14.53 +import org.openide.util.lookup.AbstractLookup.Pair;
   14.54 +
   14.55 +
   14.56 +/** Storages that can switch between another storages.
   14.57 + * @author  Jaroslav Tulach
   14.58 + */
   14.59 +final class DelegatingStorage<Transaction> extends Object
   14.60 +implements Serializable, AbstractLookup.Storage<Transaction> {
   14.61 +    /** object to delegate to */
   14.62 +    private AbstractLookup.Storage<Transaction> delegate;
   14.63 +
   14.64 +    /** thread just accessing the storage */
   14.65 +    private Thread owner;
   14.66 +
   14.67 +    public DelegatingStorage(AbstractLookup.Storage<Transaction> d) {
   14.68 +        this.delegate = d;
   14.69 +        this.owner = Thread.currentThread();
   14.70 +    }
   14.71 +
   14.72 +    /** Never serialize yourself, always put there the delegate */
   14.73 +    public Object writeReplace() {
   14.74 +        return this.delegate;
   14.75 +    }
   14.76 +
   14.77 +    /** Method to check whether there is not multiple access from the same thread.
   14.78 +     */
   14.79 +    public void checkForTreeModification() {
   14.80 +        if (Thread.currentThread() == owner) {
   14.81 +            throw new AbstractLookup.ISE("You are trying to modify lookup from lookup query!"); // NOI18N
   14.82 +        }
   14.83 +    }
   14.84 +
   14.85 +    /** Checks whether we have simple behaviour or complex.
   14.86 +     */
   14.87 +    public static boolean isSimple(AbstractLookup.Storage s) {
   14.88 +        if (s instanceof DelegatingStorage) {
   14.89 +            return ((DelegatingStorage) s).delegate instanceof ArrayStorage;
   14.90 +        } else {
   14.91 +            return s instanceof ArrayStorage;
   14.92 +        }
   14.93 +    }
   14.94 +
   14.95 +    /** Exits from the owners ship of the storage.
   14.96 +     */
   14.97 +    public AbstractLookup.Storage<Transaction> exitDelegate() {
   14.98 +        if (Thread.currentThread() != owner) {
   14.99 +            throw new IllegalStateException("Onwer: " + owner + " caller: " + Thread.currentThread()); // NOI18N
  14.100 +        }
  14.101 +
  14.102 +        AbstractLookup.Storage<Transaction> d = delegate;
  14.103 +        delegate = null;
  14.104 +
  14.105 +        return d;
  14.106 +    }
  14.107 +
  14.108 +    public boolean add(AbstractLookup.Pair<?> item, Transaction transaction) {
  14.109 +        return delegate.add(item, transaction);
  14.110 +    }
  14.111 +
  14.112 +    public void remove(org.openide.util.lookup.AbstractLookup.Pair item, Transaction transaction) {
  14.113 +        delegate.remove(item, transaction);
  14.114 +    }
  14.115 +
  14.116 +    public void retainAll(Map retain, Transaction transaction) {
  14.117 +        delegate.retainAll(retain, transaction);
  14.118 +    }
  14.119 +
  14.120 +    /** A special method to change the backing storage.
  14.121 +     * In fact it is not much typesafe as it changes the
  14.122 +     * type of Transaction but we know that nobody is currently
  14.123 +     * holding a transaction object, so there cannot be inconsitencies.
  14.124 +     */
  14.125 +    @SuppressWarnings("unchecked")
  14.126 +    private void changeDelegate(InheritanceTree st) {
  14.127 +        delegate = (AbstractLookup.Storage<Transaction>)st;
  14.128 +    }
  14.129 +
  14.130 +    public Transaction beginTransaction(int ensure) {
  14.131 +        try {
  14.132 +            return delegate.beginTransaction(ensure);
  14.133 +        } catch (UnsupportedOperationException ex) {
  14.134 +            // let's convert to InheritanceTree
  14.135 +            ArrayStorage arr = (ArrayStorage) delegate;
  14.136 +            InheritanceTree inh = new InheritanceTree();
  14.137 +            changeDelegate(inh);
  14.138 +
  14.139 +            //
  14.140 +            // Copy content
  14.141 +            //
  14.142 +            Enumeration<Pair<Object>> en = arr.lookup(Object.class);
  14.143 +
  14.144 +            while (en.hasMoreElements()) {
  14.145 +                if (!inh.add(en.nextElement(), new ArrayList<Class>())) {
  14.146 +                    throw new IllegalStateException("All objects have to be accepted"); // NOI18N
  14.147 +                }
  14.148 +            }
  14.149 +
  14.150 +            //
  14.151 +            // Copy listeners
  14.152 +            //
  14.153 +            AbstractLookup.ReferenceToResult<?> ref = arr.cleanUpResult(null);
  14.154 +
  14.155 +            if (ref != null) {
  14.156 +                ref.cloneList(inh);
  14.157 +            }
  14.158 +
  14.159 +            // we have added the current content and now we can start transaction
  14.160 +            return delegate.beginTransaction(ensure);
  14.161 +        }
  14.162 +    }
  14.163 +
  14.164 +    public org.openide.util.lookup.AbstractLookup.ReferenceToResult cleanUpResult(
  14.165 +        org.openide.util.Lookup.Template templ
  14.166 +    ) {
  14.167 +        return delegate.cleanUpResult(templ);
  14.168 +    }
  14.169 +
  14.170 +    public void endTransaction(Transaction transaction, Set<AbstractLookup.R> modified) {
  14.171 +        delegate.endTransaction(transaction, modified);
  14.172 +    }
  14.173 +
  14.174 +    public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
  14.175 +        return delegate.lookup(clazz);
  14.176 +    }
  14.177 +
  14.178 +    public org.openide.util.lookup.AbstractLookup.ReferenceToResult registerReferenceToResult(
  14.179 +        org.openide.util.lookup.AbstractLookup.ReferenceToResult newRef
  14.180 +    ) {
  14.181 +        return delegate.registerReferenceToResult(newRef);
  14.182 +    }
  14.183 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ExcludingLookup.java	Sat Oct 31 15:28:13 2009 +0100
    15.3 @@ -0,0 +1,428 @@
    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.lang.ref.Reference;
   15.47 +import java.lang.ref.WeakReference;
   15.48 +import org.openide.util.Lookup;
   15.49 +import org.openide.util.LookupListener;
   15.50 +
   15.51 +import java.util.*;
   15.52 +import org.openide.util.LookupEvent;
   15.53 +
   15.54 +
   15.55 +/** Allows exclusion of certain instances from lookup.
   15.56 + *
   15.57 + * @author Jaroslav Tulach
   15.58 + */
   15.59 +final class ExcludingLookup extends org.openide.util.Lookup {
   15.60 +    /** the other lookup that we delegate to */
   15.61 +    private Lookup delegate;
   15.62 +
   15.63 +    /** classes to exclude (Class[]) or just one class (Class) */
   15.64 +    private Object classes;
   15.65 +
   15.66 +    /**
   15.67 +     * Creates new Result object with supplied instances parameter.
   15.68 +     * @param instances to be used to return from the lookup
   15.69 +     */
   15.70 +    ExcludingLookup(Lookup delegate, Class[] classes) {
   15.71 +        this.delegate = delegate;
   15.72 +
   15.73 +        for (Class c : classes) {
   15.74 +            if (c == null) {
   15.75 +                throw new NullPointerException();
   15.76 +            }
   15.77 +        }
   15.78 +        if (classes.length == 1) {
   15.79 +            this.classes = classes[0];
   15.80 +        } else {
   15.81 +            this.classes = classes;
   15.82 +        }
   15.83 +    }
   15.84 +
   15.85 +    @Override
   15.86 +    public String toString() {
   15.87 +        return "ExcludingLookup: " + delegate + " excludes: " + Arrays.asList(classes()); // NOI18N
   15.88 +    }
   15.89 +
   15.90 +    public <T> Result<T> lookup(Template<T> template) {
   15.91 +        if (template == null) {
   15.92 +            throw new NullPointerException();
   15.93 +        }
   15.94 +
   15.95 +        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
   15.96 +            // empty result
   15.97 +            return Lookup.EMPTY.lookup(template);
   15.98 +        }
   15.99 +
  15.100 +        return new R<T>(template.getType(), delegate.lookup(template));
  15.101 +    }
  15.102 +
  15.103 +    public <T> T lookup(Class<T> clazz) {
  15.104 +        if (areSubclassesOfThisClassAlwaysExcluded(clazz)) {
  15.105 +            return null;
  15.106 +        }
  15.107 +
  15.108 +        T res = delegate.lookup(clazz);
  15.109 +
  15.110 +        if (isObjectAccessible(clazz, res, 0)) {
  15.111 +            return res;
  15.112 +        } else {
  15.113 +            return null;
  15.114 +        }
  15.115 +    }
  15.116 +
  15.117 +    @Override
  15.118 +    public <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
  15.119 +        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
  15.120 +            return null;
  15.121 +        }
  15.122 +
  15.123 +        Lookup.Item<T> retValue = delegate.lookupItem(template);
  15.124 +
  15.125 +        if (isObjectAccessible(template.getType(), retValue, 2)) {
  15.126 +            return retValue;
  15.127 +        } else {
  15.128 +            return null;
  15.129 +        }
  15.130 +    }
  15.131 +
  15.132 +    /** @return true if the instance of class c shall never be returned from this lookup
  15.133 +     */
  15.134 +    private boolean areSubclassesOfThisClassAlwaysExcluded(Class<?> c) {
  15.135 +        Class<?>[] arr = classes();
  15.136 +
  15.137 +        for (int i = 0; i < arr.length; i++) {
  15.138 +            if (arr[i].isAssignableFrom(c)) {
  15.139 +                return true;
  15.140 +            }
  15.141 +        }
  15.142 +
  15.143 +        return false;
  15.144 +    }
  15.145 +
  15.146 +    /** Returns the array of classes this lookup filters.
  15.147 +     */
  15.148 +    final Class<?>[] classes() {
  15.149 +        if (classes instanceof Class[]) {
  15.150 +            return (Class[]) classes;
  15.151 +        } else {
  15.152 +            return new Class[] { (Class) classes };
  15.153 +        }
  15.154 +    }
  15.155 +
  15.156 +    /** Does a check whether two classes are accessible (in the super/sub class)
  15.157 +     * releation ship without walking thru any of the classes mentioned in the
  15.158 +     * barrier.
  15.159 +     */
  15.160 +    private static boolean isAccessible(Class<?>[] barriers, Class<?> from, Class<?> to) {
  15.161 +        if ((to == null) || !from.isAssignableFrom(to)) {
  15.162 +            // no way to reach each other by walking up
  15.163 +            return false;
  15.164 +        }
  15.165 +
  15.166 +        for (int i = 0; i < barriers.length; i++) {
  15.167 +            if (to == barriers[i]) {
  15.168 +                return false;
  15.169 +            }
  15.170 +        }
  15.171 +
  15.172 +        if (from == to) {
  15.173 +            return true;
  15.174 +        }
  15.175 +
  15.176 +        //
  15.177 +        // depth first search
  15.178 +        //
  15.179 +        if (isAccessible(barriers, from, to.getSuperclass())) {
  15.180 +            return true;
  15.181 +        }
  15.182 +
  15.183 +        Class[] interfaces = to.getInterfaces();
  15.184 +
  15.185 +        for (int i = 0; i < interfaces.length; i++) {
  15.186 +            if (isAccessible(barriers, from, interfaces[i])) {
  15.187 +                return true;
  15.188 +            }
  15.189 +        }
  15.190 +
  15.191 +        return false;
  15.192 +    }
  15.193 +
  15.194 +    /** based on type decides whether the class accepts or not anObject
  15.195 +     * @param from the base type of the query
  15.196 +     * @param to depending on value of type either Object, Class or Item
  15.197 +     * @param type 0,1,2 for Object, Class or Item
  15.198 +     * @return true if we can access the to from from by walking around the bariers
  15.199 +     */
  15.200 +    private final boolean isObjectAccessible(Class from, Object to, int type) {
  15.201 +        if (to == null) {
  15.202 +            return false;
  15.203 +        }
  15.204 +
  15.205 +        return isObjectAccessible(classes(), from, to, type);
  15.206 +    }
  15.207 +
  15.208 +    /** based on type decides whether the class accepts or not anObject
  15.209 +     * @param barriers classes to avoid when testing reachability
  15.210 +     * @param from the base type of the query
  15.211 +     * @param to depending on value of type either Object, Class or Item
  15.212 +     * @param type 0,1,2 for Object, Class or Item
  15.213 +     * @return true if we can access the to from from by walking around the bariers
  15.214 +     */
  15.215 +    static final boolean isObjectAccessible(Class[] barriers, Class from, Object to, int type) {
  15.216 +        if (to == null) {
  15.217 +            return false;
  15.218 +        }
  15.219 +
  15.220 +        switch (type) {
  15.221 +        case 0:
  15.222 +            return isAccessible(barriers, from, to.getClass());
  15.223 +
  15.224 +        case 1:
  15.225 +            return isAccessible(barriers, from, (Class) to);
  15.226 +
  15.227 +        case 2: {
  15.228 +            Item item = (Item) to;
  15.229 +
  15.230 +            return isAccessible(barriers, from, item.getType());
  15.231 +        }
  15.232 +
  15.233 +        default:
  15.234 +            throw new IllegalStateException("Type: " + type);
  15.235 +        }
  15.236 +    }
  15.237 +
  15.238 +    /** Filters collection accroding to set of given filters.
  15.239 +     */
  15.240 +    final <E, T extends Collection<E>> T filter(
  15.241 +        Class<?>[] arr, Class<?> from, T c, int type, T prototype
  15.242 +    ) {
  15.243 +        T ret = null;
  15.244 +
  15.245 +
  15.246 +// optimistic strategy expecting we will not need to filter
  15.247 +TWICE: 
  15.248 +        for (;;) {
  15.249 +            Iterator<E> it = c.iterator();
  15.250 +BIG: 
  15.251 +            while (it.hasNext()) {
  15.252 +                E res = it.next();
  15.253 +
  15.254 +                if (!isObjectAccessible(arr, from, res, type)) {
  15.255 +                    if (ret == null) {
  15.256 +                        // we need to restart the scanning again 
  15.257 +                        // as there is an active filter
  15.258 +                        ret = prototype;
  15.259 +                        continue TWICE;
  15.260 +                    }
  15.261 +
  15.262 +                    continue BIG;
  15.263 +                }
  15.264 +
  15.265 +                if (ret != null) {
  15.266 +                    // if we are running the second round from TWICE
  15.267 +                    ret.add(res);
  15.268 +                }
  15.269 +            }
  15.270 +
  15.271 +            // ok, processed
  15.272 +            break TWICE;
  15.273 +        }
  15.274 +
  15.275 +        return (ret != null) ? ret : c;
  15.276 +    }
  15.277 +
  15.278 +    /** Delegating result that filters unwanted items and instances.
  15.279 +     */
  15.280 +    private final class R<T> extends WaitableResult<T> implements LookupListener {
  15.281 +        private Result<T> result;
  15.282 +        private WeakResult<T> weak;
  15.283 +        private Object listeners;
  15.284 +        private Class<?> from;
  15.285 +
  15.286 +        R(Class<?> from, Result<T> delegate) {
  15.287 +            this.from = from;
  15.288 +            this.result = delegate;
  15.289 +            this.weak = new WeakResult<T>(this, delegate);
  15.290 +        }
  15.291 +
  15.292 +        protected void beforeLookup(Template t) {
  15.293 +            if (result instanceof WaitableResult) {
  15.294 +                ((WaitableResult) result).beforeLookup(t);
  15.295 +            }
  15.296 +        }
  15.297 +
  15.298 +        public void addLookupListener(LookupListener l) {
  15.299 +            boolean add;
  15.300 +
  15.301 +            synchronized (this) {
  15.302 +                listeners = AbstractLookup.modifyListenerList(true, l, listeners);
  15.303 +                add = listeners != null;
  15.304 +            }
  15.305 +
  15.306 +            if (add) {
  15.307 +                result.addLookupListener(weak);
  15.308 +            }
  15.309 +        }
  15.310 +
  15.311 +        public void removeLookupListener(LookupListener l) {
  15.312 +            boolean remove;
  15.313 +
  15.314 +            synchronized (this) {
  15.315 +                listeners = AbstractLookup.modifyListenerList(false, l, listeners);
  15.316 +                remove = listeners == null;
  15.317 +            }
  15.318 +
  15.319 +            if (remove) {
  15.320 +                result.removeLookupListener(weak);
  15.321 +            }
  15.322 +        }
  15.323 +
  15.324 +        public Collection<? extends T> allInstances() {
  15.325 +            return openCol(result.allInstances(), 0);
  15.326 +        }
  15.327 +
  15.328 +        private <S> Collection<S> openCol(Collection<S> c, int type) {
  15.329 +            return filter(classes(), from, c, type, new ArrayList<S>(c.size()));
  15.330 +        }
  15.331 +
  15.332 +        @Override
  15.333 +        public Set<Class<? extends T>> allClasses() {
  15.334 +            return filter(classes(), from, result.allClasses(), 1, new HashSet<Class<? extends T>>());
  15.335 +        }
  15.336 +
  15.337 +        @Override
  15.338 +        public Collection<? extends Item<T>> allItems() {
  15.339 +            return openCol(result.allItems(), 2);
  15.340 +        }
  15.341 +
  15.342 +        public void resultChanged(org.openide.util.LookupEvent ev) {
  15.343 +            if (ev.getSource() == result) {
  15.344 +                collectFires(null);
  15.345 +            }
  15.346 +        }
  15.347 +
  15.348 +        protected void collectFires(Collection<Object> evAndListeners) {
  15.349 +            LookupListener[] arr;
  15.350 +
  15.351 +            synchronized (this) {
  15.352 +                if (listeners == null) {
  15.353 +                    return;
  15.354 +                }
  15.355 +
  15.356 +                if (listeners instanceof LookupListener) {
  15.357 +                    arr = new LookupListener[] { (LookupListener) listeners };
  15.358 +                } else {
  15.359 +                    ArrayList<?> l = (ArrayList<?>) listeners;
  15.360 +                    arr = l.toArray(new LookupListener[l.size()]);
  15.361 +                }
  15.362 +            }
  15.363 +
  15.364 +            final LookupListener[] ll = arr;
  15.365 +            final org.openide.util.LookupEvent newev = new org.openide.util.LookupEvent(this);
  15.366 +            AbstractLookup.notifyListeners(ll, newev, evAndListeners);
  15.367 +        }
  15.368 +    } // end of R
  15.369 +    
  15.370 +    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
  15.371 +        private Lookup.Result source;
  15.372 +        private Reference<R<T>> result;
  15.373 +        
  15.374 +        public WeakResult(R<T> r, Lookup.Result<T> s) {
  15.375 +            this.result = new WeakReference<R<T>>(r);
  15.376 +            this.source = s;
  15.377 +        }
  15.378 +        
  15.379 +        protected void beforeLookup(Lookup.Template t) {
  15.380 +            R r = (R)result.get();
  15.381 +            if (r != null) {
  15.382 +                r.beforeLookup(t);
  15.383 +            } else {
  15.384 +                source.removeLookupListener(this);
  15.385 +            }
  15.386 +        }
  15.387 +
  15.388 +        protected void collectFires(Collection<Object> evAndListeners) {
  15.389 +            R<T> r = result.get();
  15.390 +            if (r != null) {
  15.391 +                r.collectFires(evAndListeners);
  15.392 +            } else {
  15.393 +                source.removeLookupListener(this);
  15.394 +            }
  15.395 +        }
  15.396 +
  15.397 +        public void addLookupListener(LookupListener l) {
  15.398 +            assert false;
  15.399 +        }
  15.400 +
  15.401 +        public void removeLookupListener(LookupListener l) {
  15.402 +            assert false;
  15.403 +        }
  15.404 +
  15.405 +        public Collection<T> allInstances() {
  15.406 +            assert false;
  15.407 +            return null;
  15.408 +        }
  15.409 +
  15.410 +        public void resultChanged(LookupEvent ev) {
  15.411 +            R r = (R)result.get();
  15.412 +            if (r != null) {
  15.413 +                r.resultChanged(ev);
  15.414 +            } else {
  15.415 +                source.removeLookupListener(this);
  15.416 +            }
  15.417 +        }
  15.418 +
  15.419 +        @Override
  15.420 +        public Collection<? extends Item<T>> allItems() {
  15.421 +            assert false;
  15.422 +            return null;
  15.423 +        }
  15.424 +
  15.425 +        @Override
  15.426 +        public Set<Class<? extends T>> allClasses() {
  15.427 +            assert false;
  15.428 +            return null;
  15.429 +        }
  15.430 +    } // end of WeakResult
  15.431 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/InheritanceTree.java	Sat Oct 31 15:28:13 2009 +0100
    16.3 @@ -0,0 +1,1276 @@
    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 org.openide.util.Lookup;
   16.47 +import org.openide.util.lookup.AbstractLookup.Pair;
   16.48 +import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
   16.49 +import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
   16.50 +
   16.51 +import java.io.*;
   16.52 +
   16.53 +import java.lang.ref.WeakReference;
   16.54 +
   16.55 +import java.util.*;
   16.56 +
   16.57 +
   16.58 +/** A tree to represent classes with inheritance. Description of the
   16.59 + * data structure by Petr Nejedly:
   16.60 + * <P>
   16.61 + * So pretend I'm Lookup implementation. I've got a bunch of Items (e.g.
   16.62 + * setPairs() method),
   16.63 + * didn't do anything on them yet (no startup penalty) so I know nothing
   16.64 + * about them.
   16.65 + * Then I'll be asked for all instances implementing given interface or a
   16.66 + * class. I surely need
   16.67 + * to check all the Items now, as I don't know anything abou them. I surely
   16.68 + * don't want to call
   16.69 + * Item.getClass() as it will dismiss the whole effort. So all I have is
   16.70 + * Item.instanceOf()
   16.71 + * and I'll call it on every Item. I'll cache results, so the next time
   16.72 + * you'll ask me for
   16.73 + * the same interface/class, I'll answer immediatelly. But what if you ask
   16.74 + * me for another
   16.75 + * interface/class? I'll have to scan all Items for it again, unless I can
   16.76 + * be sure some
   16.77 + * of them can't implement it. The only source of this knowledge are the
   16.78 + * previous questions
   16.79 + * and my rulings on them. Here the algorithm have to be split into two
   16.80 + * paths. If you
   16.81 + * previously asked me for interfaces only, I'll have no hint for
   16.82 + * subsequent queries,
   16.83 + * but if you asked me for a class in history, and then for another class
   16.84 + * and these classes
   16.85 + * are not in inheritance relation (I can check hierarchy of lookup
   16.86 + * arguments, because
   16.87 + * they are already resolved/loaded) I can tell that those returned in
   16.88 + * previous query can't
   16.89 + * implement the newly asked class (they are in different hierarchy branch)
   16.90 + * and I need to
   16.91 + * ask less Items.
   16.92 + * <P>
   16.93 + * So if we use mostly classes for asking for services (and it is a trend
   16.94 + * to use
   16.95 + * abstract classes for this purpose in IDE anyway), this could be usable.
   16.96 + * <P>
   16.97 + * The data structure for separating the Items based on previous queries is
   16.98 + * simple
   16.99 + * tree, with every node tagged with one class. The tree's root is,
  16.100 + * naturally,
  16.101 + * java.lang.Object, is marked invited and initially contains all the
  16.102 + * Items.
  16.103 + * For every class query, the missing part of class hierarchy tree is
  16.104 + * created,
  16.105 + * the node of the class looked up is marked as invited and all Items from
  16.106 + * nearest
  16.107 + * invited parent (sperclass) are dragged to this node. The result are then
  16.108 + * all
  16.109 + * Items from this node and all the nodes deeper in hierarchy. Because it
  16.110 + * may
  16.111 + * be too complicated to walk through the children nodes, the results could
  16.112 + * be
  16.113 + * cached in the map.
  16.114 + * For interface lookup, there is a little hint in reality (interfaces
  16.115 + * and superinterfaces), but it would be harder to exploit it, so we could
  16.116 + * fall-back
  16.117 + * to walking through all the Items and cache results.
  16.118 + *
  16.119 + *
  16.120 + * @author  Jaroslav Tulach
  16.121 + */
  16.122 +final class InheritanceTree extends Object
  16.123 +implements Serializable, AbstractLookup.Storage<ArrayList<Class>> {
  16.124 +    private static final long serialVersionUID = 1L;
  16.125 +
  16.126 +    /** the root item (represents Object) */
  16.127 +    private transient Node object;
  16.128 +
  16.129 +    /** Map of queried interfaces.
  16.130 +     * <p>Type: <code>Map&lt;Class, (Collection&lt;AbstractLookup.Pair&gt; | AbstractLookup.Pair)&gt;</code>
  16.131 +     */
  16.132 +    private transient Map<Class,Object> interfaces;
  16.133 +
  16.134 +    /** Map (Class, ReferenceToResult) of all listeners that are waiting in
  16.135 +     * changes in class Class
  16.136 +     */
  16.137 +    private transient Map<Class,ReferenceToResult> reg;
  16.138 +
  16.139 +    /** Constructor
  16.140 +     */
  16.141 +    public InheritanceTree() {
  16.142 +        object = new Node(java.lang.Object.class);
  16.143 +    }
  16.144 +
  16.145 +    private void writeObject(ObjectOutputStream oos) throws IOException {
  16.146 +        oos.writeObject(object);
  16.147 +
  16.148 +        if (interfaces != null) {
  16.149 +            Iterator it = interfaces.entrySet().iterator();
  16.150 +
  16.151 +            while (it.hasNext()) {
  16.152 +                Map.Entry e = (Map.Entry) it.next();
  16.153 +                Class c = (Class) e.getKey();
  16.154 +                oos.writeObject(c.getName());
  16.155 +
  16.156 +                Object o = e.getValue();
  16.157 +
  16.158 +                if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
  16.159 +                    throw new ClassCastException(String.valueOf(o));
  16.160 +                }
  16.161 +
  16.162 +                oos.writeObject(o);
  16.163 +            }
  16.164 +        }
  16.165 +
  16.166 +        oos.writeObject(null);
  16.167 +    }
  16.168 +
  16.169 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
  16.170 +        object = (Node) ois.readObject();
  16.171 +        interfaces = new WeakHashMap<Class,Object>();
  16.172 +
  16.173 +        String clazz;
  16.174 +        ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
  16.175 +
  16.176 +        while ((clazz = (String) ois.readObject()) != null) {
  16.177 +            Object o = ois.readObject();
  16.178 +
  16.179 +            if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
  16.180 +                throw new ClassCastException(String.valueOf(o));
  16.181 +            }
  16.182 +
  16.183 +            Class c = Class.forName(clazz, false, l);
  16.184 +            interfaces.put(c, o);
  16.185 +        }
  16.186 +    }
  16.187 +
  16.188 +    /** Adds an item into the tree.
  16.189 +    * @param item to add
  16.190 +    * @return true if the Item has been added for the first time or false if some other
  16.191 +    *    item equal to this one already existed in the lookup
  16.192 +    */
  16.193 +    public boolean add(AbstractLookup.Pair<?> item, ArrayList<Class> affected) {
  16.194 +        Node node = registerClass(object, item);
  16.195 +
  16.196 +        affected.add(node.getType());
  16.197 +
  16.198 +        if (node.assignItem(this, item)) {
  16.199 +            // this is the first item added to n.items
  16.200 +            // ok, we have to test interfaces too
  16.201 +        } else {
  16.202 +            // equal item is already there => stop processing
  16.203 +            return false;
  16.204 +        }
  16.205 +
  16.206 +        boolean registeredAsInterface = registerInterface(item, affected);
  16.207 +
  16.208 +        return registeredAsInterface;
  16.209 +    }
  16.210 +
  16.211 +    /** Removes an item.
  16.212 +    */
  16.213 +    public void remove(AbstractLookup.Pair item, ArrayList<Class> affected) {
  16.214 +        Node n = removeClass(object, item);
  16.215 +
  16.216 +        if (n != null) {
  16.217 +            affected.add(n.getType());
  16.218 +        }
  16.219 +
  16.220 +        removeInterface(item, affected);
  16.221 +    }
  16.222 +
  16.223 +    /** Removes all items that are not present in the provided collection.
  16.224 +    * @param retain collection of Pairs to keep them in
  16.225 +    * @param notify set of Classes that has possibly changed
  16.226 +    */
  16.227 +    public void retainAll(Map retain, ArrayList<Class> notify) {
  16.228 +        retainAllInterface(retain, notify);
  16.229 +        retainAllClasses(object, retain, notify);
  16.230 +    }
  16.231 +
  16.232 +    /** Queries for instances of given class.
  16.233 +    * @param clazz the class to check
  16.234 +    * @return enumeration of Item
  16.235 +    * @see #unsorted
  16.236 +    */
  16.237 +    @SuppressWarnings("unchecked")
  16.238 +    public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
  16.239 +        if ((clazz != null) && clazz.isInterface()) {
  16.240 +            return (Enumeration)searchInterface(clazz);
  16.241 +        } else {
  16.242 +            return (Enumeration)searchClass(object, clazz);
  16.243 +        }
  16.244 +    }
  16.245 +
  16.246 +    /** A method to check whether the enumeration returned from
  16.247 +     * lookup method is sorted or is not
  16.248 +     * @param en enumeration to check
  16.249 +     * @return true if it is unsorted and needs to be sorted to find
  16.250 +     *   pair with smallest index
  16.251 +     */
  16.252 +    public static boolean unsorted(Enumeration en) {
  16.253 +        return en instanceof NeedsSortEnum;
  16.254 +    }
  16.255 +
  16.256 +    /** Prints debug messages.
  16.257 +     * @param out stream to output to
  16.258 +     * @param instances print also instances of the
  16.259 +     */
  16.260 +    public void print(java.io.PrintStream out, boolean instances) {
  16.261 +        printNode(object, "", out, instances); // NOI18N
  16.262 +    }
  16.263 +
  16.264 +    //
  16.265 +    // methods to work on classes which are not interfaces
  16.266 +    //
  16.267 +
  16.268 +    /** Searches the subtree and register the item where necessary.
  16.269 +    * @return the node that should contain the item
  16.270 +    */
  16.271 +    private static Node registerClass(Node n, AbstractLookup.Pair item) {
  16.272 +        if (!n.accepts(item)) {
  16.273 +            return null;
  16.274 +        }
  16.275 +
  16.276 +        if (n.children != null) {
  16.277 +            Iterator it = n.children.iterator();
  16.278 +
  16.279 +            for (;;) {
  16.280 +                Node ch = extractNode(it);
  16.281 +
  16.282 +                if (ch == null) {
  16.283 +                    break;
  16.284 +                }
  16.285 +
  16.286 +                Node result = registerClass(ch, item);
  16.287 +
  16.288 +                if (result != null) {
  16.289 +                    // it is in subclass, in case of classes, it cannot
  16.290 +                    // be any other class
  16.291 +                    return result;
  16.292 +                }
  16.293 +            }
  16.294 +        }
  16.295 +
  16.296 +        // ok, nobody of our subclasses wants the class, I'll take it
  16.297 +        return n;
  16.298 +    }
  16.299 +
  16.300 +    /** Removes the item from the tree of objects.
  16.301 +    * @return most narrow class that this item was removed from
  16.302 +    */
  16.303 +    private static Node removeClass(Node n, AbstractLookup.Pair item) {
  16.304 +        if (!n.accepts(item)) {
  16.305 +            return null;
  16.306 +        }
  16.307 +
  16.308 +        if ((n.items != null) && n.items.remove(item)) {
  16.309 +            // this node really contains the item
  16.310 +            return n;
  16.311 +        }
  16.312 +
  16.313 +        if (n.children != null) {
  16.314 +            Iterator it = n.children.iterator();
  16.315 +
  16.316 +            for (;;) {
  16.317 +                Node ch = extractNode(it);
  16.318 +
  16.319 +                if (ch == null) {
  16.320 +                    break;
  16.321 +                }
  16.322 +
  16.323 +                Node result = removeClass(ch, item);
  16.324 +
  16.325 +                // If the children node was emptied, remove it if possible.
  16.326 +                if (((ch.items == null) || ch.items.isEmpty()) && ((ch.children == null) || ch.children.isEmpty())) {
  16.327 +                    it.remove();
  16.328 +                }
  16.329 +
  16.330 +                if (result != null) {
  16.331 +                    // it is in subclass, in case of classes, it cannot
  16.332 +                    // be any other class
  16.333 +                    return result;
  16.334 +                }
  16.335 +            }
  16.336 +        }
  16.337 +
  16.338 +        // nobody found
  16.339 +        return null;
  16.340 +    }
  16.341 +
  16.342 +    /** Finds a node that represents a class.
  16.343 +    * @param n node to search from
  16.344 +    * @param clazz the clazz to find
  16.345 +    * @return node that represents clazz in the tree or null if the clazz is not
  16.346 +    *    represented under the node n
  16.347 +    */
  16.348 +    private Node classToNode(final Node n, final Class<?> clazz) {
  16.349 +        if (!n.accepts(clazz)) {
  16.350 +            // nothing from us
  16.351 +            return null;
  16.352 +        }
  16.353 +
  16.354 +        if (n.getType() == clazz) {
  16.355 +            // we have found what we need
  16.356 +            return n;
  16.357 +        }
  16.358 +
  16.359 +        if (n.children != null) {
  16.360 +            // have to proceed to children
  16.361 +            Iterator it = n.children.iterator();
  16.362 +
  16.363 +            for (;;) {
  16.364 +                final Node ch = extractNode(it);
  16.365 +
  16.366 +                if (ch == null) {
  16.367 +                    break;
  16.368 +                }
  16.369 +
  16.370 +                Node found = classToNode(ch, clazz);
  16.371 +
  16.372 +                if ((found != null) && ch.deserialized()) {
  16.373 +                    class VerifyJob implements AbstractLookup.ISE.Job {
  16.374 +                        private AbstractLookup.Pair<?>[] pairs;
  16.375 +                        private boolean[] answers;
  16.376 +
  16.377 +                        public VerifyJob(Collection<Pair> items) {
  16.378 +                            if (items != null) {
  16.379 +                                pairs = items.toArray(new AbstractLookup.Pair[0]);
  16.380 +                            }
  16.381 +                        }
  16.382 +
  16.383 +                        public void before() {
  16.384 +                            // make sure the node is converted into deserialized state
  16.385 +                            ch.deserialized();
  16.386 +
  16.387 +                            if (pairs != null) {
  16.388 +                                answers = new boolean[pairs.length];
  16.389 +
  16.390 +                                for (int i = 0; i < pairs.length; i++) {
  16.391 +                                    answers[i] = pairs[i].instanceOf(clazz);
  16.392 +                                }
  16.393 +                            }
  16.394 +                        }
  16.395 +
  16.396 +                        public void inside() {
  16.397 +                            if (pairs != null) {
  16.398 +                                for (int i = 0; i < pairs.length; i++) {
  16.399 +                                    if (answers[i]) {
  16.400 +                                        ch.assignItem(InheritanceTree.this, pairs[i]);
  16.401 +                                        n.items.remove(pairs[i]);
  16.402 +                                    }
  16.403 +                                }
  16.404 +                            }
  16.405 +
  16.406 +                            if (n.children != null) {
  16.407 +                                // consolidate all nodes that represent the same class
  16.408 +                                HashMap<Class,Node> nodes = new HashMap<Class,Node>(n.children.size() * 3);
  16.409 +
  16.410 +                                Iterator child = n.children.iterator();
  16.411 +
  16.412 +                                while (child.hasNext()) {
  16.413 +                                    Node node = extractNode(child);
  16.414 +                                    if (node == null) {
  16.415 +                                        continue;
  16.416 +                                    }
  16.417 +                                    Node prev = nodes.put(node.getType(), node);
  16.418 +
  16.419 +                                    if (prev != null) {
  16.420 +                                        child.remove();
  16.421 +                                        nodes.put(node.getType(), prev);
  16.422 +
  16.423 +                                        // mark as being deserialized
  16.424 +                                        prev.markDeserialized();
  16.425 +
  16.426 +                                        if (prev.children == null) {
  16.427 +                                            prev.children = node.children;
  16.428 +                                        } else {
  16.429 +                                            if (node.children != null) {
  16.430 +                                                prev.children.addAll(node.children);
  16.431 +                                            }
  16.432 +                                        }
  16.433 +
  16.434 +                                        if (node.items != null) {
  16.435 +                                            Iterator items = node.items.iterator();
  16.436 +
  16.437 +                                            while (items.hasNext()) {
  16.438 +                                                AbstractLookup.Pair item = (AbstractLookup.Pair) items.next();
  16.439 +                                                prev.assignItem(InheritanceTree.this, item);
  16.440 +                                            }
  16.441 +                                        }
  16.442 +                                    }
  16.443 +                                }
  16.444 +                            }
  16.445 +                        }
  16.446 +                    }
  16.447 +
  16.448 +                    VerifyJob verify = new VerifyJob(n.items);
  16.449 +
  16.450 +                    try {
  16.451 +                        verify.before();
  16.452 +                    } catch (AbstractLookup.ISE ex) {
  16.453 +                        // mark deserialized again
  16.454 +                        ch.markDeserialized();
  16.455 +                        ex.registerJob(verify);
  16.456 +                        throw ex;
  16.457 +                    }
  16.458 +
  16.459 +                    verify.inside();
  16.460 +
  16.461 +                    found = classToNode(ch, clazz);
  16.462 +                }
  16.463 +
  16.464 +                if (found != null) {
  16.465 +                    // class found in one of subnodes
  16.466 +                    return found;
  16.467 +                }
  16.468 +            }
  16.469 +        }
  16.470 +
  16.471 +        class TwoJobs implements AbstractLookup.ISE.Job {
  16.472 +            private AbstractLookup.Pair[] pairs;
  16.473 +            private boolean[] answers;
  16.474 +            private Node newNode;
  16.475 +
  16.476 +            public void before() {
  16.477 +                // have to create new subnode and possibly reparent one of my own
  16.478 +                // but all changes can be done only if we will not be interrupted from
  16.479 +                // outside - e.g. instanceOf methods will not throw exception
  16.480 +                // first of all let's compute the answers to method instanceOf
  16.481 +                AbstractLookup.Pair[] arr = null;
  16.482 +                boolean[] boolArr = null;
  16.483 +
  16.484 +                if (n.items != null) {
  16.485 +                    arr = new AbstractLookup.Pair[n.items.size()];
  16.486 +                    boolArr = new boolean[n.items.size()];
  16.487 +
  16.488 +                    int i = 0;
  16.489 +                    Iterator<Pair> it = n.items.iterator();
  16.490 +
  16.491 +                    while (it.hasNext()) {
  16.492 +                        AbstractLookup.Pair<?> item = it.next();
  16.493 +                        arr[i] = item;
  16.494 +                        boolArr[i] = item.instanceOf(clazz);
  16.495 +                        i++;
  16.496 +                    }
  16.497 +                }
  16.498 +
  16.499 +                pairs = arr;
  16.500 +                answers = boolArr;
  16.501 +            }
  16.502 +
  16.503 +            public void inside() {
  16.504 +                // test if the query has not chagned since
  16.505 +                if (pairs != null) {
  16.506 +                    if (!Arrays.equals(n.items.toArray(), pairs)) {
  16.507 +                        // ok, let try once more
  16.508 +                        return;
  16.509 +                    }
  16.510 +                }
  16.511 +
  16.512 +                internal();
  16.513 +            }
  16.514 +
  16.515 +            public void internal() {
  16.516 +                ArrayList<Node> reparent = null;
  16.517 +
  16.518 +                if (n.children == null) {
  16.519 +                    n.children = new ArrayList<Node>();
  16.520 +                } else {
  16.521 +                    // scan thru all my nodes if some of them are not a subclass
  16.522 +                    // of clazz => then they would need to become child of newNode
  16.523 +                    Iterator it = n.children.iterator();
  16.524 +
  16.525 +                    for (;;) {
  16.526 +                        Node r = extractNode(it);
  16.527 +
  16.528 +                        if (r == null) {
  16.529 +                            break;
  16.530 +                        }
  16.531 +
  16.532 +                        if (clazz.isAssignableFrom(r.getType())) {
  16.533 +                            if (reparent == null) {
  16.534 +                                reparent = new ArrayList<Node>();
  16.535 +                            }
  16.536 +
  16.537 +                            reparent.add(r);
  16.538 +                            it.remove();
  16.539 +                        }
  16.540 +                    }
  16.541 +                }
  16.542 +
  16.543 +                newNode = new Node(clazz);
  16.544 +                n.children.add(newNode);
  16.545 +
  16.546 +                if (reparent != null) {
  16.547 +                    // reassing reparent node as a child of newNode
  16.548 +                    newNode.children = reparent;
  16.549 +                }
  16.550 +
  16.551 +                // now take all my items that are instances of that class and
  16.552 +                // reasign them
  16.553 +                if (n.items != null) {
  16.554 +                    Iterator it = n.items.iterator();
  16.555 +                    int i = 0;
  16.556 +
  16.557 +                    while (it.hasNext()) {
  16.558 +                        AbstractLookup.Pair item = (AbstractLookup.Pair) it.next();
  16.559 +
  16.560 +                        if (answers[i]) { // answers[i] is precomputed value of item.instanceOf (clazz))
  16.561 +                            it.remove();
  16.562 +                            newNode.assignItem(InheritanceTree.this, pairs[i]);
  16.563 +                        }
  16.564 +
  16.565 +                        i++;
  16.566 +                    }
  16.567 +                }
  16.568 +            }
  16.569 +        }
  16.570 +
  16.571 +        TwoJobs j = new TwoJobs();
  16.572 +
  16.573 +        try {
  16.574 +            j.before();
  16.575 +        } catch (AbstractLookup.ISE ex) {
  16.576 +            // ok, it is not possible to call instanceOf now, let's 
  16.577 +            // schedule it for later
  16.578 +            // so register recovery job 
  16.579 +            ex.registerJob(j);
  16.580 +            throw ex;
  16.581 +        }
  16.582 +
  16.583 +        j.internal();
  16.584 +
  16.585 +        // newNode represents my clazz
  16.586 +        return j.newNode;
  16.587 +    }
  16.588 +
  16.589 +    /** Search for a requested class.
  16.590 +    * @return enumeration of Pair
  16.591 +    */
  16.592 +    private Enumeration<Pair> searchClass(Node n, Class<?> clazz) {
  16.593 +        if (clazz != null) {
  16.594 +            n = classToNode(n, clazz);
  16.595 +        }
  16.596 +
  16.597 +        if (n == null) {
  16.598 +            // not for us
  16.599 +            return emptyEn();
  16.600 +        } else {
  16.601 +            return nodeToEnum(n);
  16.602 +        }
  16.603 +    }
  16.604 +
  16.605 +    /** Retains all classes. Removes nodes which items and children are emptied, works
  16.606 +     * recursivelly from specified root node.
  16.607 +     * @param node root node from which to start to process the tree
  16.608 +     * @param retain a map from (Item, AbstractLookup.Info) that describes which items to retain
  16.609 +     *    and witch integer to assign them
  16.610 +     * @param notify collection of classes will be changed
  16.611 +     * @return <code>true<code> if some items were changed and node items and children are emptied,
  16.612 +     * those nodes, excluding root, will be removed from tree */
  16.613 +    private boolean retainAllClasses(Node node, Map retain, Collection<Class> notify) {
  16.614 +        boolean retained = false;
  16.615 +
  16.616 +        if ((node.items != null) && (retain != null)) {
  16.617 +            Iterator<Pair> it = node.items.iterator();
  16.618 +
  16.619 +            while (it.hasNext()) {
  16.620 +                AbstractLookup.Pair<?> item = it.next();
  16.621 +                AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(item);
  16.622 +
  16.623 +                if (n == null) {
  16.624 +                    // remove this item, it should not be there
  16.625 +                    it.remove();
  16.626 +                    retained = true;
  16.627 +                } else {
  16.628 +                    // change the index
  16.629 +                    if (item.getIndex() != n.index) {
  16.630 +                        item.setIndex(null, n.index);
  16.631 +
  16.632 +                        //                        notify.addAll ((ArrayList)n.transaction);
  16.633 +                    }
  16.634 +                }
  16.635 +            }
  16.636 +
  16.637 +            if (retained && (notify != null)) {
  16.638 +                // type of this node has been changed
  16.639 +                notify.add(node.getType());
  16.640 +            }
  16.641 +        }
  16.642 +
  16.643 +        if (node.children != null) {
  16.644 +            for (Iterator it = node.children.iterator();;) {
  16.645 +                Node ch = extractNode(it);
  16.646 +
  16.647 +                if (ch == null) {
  16.648 +                    break;
  16.649 +                }
  16.650 +
  16.651 +                boolean result = retainAllClasses(ch, retain, notify);
  16.652 +
  16.653 +                if (result) {
  16.654 +                    // The children node was emptied and has no children -> remove it.
  16.655 +                    it.remove();
  16.656 +                }
  16.657 +            }
  16.658 +        }
  16.659 +
  16.660 +        return retained && node.items.isEmpty() && ((node.children == null) || node.children.isEmpty());
  16.661 +    }
  16.662 +
  16.663 +    /** A method that creates enumeration of all items under given node.
  16.664 +     *
  16.665 +     * @param n node to create enumeration for
  16.666 +     * @return enumeration of Pairs
  16.667 +     */
  16.668 +    private static Enumeration<Pair> nodeToEnum(Node n) {
  16.669 +        if (n.children == null) {
  16.670 +            // create a simple enumeration because we do not have children
  16.671 +            Enumeration<Pair> e;
  16.672 +            if (n.items == null) {
  16.673 +                e = emptyEn();
  16.674 +            } else {
  16.675 +                e = Collections.enumeration(n.items);
  16.676 +            }
  16.677 +            return e;
  16.678 +        }
  16.679 +
  16.680 +        // create enumeration of Items
  16.681 +        return new NeedsSortEnum(n);
  16.682 +    }
  16.683 +
  16.684 +    //
  16.685 +    // Methods to work on interfaces
  16.686 +    // 
  16.687 +
  16.688 +    /** Registers an item with interfaces.
  16.689 +    * @param item item to register
  16.690 +    * @param affected list of classes that were affected
  16.691 +    * @return false if similar item has already been registered
  16.692 +    */
  16.693 +    @SuppressWarnings("unchecked")
  16.694 +    private boolean registerInterface(AbstractLookup.Pair<?> item, Collection<Class> affected) {
  16.695 +        if (interfaces == null) {
  16.696 +            return true;
  16.697 +        }
  16.698 +
  16.699 +        Iterator<Map.Entry<Class,Object>> it = interfaces.entrySet().iterator();
  16.700 +
  16.701 +        while (it.hasNext()) {
  16.702 +            Map.Entry<Class,Object> entry = it.next();
  16.703 +            Class<?> iface = entry.getKey();
  16.704 +
  16.705 +            if (item.instanceOf(iface)) {
  16.706 +                Object value = entry.getValue();
  16.707 +
  16.708 +                if (value instanceof Collection) {
  16.709 +                    Collection<Object> set = (Collection<Object>) value;
  16.710 +
  16.711 +                    if (!set.add(item)) {
  16.712 +                        // item is already there, probably (if everything is correct) is registered in 
  16.713 +                        // all other ifaces too, so stop additional testing
  16.714 +                        return false;
  16.715 +                    }
  16.716 +                } else {
  16.717 +                    // there is just one pair right now
  16.718 +                    if (value.equals(item)) {
  16.719 +                        // item is there => stop processing (same as above)
  16.720 +                        return false;
  16.721 +                    }
  16.722 +
  16.723 +                    // otherwise replace the single item with ArrayList
  16.724 +                    ArrayList<Object> ll = new ArrayList<Object>(3);
  16.725 +                    ll.add(value);
  16.726 +                    ll.add(item);
  16.727 +                    entry.setValue(ll);
  16.728 +                }
  16.729 +
  16.730 +                affected.add(iface);
  16.731 +            }
  16.732 +        }
  16.733 +
  16.734 +        return true;
  16.735 +    }
  16.736 +
  16.737 +    /** Removes interface.
  16.738 +    * @param item item to register
  16.739 +    * @param affected list of classes that were affected
  16.740 +    */
  16.741 +    @SuppressWarnings("unchecked")
  16.742 +    private void removeInterface(AbstractLookup.Pair item, Collection affected) {
  16.743 +        if (interfaces == null) {
  16.744 +            return;
  16.745 +        }
  16.746 +
  16.747 +        Iterator it = interfaces.entrySet().iterator();
  16.748 +
  16.749 +        while (it.hasNext()) {
  16.750 +            Map.Entry entry = (Map.Entry) it.next();
  16.751 +            Object value = entry.getValue();
  16.752 +
  16.753 +            if (value instanceof Collection) {
  16.754 +                Collection set = (Collection) value;
  16.755 +
  16.756 +                if (set.remove(item)) {
  16.757 +                    if (set.size() == 1) {
  16.758 +                        // if there is just one item remaining change to single item mode
  16.759 +                        entry.setValue(set.iterator().next());
  16.760 +                    }
  16.761 +
  16.762 +                    // adds the Class the item was register to into affected
  16.763 +                    affected.add(entry.getKey());
  16.764 +                }
  16.765 +            } else {
  16.766 +                // single item value
  16.767 +                if (value.equals(item)) {
  16.768 +                    // Emptied -> remove.
  16.769 +                    it.remove();
  16.770 +
  16.771 +                    affected.add(entry.getKey());
  16.772 +                }
  16.773 +            }
  16.774 +        }
  16.775 +    }
  16.776 +
  16.777 +    /** Retains some items.
  16.778 +    * @param retainItems items to retain and their mapping to index numbers
  16.779 +    *    (AbstractLookup.Pair -> AbstractLookup.Info)
  16.780 +    * @param affected list of classes that were affected
  16.781 +    */
  16.782 +    @SuppressWarnings("unchecked")
  16.783 +    private void retainAllInterface(Map retainItems, Collection affected) {
  16.784 +        if (interfaces == null) {
  16.785 +            return;
  16.786 +        }
  16.787 +
  16.788 +        Iterator it = interfaces.entrySet().iterator();
  16.789 +
  16.790 +        while (it.hasNext()) {
  16.791 +            Map.Entry entry = (Map.Entry) it.next();
  16.792 +            Object value = entry.getValue();
  16.793 +
  16.794 +            HashMap<?,?> retain = new HashMap(retainItems);
  16.795 +
  16.796 +            Iterator elems;
  16.797 +            boolean multi = value instanceof Collection;
  16.798 +
  16.799 +            if (multi) {
  16.800 +                // collection mode
  16.801 +                elems = ((Collection) value).iterator();
  16.802 +            } else {
  16.803 +                // single item mode
  16.804 +                elems = Collections.singleton(value).iterator();
  16.805 +            }
  16.806 +
  16.807 +            boolean changed = false;
  16.808 +            boolean reordered = false;
  16.809 +
  16.810 +            while (elems.hasNext()) {
  16.811 +                AbstractLookup.Pair p = (AbstractLookup.Pair) elems.next();
  16.812 +
  16.813 +                AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(p);
  16.814 +
  16.815 +                if (n == null) {
  16.816 +                    if (multi) {
  16.817 +                        // remove it
  16.818 +                        elems.remove();
  16.819 +                    }
  16.820 +
  16.821 +                    changed = true;
  16.822 +                } else {
  16.823 +                    if (p.getIndex() != n.index) {
  16.824 +                        // improve the index
  16.825 +                        p.setIndex(null, n.index);
  16.826 +
  16.827 +                        //                    affected.addAll ((ArrayList)n.transaction);
  16.828 +                        reordered = true;
  16.829 +                    }
  16.830 +                }
  16.831 +            }
  16.832 +
  16.833 +            if (reordered && value instanceof List) {
  16.834 +                // if reordered, than update the order in the collection
  16.835 +                List l = (List) value;
  16.836 +                Collections.sort(l, ALPairComparator.DEFAULT);
  16.837 +            }
  16.838 +
  16.839 +            if (changed) {
  16.840 +                if (multi) {
  16.841 +                    Collection c = (Collection) value;
  16.842 +
  16.843 +                    if (c.size() == 1) {
  16.844 +                        // back to single item mode
  16.845 +                        entry.setValue(c.iterator().next());
  16.846 +                    }
  16.847 +                } else {
  16.848 +                    // remove in single mode => remove completely
  16.849 +                    it.remove();
  16.850 +                }
  16.851 +
  16.852 +                // adds the Class the item was register to into affected
  16.853 +                affected.add(entry.getKey());
  16.854 +            }
  16.855 +        }
  16.856 +    }
  16.857 +
  16.858 +    /** Searches for a clazz between interfaces.
  16.859 +    * @param clazz class to search for
  16.860 +    * @return enumeration of Items
  16.861 +    */
  16.862 +    @SuppressWarnings("unchecked")
  16.863 +    private Enumeration<Pair> searchInterface(final Class<?> clazz) {
  16.864 +        if (interfaces == null) {
  16.865 +            // first call for interface, only initialize
  16.866 +            interfaces = new WeakHashMap();
  16.867 +        }
  16.868 +
  16.869 +        Object obj = interfaces.get(clazz);
  16.870 +
  16.871 +        if (obj == null) {
  16.872 +            // set of items
  16.873 +            AbstractLookup.Pair one = null;
  16.874 +            ArrayList items = null;
  16.875 +
  16.876 +            Enumeration en = lookup(Object.class);
  16.877 +
  16.878 +            while (en.hasMoreElements()) {
  16.879 +                AbstractLookup.Pair it = (AbstractLookup.Pair) en.nextElement();
  16.880 +
  16.881 +                if (it.instanceOf(clazz)) {
  16.882 +                    // ok, this item implements given clazz
  16.883 +                    if (one == null) {
  16.884 +                        one = it;
  16.885 +                    } else {
  16.886 +                        if (items == null) {
  16.887 +                            items = new ArrayList(3);
  16.888 +                            items.add(one);
  16.889 +                        }
  16.890 +
  16.891 +                        items.add(it);
  16.892 +                    }
  16.893 +                }
  16.894 +            }
  16.895 +
  16.896 +            if ((items == null) && (one != null)) {
  16.897 +                // single item mode
  16.898 +                interfaces.put(clazz, one);
  16.899 +
  16.900 +                return singletonEn(one);
  16.901 +            } else {
  16.902 +                if (items == null) {
  16.903 +                    items = new ArrayList(2);
  16.904 +                }
  16.905 +
  16.906 +                interfaces.put(clazz, items);
  16.907 +
  16.908 +                return Collections.enumeration(items);
  16.909 +            }
  16.910 +        } else {
  16.911 +            if (obj instanceof Collection) {
  16.912 +                return Collections.enumeration((Collection) obj);
  16.913 +            } else {
  16.914 +                // single item mode
  16.915 +                return singletonEn((Pair)obj);
  16.916 +            }
  16.917 +        }
  16.918 +    }
  16.919 +
  16.920 +    /** Extracts a node from an iterator, returning null if no next element found
  16.921 +     */
  16.922 +    private static Node extractNode(Iterator it) {
  16.923 +        while (it.hasNext()) {
  16.924 +            Node n = (Node) it.next();
  16.925 +
  16.926 +            if (n.get() == null) {
  16.927 +                it.remove();
  16.928 +            } else {
  16.929 +                return n;
  16.930 +            }
  16.931 +        }
  16.932 +
  16.933 +        return null;
  16.934 +    }
  16.935 +
  16.936 +    /** Prints debug info about the node.
  16.937 +     * @param n node to print
  16.938 +     * @param sp spaces to add
  16.939 +     * @param out where
  16.940 +     * @param instances print also instances
  16.941 +     */
  16.942 +    private static void printNode(Node n, String sp, java.io.PrintStream out, boolean instances) {
  16.943 +        int i;
  16.944 +        Iterator it;
  16.945 +
  16.946 +        Class type = n.getType();
  16.947 +
  16.948 +        out.print(sp);
  16.949 +        out.println("Node for: " + type + "\t" + ((type == null) ? null : type.getClassLoader())); // NOI18N
  16.950 +
  16.951 +        if (n.items != null) {
  16.952 +            i = 0;
  16.953 +            it = new ArrayList<Pair>(n.items).iterator();
  16.954 +
  16.955 +            while (it.hasNext()) {
  16.956 +                AbstractLookup.Pair p = (AbstractLookup.Pair) it.next();
  16.957 +                out.print(sp);
  16.958 +                out.print("  item (" + i++ + "): ");
  16.959 +                out.print(p); // NOI18N
  16.960 +                out.print(" id: " + Integer.toHexString(System.identityHashCode(p))); // NOI18N
  16.961 +                out.print(" index: "); // NOI18N
  16.962 +                out.print(p.getIndex());
  16.963 +
  16.964 +                if (instances) {
  16.965 +                    out.print(" I: " + p.getInstance());
  16.966 +                }
  16.967 +
  16.968 +                out.println();
  16.969 +            }
  16.970 +        }
  16.971 +
  16.972 +        if (n.children != null) {
  16.973 +            i = 0;
  16.974 +            it = n.children.iterator();
  16.975 +
  16.976 +            while (it.hasNext()) {
  16.977 +                Node ch = (Node) it.next();
  16.978 +                printNode(ch, sp + "  ", out, instances); // NOI18N
  16.979 +            }
  16.980 +        }
  16.981 +    }
  16.982 +
  16.983 +    public ReferenceToResult registerReferenceToResult(ReferenceToResult<?> newRef) {
  16.984 +        if (reg == null) {
  16.985 +            reg = new HashMap<Class,ReferenceToResult>();
  16.986 +        }
  16.987 +
  16.988 +        Class<? extends Object> clazz = newRef.template.getType();
  16.989 +
  16.990 +        // initialize the data structures if not yet
  16.991 +        lookup(clazz);
  16.992 +
  16.993 +        // newRef will be the new head of the list
  16.994 +        return reg.put(clazz, newRef);
  16.995 +    }
  16.996 +
  16.997 +    public ReferenceToResult cleanUpResult(Lookup.Template templ) {
  16.998 +        collectListeners(null, templ.getType());
  16.999 +
 16.1000 +        return (reg == null) ? null : reg.get(templ.getType());
 16.1001 +    }
 16.1002 +
 16.1003 +    public ArrayList<Class> beginTransaction(int ensure) {
 16.1004 +        return new ArrayList<Class>();
 16.1005 +    }
 16.1006 +
 16.1007 +    public void endTransaction(ArrayList<Class> list, Set<AbstractLookup.R> allAffectedResults) {
 16.1008 +        if (list.size() == 1) {
 16.1009 +            // probably the most common case
 16.1010 +            collectListeners(allAffectedResults, list.get(0));
 16.1011 +        } else {
 16.1012 +            Iterator it = list.iterator();
 16.1013 +
 16.1014 +            while (it.hasNext()) {
 16.1015 +                collectListeners(allAffectedResults, (Class) it.next());
 16.1016 +            }
 16.1017 +        }
 16.1018 +    }
 16.1019 +
 16.1020 +    /** Notifies all listeners that are interested in changes in this class.
 16.1021 +     * Should be called from synchronized places.
 16.1022 +     * @param allAffectedResults adds Results into this set
 16.1023 +     * @param c the class that has changed
 16.1024 +     */
 16.1025 +    private void collectListeners(Set<AbstractLookup.R> allAffectedResults, Class c) {
 16.1026 +        if (reg == null) {
 16.1027 +            return;
 16.1028 +        }
 16.1029 +
 16.1030 +        while (c != null) {
 16.1031 +            ReferenceToResult first = reg.get(c);
 16.1032 +            ReferenceIterator it = new ReferenceIterator(first);
 16.1033 +
 16.1034 +            while (it.next()) {
 16.1035 +                AbstractLookup.R result = it.current().getResult();
 16.1036 +
 16.1037 +                if (allAffectedResults != null) {
 16.1038 +                    // add result
 16.1039 +                    allAffectedResults.add(result);
 16.1040 +                }
 16.1041 +            }
 16.1042 +
 16.1043 +            if (first != it.first()) {
 16.1044 +                if (it.first() == null) {
 16.1045 +                    // we do not need have more results on this object
 16.1046 +                    reg.remove(c);
 16.1047 +                } else {
 16.1048 +                    // move the head of the list
 16.1049 +                    reg.put(c, it.first());
 16.1050 +                }
 16.1051 +            }
 16.1052 +
 16.1053 +            c = c.getSuperclass();
 16.1054 +        }
 16.1055 +
 16.1056 +        if (reg.isEmpty()) {
 16.1057 +            // clean up the list of all results if we do not need them anymore
 16.1058 +            reg = null;
 16.1059 +        }
 16.1060 +    }
 16.1061 +
 16.1062 +    /** Node in the tree.
 16.1063 +    */
 16.1064 +    static final class Node extends WeakReference<Class> implements Serializable {
 16.1065 +        static final long serialVersionUID = 3L;
 16.1066 +
 16.1067 +        /** children nodes */
 16.1068 +        public ArrayList<Node> children;
 16.1069 +
 16.1070 +        /** list of items assigned to this node (suspect to be subclasses) */
 16.1071 +        public Collection<Pair> items;
 16.1072 +
 16.1073 +        /** Constructor.
 16.1074 +        */
 16.1075 +        public Node(Class clazz) {
 16.1076 +            super(clazz);
 16.1077 +        }
 16.1078 +
 16.1079 +        /** Returns true if the object was deserialized also clears the serialized flag.
 16.1080 +         * @return true if so.
 16.1081 +         */
 16.1082 +        public boolean deserialized() {
 16.1083 +            if ((items == null) || items instanceof LinkedHashSet) {
 16.1084 +                return false;
 16.1085 +            }
 16.1086 +
 16.1087 +            if (items.isEmpty()) {
 16.1088 +                items = null;
 16.1089 +            } else {
 16.1090 +                items = new LinkedHashSet<Pair>(items);
 16.1091 +            }
 16.1092 +
 16.1093 +            return true;
 16.1094 +        }
 16.1095 +
 16.1096 +        /** Marks this item as being deserialized.
 16.1097 +         */
 16.1098 +        public void markDeserialized() {
 16.1099 +            if (items == null || items == Collections.EMPTY_LIST) {
 16.1100 +                items = Collections.emptyList();
 16.1101 +            } else {
 16.1102 +                items = Collections.synchronizedCollection(items);
 16.1103 +            }
 16.1104 +        }
 16.1105 +
 16.1106 +        /** Getter for the type associated with this node.
 16.1107 +         */
 16.1108 +        public Class<?> getType() {
 16.1109 +            Class<?> c = get();
 16.1110 +
 16.1111 +            // if  garbage collected, then return a garbage
 16.1112 +            return (c == null) ? Void.TYPE : c;
 16.1113 +        }
 16.1114 +
 16.1115 +        /** Checks whether a node can represent an class.
 16.1116 +        */
 16.1117 +        public boolean accepts(Class<?> clazz) {
 16.1118 +            if (getType() == Object.class) {
 16.1119 +                return true;
 16.1120 +            }
 16.1121 +
 16.1122 +            return getType().isAssignableFrom(clazz);
 16.1123 +        }
 16.1124 +
 16.1125 +        /** Checks whether item is instance of this node.
 16.1126 +        */
 16.1127 +        public boolean accepts(AbstractLookup.Pair<?> item) {
 16.1128 +            if (getType() == Object.class) {
 16.1129 +                // Object.class
 16.1130 +                return true;
 16.1131 +            }
 16.1132 +
 16.1133 +            return item.instanceOf(getType());
 16.1134 +        }
 16.1135 +
 16.1136 +        /** Assings an item to this node.
 16.1137 +        * @param item the item
 16.1138 +        * @return true if item has been added as new
 16.1139 +        */
 16.1140 +        public boolean assignItem(InheritanceTree tree, AbstractLookup.Pair<?> item) {
 16.1141 +            if ((items == null) || (items == Collections.EMPTY_LIST)) {
 16.1142 +                items = new LinkedHashSet<Pair>();
 16.1143 +                items.add(item);
 16.1144 +
 16.1145 +                return true;
 16.1146 +            }
 16.1147 +
 16.1148 +            if (items.contains(item)) {
 16.1149 +                Iterator<Pair> it = items.iterator();
 16.1150 +                Pair old;
 16.1151 +                for (;;) {
 16.1152 +                    old = it.next();
 16.1153 +                    if (item.equals(old)) {
 16.1154 +                        break;
 16.1155 +                    }
 16.1156 +                }
 16.1157 +
 16.1158 +                if (old != item) {
 16.1159 +                    // replace the items there
 16.1160 +                    item.setIndex(tree, old.getIndex());
 16.1161 +                }
 16.1162 +
 16.1163 +                it.remove();
 16.1164 +                items.add(item);
 16.1165 +
 16.1166 +                return false;
 16.1167 +            }
 16.1168 +
 16.1169 +            items.add(item);
 16.1170 +
 16.1171 +            return true;
 16.1172 +        }
 16.1173 +
 16.1174 +        private Object writeReplace() {
 16.1175 +            return new R(this);
 16.1176 +        }
 16.1177 +
 16.1178 +        @Override
 16.1179 +        public String toString() {
 16.1180 +            return "Node for " + get();
 16.1181 +        }
 16.1182 +    }
 16.1183 +     // End of class Node.
 16.1184 +
 16.1185 +    private static final class R implements Serializable {
 16.1186 +        static final long serialVersionUID = 1L;
 16.1187 +        private static ClassLoader l;
 16.1188 +        private String clazzName;
 16.1189 +        private transient Class<?> clazz;
 16.1190 +        private ArrayList<Node> children;
 16.1191 +        private Collection<Pair> items;
 16.1192 +
 16.1193 +        public R(Node n) {
 16.1194 +            this.clazzName = n.getType().getName();
 16.1195 +            this.children = n.children;
 16.1196 +
 16.1197 +            if (n.items instanceof LinkedHashSet || (n.items == null)) {
 16.1198 +                this.items = n.items;
 16.1199 +            } else {
 16.1200 +                this.items = new LinkedHashSet<Pair>(n.items);
 16.1201 +            }
 16.1202 +        }
 16.1203 +
 16.1204 +        private void readObject(ObjectInputStream ois)
 16.1205 +        throws IOException, ClassNotFoundException {
 16.1206 +            ois.defaultReadObject();
 16.1207 +
 16.1208 +            if (l == null) {
 16.1209 +                l = Lookup.getDefault().lookup(ClassLoader.class);
 16.1210 +            }
 16.1211 +
 16.1212 +            clazz = Class.forName(clazzName, false, l);
 16.1213 +        }
 16.1214 +
 16.1215 +        private Object readResolve() throws ObjectStreamException {
 16.1216 +            Node n = new Node(clazz);
 16.1217 +            n.children = children;
 16.1218 +            n.items = items;
 16.1219 +            n.markDeserialized();
 16.1220 +
 16.1221 +            return n;
 16.1222 +        }
 16.1223 +    }
 16.1224 +     // end of R
 16.1225 +
 16.1226 +    static Enumeration<Object> arrayEn(Object[] object) {
 16.1227 +        return Collections.enumeration(Arrays.asList(object));
 16.1228 +    }
 16.1229 +    static <T> Enumeration<T> singletonEn(T object) {
 16.1230 +        return Collections.enumeration(Collections.singleton(object));
 16.1231 +    }
 16.1232 +    static <T> Enumeration<T> emptyEn() {
 16.1233 +        return Collections.enumeration(Collections.<T>emptyList());
 16.1234 +    }
 16.1235 +
 16.1236 +    /** Just a marker class to be able to do instanceof and find out
 16.1237 +     * that this enumeration is not sorted
 16.1238 +     */
 16.1239 +    private static final class NeedsSortEnum extends LinkedList<Node>
 16.1240 +    implements Enumeration<Pair> {
 16.1241 +        private Enumeration<Pair> en;
 16.1242 +
 16.1243 +        public NeedsSortEnum(Node n) {
 16.1244 +            add(n);
 16.1245 +        }
 16.1246 +
 16.1247 +        private boolean ensureNext() {
 16.1248 +            for (;;) {
 16.1249 +                if (en != null && en.hasMoreElements()) {
 16.1250 +                    return true;
 16.1251 +                }
 16.1252 +                if (isEmpty()) {
 16.1253 +                    return false;
 16.1254 +                }
 16.1255 +
 16.1256 +                Node n2 = poll();
 16.1257 +                if (n2.children != null) {
 16.1258 +                    addAll(n2.children);
 16.1259 +                }
 16.1260 +
 16.1261 +                if (n2.items != null && !n2.items.isEmpty()) {
 16.1262 +                    en = Collections.enumeration(n2.items);
 16.1263 +                }
 16.1264 +            }
 16.1265 +        }
 16.1266 +
 16.1267 +        public boolean hasMoreElements() {
 16.1268 +            return ensureNext();
 16.1269 +        }
 16.1270 +
 16.1271 +        public Pair nextElement() {
 16.1272 +            if (!ensureNext()) {
 16.1273 +                throw new NoSuchElementException();
 16.1274 +            }
 16.1275 +            return en.nextElement();
 16.1276 +        }
 16.1277 +    }
 16.1278 +     // end of NeedsSortEnum
 16.1279 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/InstanceContent.java	Sat Oct 31 15:28:13 2009 +0100
    17.3 @@ -0,0 +1,378 @@
    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.AbstractLookup.Pair;
   17.47 +
   17.48 +import java.lang.ref.WeakReference;
   17.49 +
   17.50 +import java.util.*;
   17.51 +import java.util.concurrent.Executor;
   17.52 +import org.openide.util.Lookup.Item;
   17.53 +
   17.54 +
   17.55 +/** A special content implementation that can be passed to AbstractLookup
   17.56 + * and provides methods for registration of instances and lazy instances.
   17.57 + * <PRE>
   17.58 + *      InstanceContent ic = new InstanceContent ();
   17.59 + *      AbstractLookup al = new AbstractLookup (ic);
   17.60 + *
   17.61 + *      ic.add (new Object ());
   17.62 + *      ic.add (new Dimension (...));
   17.63 + *
   17.64 + *      Dimension theDim = (Dimension)al.lookup (Dimension.class);
   17.65 + * </PRE>
   17.66 + *
   17.67 + * @author  Jaroslav Tulach
   17.68 + *
   17.69 + * @since 1.25
   17.70 + */
   17.71 +public final class InstanceContent extends AbstractLookup.Content {
   17.72 +    /**
   17.73 +     * Create a new, empty content.
   17.74 +     */
   17.75 +    public InstanceContent() {
   17.76 +    }
   17.77 +
   17.78 +    /** Creates a content associated with an executor to handle dispatch
   17.79 +     * of changes.
   17.80 +     * @param notifyIn the executor to notify changes in
   17.81 +     * @since  7.16
   17.82 +     */
   17.83 +    public InstanceContent(Executor notifyIn) {
   17.84 +        super(notifyIn);
   17.85 +    }
   17.86 +    /** The method to add instance to the lookup with.
   17.87 +     * @param inst instance
   17.88 +     */
   17.89 +    public final void add(Object inst) {
   17.90 +        addPair(new SimpleItem<Object>(inst));
   17.91 +    }
   17.92 +
   17.93 +    /** Adds a convertible instance into the lookup. The <code>inst</code>
   17.94 +     * argument is just a key, not the actual value to appear in the lookup.
   17.95 +     * The value will be created on demand, later when it is really needed
   17.96 +     * by calling <code>convertor</code> methods.
   17.97 +     * <p>
   17.98 +     * This method is useful to delay creation of heavy weight objects.
   17.99 +     * Instead just register lightweight key and a convertor.
  17.100 +     * <p>
  17.101 +     * To remove registered object from lookup use {@link #remove(java.lang.Object, org.openide.util.lookup.InstanceContent.Convertor)}
  17.102 +     * with the same arguments.
  17.103 +     *
  17.104 +     * @param inst instance
  17.105 +     * @param conv convertor which postponing an instantiation,
  17.106 +     * if <code>conv==null</code> then the instance is registered directly.
  17.107 +     */
  17.108 +    public final <T,R> void add(T inst, Convertor<T,R> conv) {
  17.109 +        addPair(new ConvertingItem<T,R>(inst, conv));
  17.110 +    }
  17.111 +
  17.112 +    /** Remove instance.
  17.113 +     * @param inst instance
  17.114 +     */
  17.115 +    public final void remove(Object inst) {
  17.116 +        removePair(new SimpleItem<Object>(inst));
  17.117 +    }
  17.118 +
  17.119 +    /** Remove instance added with a convertor.
  17.120 +     * @param inst instance
  17.121 +     * @param conv convertor, if <code>conv==null</code> it is same like
  17.122 +     * remove(Object)
  17.123 +     */
  17.124 +    public final <T,R> void remove(T inst, Convertor<T,R> conv) {
  17.125 +        removePair(new ConvertingItem<T,R>(inst, conv));
  17.126 +    }
  17.127 +
  17.128 +    /** Changes all pairs in the lookup to new values. Converts collection of
  17.129 +     * instances to collection of pairs.
  17.130 +     * @param col the collection of (Item) objects
  17.131 +     * @param conv the convertor to use or null
  17.132 +     */
  17.133 +    public final <T,R> void set(Collection<T> col, Convertor<T,R> conv) {
  17.134 +        ArrayList<Pair<?>> l = new ArrayList<Pair<?>>(col.size());
  17.135 +        Iterator<T> it = col.iterator();
  17.136 +
  17.137 +        if (conv == null) {
  17.138 +            while (it.hasNext()) {
  17.139 +                l.add(new SimpleItem<T>(it.next()));
  17.140 +            }
  17.141 +        } else {
  17.142 +            while (it.hasNext()) {
  17.143 +                l.add(new ConvertingItem<T,R>(it.next(), conv));
  17.144 +            }
  17.145 +        }
  17.146 +
  17.147 +        setPairs(l);
  17.148 +    }
  17.149 +
  17.150 +    /** Convertor postpones an instantiation of an object.
  17.151 +     * @since 1.25
  17.152 +     */
  17.153 +    public static interface Convertor<T,R> {
  17.154 +        /** Convert obj to other object. There is no need to implement
  17.155 +         * cache mechanism. It is provided by
  17.156 +         * {@link Item#getInstance()} method itself. However the
  17.157 +         * method can be called more than once because instance is held
  17.158 +         * just by weak reference.
  17.159 +         *
  17.160 +         * @param obj the registered object
  17.161 +         * @return the object converted from this object
  17.162 +         */
  17.163 +        public R convert(T obj);
  17.164 +
  17.165 +        /** Return type of converted object. Accessible via
  17.166 +         * {@link Item#getType()}
  17.167 +         * @param obj the registered object
  17.168 +         * @return the class that will be produced from this object (class or
  17.169 +         *      superclass of convert (obj))
  17.170 +         */
  17.171 +        public Class<? extends R> type(T obj);
  17.172 +
  17.173 +        /** Computes the ID of the resulted object. Accessible via
  17.174 +         * {@link Item#getId()}.
  17.175 +         * @param obj the registered object
  17.176 +         * @return the ID for the object
  17.177 +         */
  17.178 +        public String id(T obj);
  17.179 +
  17.180 +        /** The human presentable name for the object. Accessible via
  17.181 +         * {@link Item#getDisplayName()}.
  17.182 +         * @param obj the registered object
  17.183 +         * @return the name representing the object for the user
  17.184 +         */
  17.185 +        public String displayName(T obj);
  17.186 +    }
  17.187 +
  17.188 +    /** Instance of one item representing an object.
  17.189 +     */
  17.190 +    final static class SimpleItem<T> extends Pair<T> {
  17.191 +        private T obj;
  17.192 +
  17.193 +        /** Create an item.
  17.194 +         * @obj object to register
  17.195 +         */
  17.196 +        public SimpleItem(T obj) {
  17.197 +            if (obj == null) {
  17.198 +                throw new NullPointerException();
  17.199 +            }
  17.200 +            this.obj = obj;
  17.201 +        }
  17.202 +
  17.203 +        /** Tests whether this item can produce object
  17.204 +         * of class c.
  17.205 +         */
  17.206 +        public boolean instanceOf(Class<?> c) {
  17.207 +            return c.isInstance(obj);
  17.208 +        }
  17.209 +
  17.210 +        /** Get instance of registered object. If convertor is specified then
  17.211 +         *  method InstanceLookup.Convertor.convertor is used and weak reference
  17.212 +         * to converted object is saved.
  17.213 +         * @return the instance of the object.
  17.214 +         */
  17.215 +        public T getInstance() {
  17.216 +            return obj;
  17.217 +        }
  17.218 +
  17.219 +        @Override
  17.220 +        public boolean equals(Object o) {
  17.221 +            if (o instanceof SimpleItem) {
  17.222 +                return obj.equals(((SimpleItem) o).obj);
  17.223 +            } else {
  17.224 +                return false;
  17.225 +            }
  17.226 +        }
  17.227 +
  17.228 +        @Override
  17.229 +        public int hashCode() {
  17.230 +            return obj.hashCode();
  17.231 +        }
  17.232 +
  17.233 +        /** An identity of the item.
  17.234 +         * @return string representing the item, that can be used for
  17.235 +         *   persistance purposes to locate the same item next time
  17.236 +         */
  17.237 +        public String getId() {
  17.238 +            return "IL[" + obj.toString(); // NOI18N
  17.239 +        }
  17.240 +
  17.241 +        /** Getter for display name of the item.
  17.242 +         */
  17.243 +        public String getDisplayName() {
  17.244 +            return obj.toString();
  17.245 +        }
  17.246 +
  17.247 +        /** Method that can test whether an instance of a class has been created
  17.248 +         * by this item.
  17.249 +         *
  17.250 +         * @param obj the instance
  17.251 +         * @return if the item has already create an instance and it is the same
  17.252 +         *  as obj.
  17.253 +         */
  17.254 +        protected boolean creatorOf(Object obj) {
  17.255 +            return obj == this.obj;
  17.256 +        }
  17.257 +
  17.258 +        /** The class of this item.
  17.259 +         * @return the correct class
  17.260 +         */
  17.261 +        @SuppressWarnings("unchecked")
  17.262 +        public Class<? extends T> getType() {
  17.263 +            return (Class<? extends T>)obj.getClass();
  17.264 +        }
  17.265 +    }
  17.266 +     // end of SimpleItem
  17.267 +
  17.268 +    /** Instance of one item registered in the map.
  17.269 +     */
  17.270 +    final static class ConvertingItem<T,R> extends Pair<R> {
  17.271 +        /** registered object */
  17.272 +        private T obj;
  17.273 +
  17.274 +        /** Reference to converted object. */
  17.275 +        private WeakReference<R> ref;
  17.276 +
  17.277 +        /** convertor to use */
  17.278 +        private Convertor<? super T,R> conv;
  17.279 +
  17.280 +        /** Create an item.
  17.281 +         * @obj object to register
  17.282 +         * @conv a convertor, can be <code>null</code>.
  17.283 +         */
  17.284 +        public ConvertingItem(T obj, Convertor<? super T,R> conv) {
  17.285 +            this.obj = obj;
  17.286 +            this.conv = conv;
  17.287 +        }
  17.288 +
  17.289 +        /** Tests whether this item can produce object
  17.290 +         * of class c.
  17.291 +         */
  17.292 +        public boolean instanceOf(Class<?> c) {
  17.293 +            return c.isAssignableFrom(getType());
  17.294 +        }
  17.295 +
  17.296 +        /** Returns converted object or null if obj has not been converted yet
  17.297 +         * or reference was cleared by garbage collector.
  17.298 +         */
  17.299 +        private R getConverted() {
  17.300 +            if (ref == null) {
  17.301 +                return null;
  17.302 +            }
  17.303 +
  17.304 +            return ref.get();
  17.305 +        }
  17.306 +
  17.307 +        /** Get instance of registered object. If convertor is specified then
  17.308 +         *  method InstanceLookup.Convertor.convertor is used and weak reference
  17.309 +         * to converted object is saved.
  17.310 +         * @return the instance of the object.
  17.311 +         */
  17.312 +        public synchronized R getInstance() {
  17.313 +            R converted = getConverted();
  17.314 +
  17.315 +            if (converted == null) {
  17.316 +                converted = conv.convert(obj);
  17.317 +                ref = new WeakReference<R>(converted);
  17.318 +            }
  17.319 +
  17.320 +            return converted;
  17.321 +        }
  17.322 +
  17.323 +        @Override
  17.324 +        public boolean equals(Object o) {
  17.325 +            if (o instanceof ConvertingItem) {
  17.326 +                return obj.equals(((ConvertingItem) o).obj);
  17.327 +            } else {
  17.328 +                return false;
  17.329 +            }
  17.330 +        }
  17.331 +
  17.332 +        @Override
  17.333 +        public int hashCode() {
  17.334 +            return obj.hashCode();
  17.335 +        }
  17.336 +
  17.337 +        /** An identity of the item.
  17.338 +         * @return string representing the item, that can be used for
  17.339 +         *   persistance purposes to locate the same item next time
  17.340 +         */
  17.341 +        public String getId() {
  17.342 +            return conv.id(obj);
  17.343 +        }
  17.344 +
  17.345 +        /** Getter for display name of the item.
  17.346 +         */
  17.347 +        public String getDisplayName() {
  17.348 +            return conv.displayName(obj);
  17.349 +        }
  17.350 +
  17.351 +        /** Method that can test whether an instance of a class has been created
  17.352 +         * by this item.
  17.353 +         *
  17.354 +         * @param obj the instance
  17.355 +         * @return if the item has already create an instance and it is the same
  17.356 +         *  as obj.
  17.357 +         */
  17.358 +        protected boolean creatorOf(Object obj) {
  17.359 +            if (conv == null) {
  17.360 +                return obj == this.obj;
  17.361 +            } else {
  17.362 +                return obj == getConverted();
  17.363 +            }
  17.364 +        }
  17.365 +
  17.366 +        /** The class of this item.
  17.367 +         * @return the correct class
  17.368 +         */
  17.369 +        @SuppressWarnings("unchecked")
  17.370 +        public Class<? extends R> getType() {
  17.371 +            R converted = getConverted();
  17.372 +
  17.373 +            if (converted == null) {
  17.374 +                return conv.type(obj);
  17.375 +            }
  17.376 +
  17.377 +            return (Class<? extends R>)converted.getClass();
  17.378 +        }
  17.379 +    }
  17.380 +     // end of ConvertingItem
  17.381 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/Lookups.java	Sat Oct 31 15:28:13 2009 +0100
    18.3 @@ -0,0 +1,317 @@
    18.4 +/*
    18.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    18.6 + *
    18.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    18.8 + *
    18.9 + * The contents of this file are subject to the terms of either the GNU
   18.10 + * General Public License Version 2 only ("GPL") or the Common
   18.11 + * Development and Distribution License("CDDL") (collectively, the
   18.12 + * "License"). You may not use this file except in compliance with the
   18.13 + * License. You can obtain a copy of the License at
   18.14 + * http://www.netbeans.org/cddl-gplv2.html
   18.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   18.16 + * specific language governing permissions and limitations under the
   18.17 + * License.  When distributing the software, include this License Header
   18.18 + * Notice in each file and include the License file at
   18.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   18.20 + * particular file as subject to the "Classpath" exception as provided
   18.21 + * by Sun in the GPL Version 2 section of the License file that
   18.22 + * accompanied this code. If applicable, add the following below the
   18.23 + * License Header, with the fields enclosed by brackets [] replaced by
   18.24 + * your own identifying information:
   18.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   18.26 + *
   18.27 + * Contributor(s):
   18.28 + *
   18.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   18.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
   18.31 + * Microsystems, Inc. All Rights Reserved.
   18.32 + *
   18.33 + * If you wish your version of this file to be governed by only the CDDL
   18.34 + * or only the GPL Version 2, indicate your decision by adding
   18.35 + * "[Contributor] elects to include this software in this distribution
   18.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   18.37 + * single choice of license, a recipient has the option to distribute
   18.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   18.39 + * to extend the choice of license to its licensees as provided above.
   18.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   18.41 + * Version 2 license, then the option applies only if the new code is
   18.42 + * made subject to such option by the copyright holder.
   18.43 + */
   18.44 +
   18.45 +package org.openide.util.lookup;
   18.46 +
   18.47 +import java.util.Arrays;
   18.48 +import org.netbeans.modules.openide.util.NamedServicesProvider;
   18.49 +import org.openide.util.Lookup;
   18.50 +
   18.51 +/**
   18.52 + * Static factory methods for creating common lookup implementations.
   18.53 + *
   18.54 + * @author David Strupl
   18.55 + * @since 2.21
   18.56 + */
   18.57 +public class Lookups {
   18.58 +
   18.59 +    /** static methods only */
   18.60 +    private Lookups() {}
   18.61 +
   18.62 +    /**
   18.63 +     * Creates a singleton lookup. It means lookup that contains only
   18.64 +     * one object specified via the supplied parameter. The lookup will
   18.65 +     * either return the object or null if the supplied template does
   18.66 +     * not match the class. If the specified argument is null the method
   18.67 +     * will end with NullPointerException.
   18.68 +     * @return Fully initialized lookup object ready to use
   18.69 +     * @throws NullPointerException if the supplied argument is null
   18.70 +     * @since 2.21
   18.71 +     */
   18.72 +    public static Lookup singleton(Object objectToLookup) {
   18.73 +        if (objectToLookup == null) {
   18.74 +            throw new NullPointerException();
   18.75 +        }
   18.76 +
   18.77 +        return new SingletonLookup(objectToLookup);
   18.78 +    }
   18.79 +
   18.80 +    /**
   18.81 +     * Creates a lookup that contains an array of objects specified via the
   18.82 +     * parameter. The resulting lookup is fixed in the following sense: it
   18.83 +     * contains only fixed set of objects passed in by the array parameter.
   18.84 +     * Its contents never changes so registering listeners on such lookup
   18.85 +     * does not have any observable effect (the listeners are never called).
   18.86 +     *
   18.87 +     * @param objectsToLookup list of objects to include
   18.88 +     * @return Fully initialized lookup object ready to use
   18.89 +     * @throws NullPointerException if the supplied argument is null
   18.90 +     * @since 2.21
   18.91 +     *
   18.92 +     */
   18.93 +    public static Lookup fixed(Object... objectsToLookup) {
   18.94 +        if (objectsToLookup == null) {
   18.95 +            throw new NullPointerException();
   18.96 +        }
   18.97 +
   18.98 +        if (objectsToLookup.length == 0) {
   18.99 +            return Lookup.EMPTY;
  18.100 +        }
  18.101 +
  18.102 +        if (objectsToLookup.length == 1) {
  18.103 +            return singleton(objectsToLookup[0]);
  18.104 +        }
  18.105 +
  18.106 +        return new SimpleLookup(Arrays.asList(objectsToLookup));
  18.107 +    }
  18.108 +
  18.109 +    /**
  18.110 +     * Creates a lookup that contains an array of objects specified via the
  18.111 +     * parameter. The resulting lookup is fixed in the following sense: it
  18.112 +     * contains only fixed set of objects passed in by the array parameter.
  18.113 +     * The objects returned from this lookup are converted to real objects
  18.114 +     * before they are returned by the lookup.
  18.115 +     * Its contents never changes so registering listeners on such lookup
  18.116 +     * does not have any observable effect (the listeners are never called).
  18.117 +     *
  18.118 +     * @return Fully initialized lookup object ready to use
  18.119 +     * @throws NullPointerException if the any of the arguments is null
  18.120 +     * @since 2.21
  18.121 +     *
  18.122 +     */
  18.123 +    public static <T,R> Lookup fixed(T[] keys, InstanceContent.Convertor<? super T,R> convertor) {
  18.124 +        if (keys == null) {
  18.125 +            throw new NullPointerException();
  18.126 +        }
  18.127 +
  18.128 +        if (convertor == null) {
  18.129 +            throw new NullPointerException();
  18.130 +        }
  18.131 +
  18.132 +        return new SimpleLookup(Arrays.asList(keys), convertor);
  18.133 +    }
  18.134 +
  18.135 +    /** Creates a lookup that delegates to another one but that one can change
  18.136 +     * from time to time. The returned lookup checks every time somebody calls
  18.137 +     * <code>lookup</code> or <code>lookupItem</code> method whether the
  18.138 +     * provider still returns the same lookup. If not, it updates state of
  18.139 +     * all {@link org.openide.util.Lookup.Result}s 
  18.140 +     * that it created (and that still exists).
  18.141 +     * <P>
  18.142 +     * The user of this method has to implement its provider's <code>getLookup</code>
  18.143 +     * method (must be thread safe and fast, will be called often and from any thread)
  18.144 +     * pass it to this method and use the returned lookup. Whenever the user
  18.145 +     * changes the return value from the <code>getLookup</code> method and wants
  18.146 +     * to notify listeners on the lookup about that it should trigger the event
  18.147 +     * firing, for example by calling <code>lookup.lookup (Object.class)</code>
  18.148 +     * directly on the lookup returned by this method
  18.149 +     * that forces a check of the return value of {@link org.openide.util.Lookup.Provider#getLookup}</code>.
  18.150 +     *
  18.151 +     * @param provider the provider that returns a lookup to delegate to
  18.152 +     * @return lookup delegating to the lookup returned by the provider
  18.153 +     * @since 3.9
  18.154 +     */
  18.155 +    public static Lookup proxy(Lookup.Provider provider) {
  18.156 +        return new SimpleProxyLookup(provider);
  18.157 +    }
  18.158 +
  18.159 +    /** Returns a lookup that implements the JDK1.3 JAR services mechanism and delegates
  18.160 +     * to META-INF/services/name.of.class files.
  18.161 +     * <p>Some extensions to the JAR services specification are implemented:
  18.162 +     * <ol>
  18.163 +     * <li>An entry may be followed by a line of the form <code>#position=<i>integer</i></code>
  18.164 +     *     to specify ordering. (Smaller numbers first, entries with unspecified position last.)
  18.165 +     * <li>A line of the form <code>#-<i>classname</i></code> suppresses an entry registered
  18.166 +     *     in another file, so can be used to supersede one implementation with another.
  18.167 +     * </ol>
  18.168 +     * <p>Note: It is not dynamic - so if you need to change the classloader or JARs,
  18.169 +     * wrap it in a {@link ProxyLookup} and change the delegate when necessary.
  18.170 +     * Existing instances will be kept if the implementation classes are unchanged,
  18.171 +     * so there is "stability" in doing this provided some parent loaders are the same
  18.172 +     * as the previous ones.
  18.173 +     * @since 3.35
  18.174 +     * @see ServiceProvider
  18.175 +     */
  18.176 +    public static Lookup metaInfServices(ClassLoader classLoader) {
  18.177 +        return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N
  18.178 +    }
  18.179 +
  18.180 +    /** Returns a lookup that behaves exactly like {@link #metaInfServices(ClassLoader)}
  18.181 +     * except that it does not read data from <code>META-INF/services/</code>, but instead
  18.182 +     * from the specified prefix.
  18.183 +     * @param classLoader class loader to use for loading
  18.184 +     * @param prefix prefix to prepend to the class name when searching
  18.185 +     * @since 7.9
  18.186 +     */
  18.187 +    public static Lookup metaInfServices(ClassLoader classLoader, String prefix) {
  18.188 +        return new MetaInfServicesLookup(classLoader, prefix);
  18.189 +    }
  18.190 +    
  18.191 +    /** Creates a <q>named</q> lookup.
  18.192 +     * It is a lookup identified by a given path.
  18.193 +     * Two lookups with the same path should have the same content.
  18.194 +     * <p>It is expected that each <q>named</q> lookup
  18.195 +     * will contain a superset of what would be created by:
  18.196 +     * <code>{@linkplain #metaInfServices(ClassLoader,String) metaInfServices}(theRightLoader, "META-INF/namedservices/" + path + "/")</code>
  18.197 +     *
  18.198 +     * <p class="nonnormative">Various environments can add their own
  18.199 +     * extensions to its content. As such
  18.200 +     * {@link Lookups#forPath(java.lang.String)} can combine lookups
  18.201 +     * from several sources. In current NetBeans Runtime Container, two lookups are used:
  18.202 +     * </p>
  18.203 +     * <ul class="nonnormative">
  18.204 +     * <li><code>Lookups.metaInfServices("META-INF/namedservices/" + path)</code></li>
  18.205 +     * <li><code>org.openide.loaders.FolderLookup(path)</code></li>
  18.206 +     * </ul>
  18.207 +     * <p class="nonnormative">
  18.208 +     * Please note that these lookups differ in the way they inspect sub-folders.
  18.209 +     * The first lookup just returns instances from the given path, ignoring
  18.210 +     * sub-folders, the second one retrieves instances from the whole sub-tree.
  18.211 +     * </p>
  18.212 +     * <p>
  18.213 +     * Read more about the <a href="../doc-files/api.html#folderlookup">usage of this method</a>.
  18.214 +     * 
  18.215 +     * @param path the path identifying the lookup, e.g. <code>Projects/Actions</code>
  18.216 +     * @return lookup associated with this path
  18.217 +     * @since 7.9
  18.218 +     */
  18.219 +    public static Lookup forPath(String path) {
  18.220 +        return NamedServicesProvider.find(path);
  18.221 +    }
  18.222 +    
  18.223 +    /** Creates a lookup that wraps another one and filters out instances
  18.224 +     * of specified classes. If you have a lookup and
  18.225 +     * you want to remove all instances of ActionMap you can use:
  18.226 +     * <pre>
  18.227 +     * l = Lookups.exclude(lookup, ActionMap.class);
  18.228 +     * </pre>
  18.229 +     * Then anybody who asks for <code>l.lookup(ActionMap.class)</code> or
  18.230 +     * subclass will get <code>null</code>. Even if the original lookup contains the
  18.231 +     * value.
  18.232 +     * To create empty lookup (well, just an example, otherwise use {@link Lookup#EMPTY}) one could use:
  18.233 +     * <pre>
  18.234 +     * Lookup.exclude(anyLookup, Object.class);
  18.235 +     * </pre>
  18.236 +     * as any instance in any lookup is of type Object and thus would be excluded.
  18.237 +     * <p>
  18.238 +     * The complete behavior can be described as <code>classes</code> being
  18.239 +     * a barrier. For an object not to be excluded, there has to be an inheritance
  18.240 +     * path between the queried class and the actual class of the instance,
  18.241 +     * that is not blocked by any of the excluded classes:
  18.242 +     * <pre>
  18.243 +     * interface A {}
  18.244 +     * interface B {}
  18.245 +     * class C implements A, B {}
  18.246 +     * Object c = new C();
  18.247 +     * Lookup l1 = Lookups.singleton(c);
  18.248 +     * Lookup l2 = Lookups.exclude(l1, A.class);
  18.249 +     * assertNull("A is directly excluded", l2.lookup(A.class));
  18.250 +     * assertEquals("Returns C as A.class is not between B and C", c, l2.lookup(B.class));
  18.251 +     * </pre>
  18.252 +     * For more info check the
  18.253 +     * <a href="http://hg.netbeans.org/main-golden/annotate/4883eaeda744/openide.util/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java">
  18.254 +     * excluding lookup tests</a> and the discussion in issue
  18.255 +     * <a href="http://openide.netbeans.org/issues/show_bug.cgi?id=53058">53058</a>.
  18.256 +     *
  18.257 +     * @param lookup the original lookup that should be filtered
  18.258 +     * @param classes array of classes those instances should be excluded
  18.259 +     * @since 5.4
  18.260 +     */
  18.261 +    public static Lookup exclude(Lookup lookup, Class... classes) {
  18.262 +        return new ExcludingLookup(lookup, classes);
  18.263 +    }
  18.264 +
  18.265 +    /** Creates <code>Lookup.Item</code> representing the instance passed in.
  18.266 +     *
  18.267 +     * @param instance the object for which Lookup.Item should be creted
  18.268 +     * @param id unique identification of the object, for details see {@link org.openide.util.Lookup.Item#getId},
  18.269 +     * can be <code>null</code>
  18.270 +     * @return lookup item representing instance
  18.271 +     * @since 4.8
  18.272 +     */
  18.273 +    public static <T> Lookup.Item<T> lookupItem(T instance, String id) {
  18.274 +        return new LookupItem<T>(instance, id);
  18.275 +    }
  18.276 +
  18.277 +    private static class LookupItem<T> extends Lookup.Item<T> {
  18.278 +        private String id;
  18.279 +        private T instance;
  18.280 +
  18.281 +        public LookupItem(T instance) {
  18.282 +            this(instance, null);
  18.283 +        }
  18.284 +
  18.285 +        public LookupItem(T instance, String id) {
  18.286 +            this.id = id;
  18.287 +            this.instance = instance;
  18.288 +        }
  18.289 +
  18.290 +        public String getDisplayName() {
  18.291 +            return getId();
  18.292 +        }
  18.293 +
  18.294 +        public String getId() {
  18.295 +            return (id == null) ? instance.toString() : id;
  18.296 +        }
  18.297 +
  18.298 +        public T getInstance() {
  18.299 +            return instance;
  18.300 +        }
  18.301 +
  18.302 +        @SuppressWarnings("unchecked")
  18.303 +        public Class<? extends T> getType() {
  18.304 +            return (Class<? extends T>)instance.getClass();
  18.305 +        }
  18.306 +
  18.307 +        public @Override boolean equals(Object object) {
  18.308 +            if (object instanceof LookupItem) {
  18.309 +                return instance == ((LookupItem) object).getInstance();
  18.310 +            }
  18.311 +
  18.312 +            return false;
  18.313 +        }
  18.314 +
  18.315 +        public @Override int hashCode() {
  18.316 +            return instance.hashCode();
  18.317 +        }
  18.318 +    }
  18.319 +     // End of LookupItem class
  18.320 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/MetaInfServicesLookup.java	Sat Oct 31 15:28:13 2009 +0100
    19.3 @@ -0,0 +1,560 @@
    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 +
   19.45 +package org.openide.util.lookup;
   19.46 +
   19.47 +import java.io.BufferedReader;
   19.48 +import java.io.IOException;
   19.49 +import java.io.InputStream;
   19.50 +import java.io.InputStreamReader;
   19.51 +import java.lang.ref.Reference;
   19.52 +import java.lang.ref.WeakReference;
   19.53 +import java.lang.reflect.Method;
   19.54 +import java.net.URL;
   19.55 +import java.util.ArrayList;
   19.56 +import java.util.Collection;
   19.57 +import java.util.Enumeration;
   19.58 +import java.util.HashSet;
   19.59 +import java.util.LinkedHashSet;
   19.60 +import java.util.List;
   19.61 +import java.util.Map;
   19.62 +import java.util.WeakHashMap;
   19.63 +import java.util.concurrent.Executor;
   19.64 +import java.util.logging.Level;
   19.65 +import java.util.logging.Logger;
   19.66 +import org.openide.util.Lookup;
   19.67 +import org.openide.util.RequestProcessor;
   19.68 +
   19.69 +/**
   19.70 + * @author Jaroslav Tulach, Jesse Glick
   19.71 + * @see Lookups#metaInfServices(ClassLoader,String)
   19.72 + * @see "#14722"
   19.73 + */
   19.74 +final class MetaInfServicesLookup extends AbstractLookup {
   19.75 +
   19.76 +    private static final Logger LOGGER = Logger.getLogger(MetaInfServicesLookup.class.getName());
   19.77 +    static final Executor RP = new RequestProcessor(MetaInfServicesLookup.class.getName(), 1);
   19.78 +    private static int knownInstancesCount;
   19.79 +    private static final List<Reference<Object>> knownInstances;
   19.80 +    static {
   19.81 +        knownInstances = new ArrayList<Reference<Object>>();
   19.82 +        for (int i = 0; i < 512; i++) {
   19.83 +            knownInstances.add(null);
   19.84 +        }
   19.85 +    }
   19.86 +
   19.87 +    /** A set of all requested classes.
   19.88 +     * Note that classes that we actually succeeded on can never be removed
   19.89 +     * from here because we hold a strong reference to the loader.
   19.90 +     * However we also hold classes which are definitely not loadable by
   19.91 +     * our loader.
   19.92 +     */
   19.93 +    private final Map<Class,Object> classes = new WeakHashMap<Class,Object>();
   19.94 +
   19.95 +    /** class loader to use */
   19.96 +    private final ClassLoader loader;
   19.97 +    /** prefix to prepend */
   19.98 +    private final String prefix;
   19.99 +
  19.100 +    /** Create a lookup reading from a specified classloader.
  19.101 +     */
  19.102 +    public MetaInfServicesLookup(ClassLoader loader, String prefix) {
  19.103 +        this.loader = loader;
  19.104 +        this.prefix = prefix;
  19.105 +
  19.106 +        LOGGER.log(Level.FINE, "Created: {0}", this);
  19.107 +    }
  19.108 +
  19.109 +    @Override
  19.110 +    public String toString() {
  19.111 +        return "MetaInfServicesLookup[" + loader + "]"; // NOI18N
  19.112 +    }
  19.113 +
  19.114 +    /* Tries to load appropriate resources from manifest files.
  19.115 +     */
  19.116 +    @Override
  19.117 +    protected final void beforeLookup(Lookup.Template t) {
  19.118 +        Class c = t.getType();
  19.119 +
  19.120 +        Collection<AbstractLookup.Pair<?>> toAdd = null;
  19.121 +        synchronized (this) {
  19.122 +            if (classes.get(c) == null) { // NOI18N
  19.123 +                toAdd = new ArrayList<Pair<?>>();
  19.124 +            } else {
  19.125 +                // ok, nothing needs to be done
  19.126 +                return;
  19.127 +            }
  19.128 +        }
  19.129 +        if (toAdd != null) {
  19.130 +            search(c, toAdd);
  19.131 +        }
  19.132 +        synchronized (this) {
  19.133 +            if (classes.put(c, "") == null) { // NOI18N
  19.134 +                // Added new class, search for it.
  19.135 +                LinkedHashSet<AbstractLookup.Pair<?>> arr = getPairsAsLHS();
  19.136 +                arr.addAll(toAdd);
  19.137 +                setPairs(arr, RP);
  19.138 +            }
  19.139 +        }
  19.140 +    }
  19.141 +
  19.142 +    /** Finds all pairs and adds them to the collection.
  19.143 +     *
  19.144 +     * @param clazz class to find
  19.145 +     * @param result collection to add Pair to
  19.146 +     */
  19.147 +    private void search(Class<?> clazz, Collection<AbstractLookup.Pair<?>> result) {
  19.148 +        if (LOGGER.isLoggable(Level.FINER)) {
  19.149 +            LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this);
  19.150 +        }
  19.151 +
  19.152 +        String res = prefix + clazz.getName(); // NOI18N
  19.153 +        Enumeration<URL> en;
  19.154 +
  19.155 +        try {
  19.156 +            en = loader.getResources(res);
  19.157 +        } catch (IOException ioe) {
  19.158 +            // do not use ErrorManager because we are in the startup code
  19.159 +            // and ErrorManager might not be ready
  19.160 +            ioe.printStackTrace();
  19.161 +
  19.162 +            return;
  19.163 +        }
  19.164 +
  19.165 +        // Do not create multiple instances in case more than one JAR
  19.166 +        // has the same entry in it (and they load to the same class).
  19.167 +        // Probably would not happen, assuming JARs only list classes
  19.168 +        // they own, but just in case...
  19.169 +        List<Item> foundClasses = new ArrayList<Item>();
  19.170 +        Collection<Class> removeClasses = new ArrayList<Class>();
  19.171 +
  19.172 +        boolean foundOne = false;
  19.173 +
  19.174 +        while (en.hasMoreElements()) {
  19.175 +            if (!foundOne) {
  19.176 +                foundOne = true;
  19.177 +
  19.178 +                // Double-check that in fact we can load the *interface* class.
  19.179 +                // For example, say class I is defined in two JARs, J1 and J2.
  19.180 +                // There is also an implementation M1 defined in J1, and another
  19.181 +                // implementation M2 defined in J2.
  19.182 +                // Classloaders C1 and C2 are made from J1 and J2.
  19.183 +                // A MetaInfServicesLookup is made from C1. Then the user asks to
  19.184 +                // lookup I as loaded from C2. J1 has the services line and lists
  19.185 +                // M1, and we can in fact make it. However it is not of the desired
  19.186 +                // type to be looked up. Don't do this check, which could be expensive,
  19.187 +                // unless we expect to be getting some results, however.
  19.188 +                Class realMcCoy = null;
  19.189 +
  19.190 +                try {
  19.191 +                    realMcCoy = loader.loadClass(clazz.getName());
  19.192 +                } catch (ClassNotFoundException cnfe) {
  19.193 +                    // our loader does not know about it, OK
  19.194 +                }
  19.195 +
  19.196 +                if (realMcCoy != clazz) {
  19.197 +                    // Either the interface class is not available at all in our loader,
  19.198 +                    // or it is not the same version as we expected. Don't provide results.
  19.199 +                    if (LOGGER.isLoggable(Level.WARNING)) {
  19.200 +                        if (realMcCoy != null) {
  19.201 +                            LOGGER.log(Level.WARNING,
  19.202 +                                clazz.getName() + " is not the real McCoy! Actually found it in " +
  19.203 +                                realMcCoy.getClassLoader()
  19.204 +                            ); // NOI18N
  19.205 +                        } else {
  19.206 +                            LOGGER.log(Level.WARNING, clazz.getName() + " could not be found in " + loader); // NOI18N
  19.207 +                        }
  19.208 +                    }
  19.209 +
  19.210 +                    return;
  19.211 +                }
  19.212 +            }
  19.213 +
  19.214 +            URL url = en.nextElement();
  19.215 +            Item currentItem = null;
  19.216 +
  19.217 +            try {
  19.218 +                InputStream is = url.openStream();
  19.219 +
  19.220 +                try {
  19.221 +                    BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N
  19.222 +
  19.223 +                    while (true) {
  19.224 +                        String line = reader.readLine();
  19.225 +
  19.226 +                        if (line == null) {
  19.227 +                            break;
  19.228 +                        }
  19.229 +
  19.230 +                        line = line.trim();
  19.231 +
  19.232 +                        // is it position attribute?
  19.233 +                        if (line.startsWith("#position=")) {
  19.234 +                            if (currentItem == null) {
  19.235 +                                LOGGER.log(Level.WARNING, "Found line '{0}' in {1} but there is no item to associate it with", new Object[] {line, url});
  19.236 +                                continue;
  19.237 +                            }
  19.238 +
  19.239 +                            try {
  19.240 +                                currentItem.position = Integer.parseInt(line.substring(10));
  19.241 +                            } catch (NumberFormatException e) {
  19.242 +                                // do not use ErrorManager because we are in the startup code
  19.243 +                                // and ErrorManager might not be ready
  19.244 +                                e.printStackTrace();
  19.245 +                            }
  19.246 +                        }
  19.247 +
  19.248 +                        if (currentItem != null) {
  19.249 +                            insertItem(currentItem, foundClasses);
  19.250 +                            currentItem = null;
  19.251 +                        }
  19.252 +
  19.253 +                        // Ignore blank lines and comments.
  19.254 +                        if (line.length() == 0) {
  19.255 +                            continue;
  19.256 +                        }
  19.257 +
  19.258 +                        boolean remove = false;
  19.259 +
  19.260 +                        if (line.charAt(0) == '#') {
  19.261 +                            if ((line.length() == 1) || (line.charAt(1) != '-')) {
  19.262 +                                continue;
  19.263 +                            }
  19.264 +
  19.265 +                            // line starting with #- is a sign to remove that class from lookup
  19.266 +                            remove = true;
  19.267 +                            line = line.substring(2);
  19.268 +                        }
  19.269 +
  19.270 +                        Class inst = null;
  19.271 +
  19.272 +                        try {
  19.273 +                            // Most lines are fully-qualified class names.
  19.274 +                            inst = Class.forName(line, false, loader);
  19.275 +                        } catch (ClassNotFoundException cnfe) {
  19.276 +                            if (remove) {
  19.277 +                                // if we are removing somthing and the something
  19.278 +                                // cannot be found it is ok to do nothing
  19.279 +                                continue;
  19.280 +                            } else {
  19.281 +                                // but if we are not removing just rethrow
  19.282 +                                throw cnfe;
  19.283 +                            }
  19.284 +                        }
  19.285 +
  19.286 +                        if (!clazz.isAssignableFrom(inst)) {
  19.287 +                            throw new ClassNotFoundException(clazzToString(inst) + " not a subclass of " + clazzToString(clazz)); // NOI18N
  19.288 +                        }
  19.289 +
  19.290 +                        if (remove) {
  19.291 +                            removeClasses.add(inst);
  19.292 +                        } else {
  19.293 +                            // create new item here, but do not put it into
  19.294 +                            // foundClasses array yet because following line
  19.295 +                            // might specify its position
  19.296 +                            currentItem = new Item();
  19.297 +                            currentItem.clazz = inst;
  19.298 +                        }
  19.299 +                    }
  19.300 +
  19.301 +                    if (currentItem != null) {
  19.302 +                        insertItem(currentItem, foundClasses);
  19.303 +                        currentItem = null;
  19.304 +                    }
  19.305 +                } finally {
  19.306 +                    is.close();
  19.307 +                }
  19.308 +            } catch (ClassNotFoundException ex) {
  19.309 +                LOGGER.log(Level.WARNING, null, ex);
  19.310 +            } catch (IOException ex) {
  19.311 +                LOGGER.log(Level.WARNING, null, ex);
  19.312 +            }
  19.313 +        }
  19.314 +
  19.315 +        LOGGER.log(Level.FINER, "Found impls of {0}: {1} and removed: {2} from: {3}", new Object[] {clazz.getName(), foundClasses, removeClasses, this});
  19.316 +
  19.317 +        foundClasses.removeAll(removeClasses);
  19.318 +
  19.319 +        for (Item item : foundClasses) {
  19.320 +            if (removeClasses.contains(item.clazz)) {
  19.321 +                continue;
  19.322 +            }
  19.323 +
  19.324 +            result.add(new P(item.clazz));
  19.325 +        }
  19.326 +    }
  19.327 +    private static String clazzToString(Class clazz) {
  19.328 +        return clazz.getName() + "@" + clazz.getClassLoader() + ":" + clazz.getProtectionDomain().getCodeSource().getLocation(); // NOI18N
  19.329 +    }
  19.330 +
  19.331 +    /**
  19.332 +     * Insert item to the list according to item.position value.
  19.333 +     */
  19.334 +    private void insertItem(Item item, List<Item> list) {
  19.335 +        // no position? -> add it to the end
  19.336 +        if (item.position == -1) {
  19.337 +            list.add(item);
  19.338 +
  19.339 +            return;
  19.340 +        }
  19.341 +
  19.342 +        int index = -1;
  19.343 +        for (Item i : list) {
  19.344 +            index++;
  19.345 +
  19.346 +            if (i.position == -1) {
  19.347 +                list.add(index, item);
  19.348 +
  19.349 +                return;
  19.350 +            } else {
  19.351 +                if (i.position > item.position) {
  19.352 +                    list.add(index, item);
  19.353 +
  19.354 +                    return;
  19.355 +                }
  19.356 +            }
  19.357 +        }
  19.358 +
  19.359 +        list.add(item);
  19.360 +    }
  19.361 +
  19.362 +    private static class Item {
  19.363 +        private Class clazz;
  19.364 +        private int position = -1;
  19.365 +        @Override
  19.366 +        public String toString() {
  19.367 +            return "MetaInfServicesLookup.Item[" + clazz.getName() + "]"; // NOI18N
  19.368 +        }
  19.369 +    }
  19.370 +
  19.371 +    /** Pair that holds name of a class and maybe the instance.
  19.372 +     */
  19.373 +    private static final class P extends AbstractLookup.Pair<Object> {
  19.374 +        /** May be one of three things:
  19.375 +         * 1. The implementation class which was named in the services file.
  19.376 +         * 2. An instance of it.
  19.377 +         * 3. Null, if creation of the instance resulted in an error.
  19.378 +         */
  19.379 +        private Object object;
  19.380 +
  19.381 +        public P(Class<?> clazz) {
  19.382 +            this.object = clazz;
  19.383 +        }
  19.384 +
  19.385 +        /** Finds the class.
  19.386 +         */
  19.387 +        private Class<? extends Object> clazz() {
  19.388 +            Object o = object;
  19.389 +
  19.390 +            if (o instanceof Class) {
  19.391 +                return (Class<? extends Object>) o;
  19.392 +            } else if (o != null) {
  19.393 +                return o.getClass();
  19.394 +            } else {
  19.395 +                // Broken.
  19.396 +                return Object.class;
  19.397 +            }
  19.398 +        }
  19.399 +
  19.400 +        @Override
  19.401 +        public boolean equals(Object o) {
  19.402 +            if (o instanceof P) {
  19.403 +                return ((P) o).clazz().equals(clazz());
  19.404 +            }
  19.405 +
  19.406 +            return false;
  19.407 +        }
  19.408 +
  19.409 +        @Override
  19.410 +        public int hashCode() {
  19.411 +            return clazz().hashCode();
  19.412 +        }
  19.413 +
  19.414 +        protected boolean instanceOf(Class<?> c) {
  19.415 +            return c.isAssignableFrom(clazz());
  19.416 +        }
  19.417 +
  19.418 +        public Class<?> getType() {
  19.419 +            return clazz();
  19.420 +        }
  19.421 +
  19.422 +        public Object getInstance() {
  19.423 +            Object o = object; // keeping local copy to avoid another
  19.424 +
  19.425 +            // thread to modify it under my hands
  19.426 +            if (o instanceof Class) {
  19.427 +                synchronized (o) { // o is Class and we will not create 
  19.428 +                                   // 2 instances of the same class
  19.429 +
  19.430 +                    try {
  19.431 +                        Class<?> c = ((Class) o);
  19.432 +                        o = null;
  19.433 +
  19.434 +                        synchronized (knownInstances) { // guards only the static cache
  19.435 +                            int size = knownInstances.size();
  19.436 +                            int index = c.hashCode() % size;
  19.437 +                            for (int i = 0; i < size; i++) {
  19.438 +                                Reference<Object> ref = knownInstances.get(index);
  19.439 +                                Object obj = ref == null ? null : ref.get();
  19.440 +                                if (obj == null) {
  19.441 +                                    break;
  19.442 +                                }
  19.443 +                                if (c == obj.getClass()) {
  19.444 +                                    o = obj;
  19.445 +                                    break;
  19.446 +                                }
  19.447 +                                if (++index == size) {
  19.448 +                                    index = 0;
  19.449 +                                }
  19.450 +                            }
  19.451 +                        }
  19.452 +
  19.453 +                        if (o == null) {
  19.454 +                            o = createInstance(c);
  19.455 +
  19.456 +                            synchronized (knownInstances) { // guards only the static cache
  19.457 +                                hashPut(o);
  19.458 +
  19.459 +                                int size = knownInstances.size();
  19.460 +                                if (knownInstancesCount > size * 2 / 3) {
  19.461 +                                    LOGGER.log(Level.CONFIG, "Cache of size {0} is 2/3 full. Rehashing.", size);
  19.462 +                                    HashSet<Reference<Object>> all = new HashSet<Reference<Object>>();
  19.463 +                                    all.addAll(knownInstances);
  19.464 +                                    for (int i = 0; i < size; i++) {
  19.465 +                                        knownInstances.set(i, null);
  19.466 +                                    }
  19.467 +                                    for (int i = 0; i < size; i++) {
  19.468 +                                        knownInstances.add(null);
  19.469 +                                    }
  19.470 +                                    knownInstancesCount = 0;
  19.471 +                                    for (Reference<Object> r : all) {
  19.472 +                                        if (r == null) {
  19.473 +                                            continue;
  19.474 +                                        }
  19.475 +                                        Object instance = r.get();
  19.476 +                                        if (instance == null) {
  19.477 +                                            continue;
  19.478 +                                        }
  19.479 +                                        hashPut(instance);
  19.480 +                                    }
  19.481 +                                }
  19.482 +
  19.483 +                            }
  19.484 +                        }
  19.485 +
  19.486 +                        // Do not assign to instance var unless there is a complete synch
  19.487 +                        // block between the newInstance and this line. Otherwise we could
  19.488 +                        // be assigning a half-constructed instance that another thread
  19.489 +                        // could see and return immediately.
  19.490 +                        object = o;
  19.491 +                    } catch (Exception ex) {
  19.492 +                        LOGGER.log(Level.WARNING, "Cannot create " + object, ex);
  19.493 +                        object = null;
  19.494 +                    } catch (ExceptionInInitializerError x) { // #174055
  19.495 +                        LOGGER.log(Level.WARNING, "Cannot create " + object, x);
  19.496 +                        object = null;
  19.497 +                    }
  19.498 +                }
  19.499 +            }
  19.500 +
  19.501 +            return object;
  19.502 +        }
  19.503 +
  19.504 +        public String getDisplayName() {
  19.505 +            return clazz().getName();
  19.506 +        }
  19.507 +
  19.508 +        public String getId() {
  19.509 +            return clazz().getName();
  19.510 +        }
  19.511 +
  19.512 +        protected boolean creatorOf(Object obj) {
  19.513 +            return obj == object;
  19.514 +        }
  19.515 +
  19.516 +        private static void hashPut(Object o) {
  19.517 +            Class<?> c = o.getClass();
  19.518 +            int size = knownInstances.size();
  19.519 +            int index = c.hashCode() % size;
  19.520 +            for (int i = 0; i < size; i++) {
  19.521 +                Reference<Object> ref = knownInstances.get(index);
  19.522 +                Object obj = ref == null ? null : ref.get();
  19.523 +                if (obj == null) {
  19.524 +                    knownInstances.set(index, new WeakReference<Object>(o));
  19.525 +                    knownInstancesCount++;
  19.526 +                    break;
  19.527 +                }
  19.528 +                if (++index == size) {
  19.529 +                    index = 0;
  19.530 +                }
  19.531 +            }
  19.532 +        }
  19.533 +
  19.534 +        private static boolean findSharedClassObjectSkip;
  19.535 +        private static Method findSharedClassObject;
  19.536 +        /** Basically does c.newInstance(), however the method is complicated
  19.537 +         * with a special behaviour for old and almost obsoleted NetBeans
  19.538 +         * class: SharedClassObject.
  19.539 +         */
  19.540 +        private static Object createInstance(Class<?> c) throws InstantiationException, IllegalAccessException {
  19.541 +            if (!findSharedClassObjectSkip) {
  19.542 +                try {
  19.543 +                    if (findSharedClassObject == null) {
  19.544 +                        Class<?> sco;
  19.545 +                        try {
  19.546 +                            sco = Class.forName("org.openide.util.SharedClassObject"); // NOI18N
  19.547 +                        } catch (ClassNotFoundException ex) {
  19.548 +                            findSharedClassObjectSkip = true;
  19.549 +                            return c.newInstance();
  19.550 +                        }
  19.551 +                        findSharedClassObject = sco.getMethod("findObject", Class.class, boolean.class);
  19.552 +                    }
  19.553 +                    if (findSharedClassObject.getReturnType().isAssignableFrom(c)) {
  19.554 +                        return findSharedClassObject.invoke(null, c, true);
  19.555 +                    }
  19.556 +                } catch (Exception problem) {
  19.557 +                    throw (InstantiationException)new InstantiationException(problem.getMessage()).initCause(problem);
  19.558 +                }
  19.559 +            }
  19.560 +            return c.newInstance();
  19.561 +        }
  19.562 +    }
  19.563 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ProxyLookup.java	Sat Oct 31 15:28:13 2009 +0100
    20.3 @@ -0,0 +1,969 @@
    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 +
   20.45 +package org.openide.util.lookup;
   20.46 +
   20.47 +import java.lang.ref.Reference;
   20.48 +import java.lang.ref.WeakReference;
   20.49 +import java.util.ArrayList;
   20.50 +import java.util.Arrays;
   20.51 +import java.util.Collection;
   20.52 +import java.util.Collections;
   20.53 +import java.util.HashMap;
   20.54 +import java.util.HashSet;
   20.55 +import java.util.IdentityHashMap;
   20.56 +import java.util.Iterator;
   20.57 +import java.util.List;
   20.58 +import java.util.Map;
   20.59 +import java.util.Map.Entry;
   20.60 +import java.util.Set;
   20.61 +import java.util.concurrent.Executor;
   20.62 +import javax.swing.event.EventListenerList;
   20.63 +import org.openide.util.Lookup;
   20.64 +import org.openide.util.LookupEvent;
   20.65 +import org.openide.util.LookupListener;
   20.66 +
   20.67 +/** Implementation of lookup that can delegate to others.
   20.68 + *
   20.69 + * @author  Jaroslav Tulach
   20.70 + * @since 1.9
   20.71 + */
   20.72 +public class ProxyLookup extends Lookup {
   20.73 +    /** data representing the state of the lookup */
   20.74 +    private ImmutableInternalData data;
   20.75 +
   20.76 +    /** Create a proxy to some other lookups.
   20.77 +     * @param lookups the initial delegates
   20.78 +     */
   20.79 +    public ProxyLookup(Lookup... lookups) {
   20.80 +        data = ImmutableInternalData.EMPTY.setLookupsNoFire(lookups, true);
   20.81 +    }
   20.82 +
   20.83 +    /**
   20.84 +     * Create a lookup initially proxying to no others.
   20.85 +     * Permits serializable subclasses.
   20.86 +     * @since 3.27
   20.87 +     */
   20.88 +    protected ProxyLookup() {
   20.89 +        data = ImmutableInternalData.EMPTY;
   20.90 +    }
   20.91 +
   20.92 +    @Override
   20.93 +    public synchronized String toString() {
   20.94 +        return "ProxyLookup(class=" + getClass() + ")->" + Arrays.asList(getData().getLookups(false)); // NOI18N
   20.95 +    }
   20.96 +
   20.97 +    /** Getter for the delegates.
   20.98 +    * @return the array of lookups we delegate to
   20.99 +    * @since 1.19
  20.100 +    */
  20.101 +    protected final Lookup[] getLookups() {
  20.102 +        synchronized (ProxyLookup.this) {
  20.103 +            return getData().getLookups(true);
  20.104 +        }
  20.105 +    }
  20.106 +
  20.107 +    private Set<Lookup> identityHashSet(Collection<Lookup> current) {
  20.108 +        Map<Lookup,Void> map = new IdentityHashMap<Lookup, Void>();
  20.109 +        for (Lookup lookup : current) {
  20.110 +            map.put(lookup, null);
  20.111 +        }
  20.112 +        return map.keySet();
  20.113 +    }
  20.114 +    
  20.115 +    /**
  20.116 +     * Changes the delegates.
  20.117 +     *
  20.118 +     * @param lookups the new lookups to delegate to
  20.119 +     * @since 1.19 protected
  20.120 +     */
  20.121 +    protected final void setLookups(Lookup... lookups) {
  20.122 +        setLookups(null, lookups);
  20.123 +    }
  20.124 +    
  20.125 +    /**
  20.126 +     * Changes the delegates immediatelly, notifies the listeners in provided
  20.127 +     * executor, potentially later.
  20.128 +     *
  20.129 +     * @param lookups the new lookups to delegate to
  20.130 +     * @param notifyIn executor to deliver the notification to listeners or null
  20.131 +     * @since 7.16
  20.132 +     */
  20.133 +    protected final void setLookups(Executor notifyIn, Lookup... lookups) {
  20.134 +        Collection<Reference<R>> arr;
  20.135 +        Set<Lookup> newL;
  20.136 +        Set<Lookup> current;
  20.137 +        Lookup[] old;
  20.138 +        
  20.139 +        Map<Result,LookupListener> toRemove = new IdentityHashMap<Lookup.Result, LookupListener>();
  20.140 +        Map<Result,LookupListener> toAdd = new IdentityHashMap<Lookup.Result, LookupListener>();
  20.141 +        
  20.142 +        ImmutableInternalData orig;
  20.143 +        synchronized (ProxyLookup.this) {
  20.144 +            orig = getData();
  20.145 +            ImmutableInternalData newData = getData().setLookupsNoFire(lookups, false);
  20.146 +            if (newData == getData()) {
  20.147 +                return;
  20.148 +            }
  20.149 +            arr = setData(newData, lookups, toAdd, toRemove);
  20.150 +        }
  20.151 +        
  20.152 +        // better to do this later than in synchronized block
  20.153 +        for (Map.Entry<Result, LookupListener> e : toRemove.entrySet()) {
  20.154 +            e.getKey().removeLookupListener(e.getValue());
  20.155 +        }
  20.156 +        for (Map.Entry<Result, LookupListener> e : toAdd.entrySet()) {
  20.157 +            e.getKey().addLookupListener(e.getValue());
  20.158 +        }
  20.159 +
  20.160 +
  20.161 +        // this cannot be done from the synchronized block
  20.162 +        final ArrayList<Object> evAndListeners = new ArrayList<Object>();
  20.163 +        for (Reference<R> ref : arr) {
  20.164 +            R<?> r = ref.get();
  20.165 +            if (r != null) {
  20.166 +                r.collectFires(evAndListeners);
  20.167 +            }
  20.168 +        }
  20.169 +        
  20.170 +        class Notify implements Runnable {
  20.171 +            public void run() {
  20.172 +                Iterator it = evAndListeners.iterator();
  20.173 +                while (it.hasNext()) {
  20.174 +                    LookupEvent ev = (LookupEvent)it.next();
  20.175 +                    LookupListener l = (LookupListener)it.next();
  20.176 +                    l.resultChanged(ev);
  20.177 +                }
  20.178 +            }
  20.179 +        }
  20.180 +        Notify n = new Notify();
  20.181 +        if (notifyIn == null) {
  20.182 +            n.run();
  20.183 +        } else {
  20.184 +            notifyIn.execute(n);
  20.185 +        }
  20.186 +    }
  20.187 +
  20.188 +    /** Notifies subclasses that a query is about to be processed.
  20.189 +     * Subclasses can update its state before the actual processing
  20.190 +     * begins. It is allowed to call <code>setLookups</code> method
  20.191 +     * to change/update the set of objects the proxy delegates to.
  20.192 +     *
  20.193 +     * @param template the template of the query
  20.194 +     * @since 1.31
  20.195 +     */
  20.196 +    protected void beforeLookup(Template<?> template) {
  20.197 +    }
  20.198 +
  20.199 +    public final <T> T lookup(Class<T> clazz) {
  20.200 +        beforeLookup(new Template<T>(clazz));
  20.201 +
  20.202 +        Lookup[] tmpLkps;
  20.203 +        synchronized (ProxyLookup.this) {
  20.204 +            tmpLkps = getData().getLookups(false);
  20.205 +        }
  20.206 +
  20.207 +        for (int i = 0; i < tmpLkps.length; i++) {
  20.208 +            T o = tmpLkps[i].lookup(clazz);
  20.209 +
  20.210 +            if (o != null) {
  20.211 +                return o;
  20.212 +            }
  20.213 +        }
  20.214 +
  20.215 +        return null;
  20.216 +    }
  20.217 +
  20.218 +    @Override
  20.219 +    public final <T> Item<T> lookupItem(Template<T> template) {
  20.220 +        beforeLookup(template);
  20.221 +
  20.222 +        Lookup[] tmpLkps; 
  20.223 +        synchronized (ProxyLookup.this) {
  20.224 +            tmpLkps = getData().getLookups(false);
  20.225 +        }
  20.226 +
  20.227 +        for (int i = 0; i < tmpLkps.length; i++) {
  20.228 +            Item<T> o = tmpLkps[i].lookupItem(template);
  20.229 +
  20.230 +            if (o != null) {
  20.231 +                return o;
  20.232 +            }
  20.233 +        }
  20.234 +
  20.235 +        return null;
  20.236 +    }
  20.237 +
  20.238 +    @SuppressWarnings("unchecked")
  20.239 +    private static <T> R<T> convertResult(R r) {
  20.240 +        return (R<T>)r;
  20.241 +    }
  20.242 +
  20.243 +    public final <T> Result<T> lookup(Lookup.Template<T> template) {
  20.244 +        synchronized (ProxyLookup.this) {
  20.245 +            ImmutableInternalData[] res = { null };
  20.246 +            R<T> newR = getData().findResult(this, res, template);
  20.247 +            setData(res[0], getData().getLookups(false), null, null);
  20.248 +            return newR;
  20.249 +        }
  20.250 +    }
  20.251 +
  20.252 +    /** Unregisters a template from the has map.
  20.253 +     */
  20.254 +    private final void unregisterTemplate(Template<?> template) {
  20.255 +        synchronized (ProxyLookup.this) {
  20.256 +            ImmutableInternalData id = getData();
  20.257 +            if (id == null) {
  20.258 +                return;
  20.259 +            }
  20.260 +            setData(id.removeTemplate(this, template), getData().getLookups(false), null, null);
  20.261 +        }
  20.262 +    }
  20.263 +
  20.264 +    private ImmutableInternalData getData() {
  20.265 +        assert Thread.holdsLock(this);
  20.266 +        return data;
  20.267 +    }
  20.268 +
  20.269 +    private Collection<Reference<R>> setData(
  20.270 +        ImmutableInternalData newData, Lookup[] current, 
  20.271 +        Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
  20.272 +    ) {
  20.273 +        assert Thread.holdsLock(ProxyLookup.this);
  20.274 +        assert newData != null;
  20.275 +        
  20.276 +        ImmutableInternalData previous = this.getData();
  20.277 +        
  20.278 +        if (previous == newData) {
  20.279 +            return Collections.emptyList();
  20.280 +        }
  20.281 +
  20.282 +        if (newData.isEmpty()) {
  20.283 +            this.setData(newData);
  20.284 +            // no affected results => exit
  20.285 +            return Collections.emptyList();
  20.286 +        }
  20.287 +
  20.288 +        Collection<Reference<R>> arr = newData.references();
  20.289 +
  20.290 +        Set<Lookup> removed = identityHashSet(previous.getLookupsList());
  20.291 +        Set<Lookup> currentSet = identityHashSet(Arrays.asList(current));
  20.292 +        Set<Lookup> newL = identityHashSet(currentSet);
  20.293 +        removed.removeAll(currentSet); // current contains just those lookups that have disappeared
  20.294 +        newL.removeAll(previous.getLookupsList()); // really new lookups
  20.295 +
  20.296 +        for (Reference<R> ref : arr) {
  20.297 +            R<?> r = ref.get();
  20.298 +            if (r != null) {
  20.299 +                r.lookupChange(newData, current, previous, newL, removed, toAdd, toRemove);
  20.300 +                if (this.getData() != previous) {
  20.301 +                    // the data were changed by an re-entrant call
  20.302 +                    // skip any other change processing, as it is not needed
  20.303 +                    // anymore
  20.304 +                }
  20.305 +            }
  20.306 +        }
  20.307 +                for (Reference<R> ref : arr) {
  20.308 +            R<?> r = ref.get();
  20.309 +            if (r != null) {
  20.310 +                r.data = newData;
  20.311 +            }
  20.312 +        }
  20.313 +        this.setData(newData);
  20.314 +        return arr;
  20.315 +    }
  20.316 +
  20.317 +    private void setData(ImmutableInternalData data) {
  20.318 +        this.data = data;
  20.319 +    }
  20.320 +
  20.321 +    /** Result of a lookup request. Allows access to single object
  20.322 +     * that was found (not too useful) and also to all objects found
  20.323 +     * (more useful).
  20.324 +     */
  20.325 +    private static final class R<T> extends WaitableResult<T> {
  20.326 +        /** weak listener & result */
  20.327 +        private final WeakResult<T> weakL;
  20.328 +        
  20.329 +        /** list of listeners added */
  20.330 +        private javax.swing.event.EventListenerList listeners;
  20.331 +
  20.332 +        /** collection of Objects */
  20.333 +        private Collection[] cache;
  20.334 +
  20.335 +        
  20.336 +        /** associated lookup */
  20.337 +        private ImmutableInternalData data;
  20.338 +
  20.339 +        /** Constructor.
  20.340 +         */
  20.341 +        public R(ProxyLookup proxy, Lookup.Template<T> t) {
  20.342 +            this.weakL = new WeakResult<T>(proxy, this, t);
  20.343 +        }
  20.344 +        
  20.345 +        private ProxyLookup proxy() {
  20.346 +            return weakL.result.proxy;
  20.347 +        }
  20.348 +
  20.349 +        @SuppressWarnings("unchecked")
  20.350 +        private Result<T>[] newResults(int len) {
  20.351 +            return new Result[len];
  20.352 +        }
  20.353 +        
  20.354 +        @Override
  20.355 +        protected void finalize() {
  20.356 +            weakL.result.run();
  20.357 +        }
  20.358 +
  20.359 +        /** initializes the results
  20.360 +         */
  20.361 +        private Result<T>[] initResults() {
  20.362 +            BIG_LOOP: for (;;) {
  20.363 +                Lookup[] myLkps;
  20.364 +                ImmutableInternalData current;
  20.365 +                synchronized (proxy()) {
  20.366 +                    if (weakL.getResults() != null) {
  20.367 +                        return weakL.getResults();
  20.368 +                    }
  20.369 +                    myLkps = data.getLookups(false);
  20.370 +                    current = data;
  20.371 +                }
  20.372 +
  20.373 +                Result<T>[] arr = newResults(myLkps.length);
  20.374 +
  20.375 +                for (int i = 0; i < arr.length; i++) {
  20.376 +                    arr[i] = myLkps[i].lookup(weakL.result.template);
  20.377 +                }
  20.378 +
  20.379 +                synchronized (proxy()) {
  20.380 +                    if (current != data) {
  20.381 +                        continue;
  20.382 +                    }
  20.383 +                    
  20.384 +                    Lookup[] currentLkps = data.getLookups(false);
  20.385 +                    if (currentLkps.length != myLkps.length) {
  20.386 +                        continue BIG_LOOP;
  20.387 +                    }
  20.388 +                    for (int i = 0; i < currentLkps.length; i++) {
  20.389 +                        if (currentLkps[i] != myLkps[i]) {
  20.390 +                            continue BIG_LOOP;
  20.391 +                        }
  20.392 +                    }
  20.393 +                    
  20.394 +                    // some other thread might compute the result mean while. 
  20.395 +                    // if not finish the computation yourself
  20.396 +                    if (weakL.getResults() != null) {
  20.397 +                        return weakL.getResults();
  20.398 +                    }
  20.399 +
  20.400 +                    for (int i = 0; i < arr.length; i++) {
  20.401 +                        arr[i].addLookupListener(weakL);
  20.402 +                    }
  20.403 +
  20.404 +                    weakL.setResults(arr);
  20.405 +
  20.406 +                    return arr;
  20.407 +                }
  20.408 +            }
  20.409 +        }
  20.410 +
  20.411 +        /** Called when there is a change in the list of proxied lookups.
  20.412 +         * @param added set of added lookups
  20.413 +         * @param remove set of removed lookups
  20.414 +         * @param current array of current lookups
  20.415 +         */
  20.416 +        final void lookupChange(
  20.417 +            ImmutableInternalData newData, Lookup[] current, ImmutableInternalData oldData,
  20.418 +            Set<Lookup> added, Set<Lookup> removed,
  20.419 +            Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
  20.420 +        ) {
  20.421 +            if (weakL.getResults() == null) {
  20.422 +                // not computed yet, do not need to do anything
  20.423 +                return;
  20.424 +            }
  20.425 +
  20.426 +            Lookup[] old = oldData.getLookups(false);
  20.427 +
  20.428 +            // map (Lookup, Lookup.Result)
  20.429 +            Map<Lookup,Result<T>> map = new IdentityHashMap<Lookup,Result<T>>(old.length * 2);
  20.430 +
  20.431 +            for (int i = 0; i < old.length; i++) {
  20.432 +                if (removed.contains(old[i])) {
  20.433 +                    // removed lookup
  20.434 +                    if (toRemove != null) {
  20.435 +                        toRemove.put(weakL.getResults()[i], weakL);
  20.436 +                    }
  20.437 +                } else {
  20.438 +                    // remember the association
  20.439 +                    map.put(old[i], weakL.getResults()[i]);
  20.440 +                }
  20.441 +            }
  20.442 +
  20.443 +            Lookup.Result<T>[] arr = newResults(current.length);
  20.444 +
  20.445 +            for (int i = 0; i < current.length; i++) {
  20.446 +                if (added.contains(current[i])) {
  20.447 +                    // new lookup
  20.448 +                    arr[i] = current[i].lookup(weakL.result.template);
  20.449 +                    if (toAdd != null) {
  20.450 +                        toAdd.put(arr[i], weakL);
  20.451 +                    }
  20.452 +                } else {
  20.453 +                    // old lookup
  20.454 +                    arr[i] = map.get(current[i]);
  20.455 +
  20.456 +                    if (arr[i] == null) {
  20.457 +                        // assert
  20.458 +                        throw new IllegalStateException();
  20.459 +                    }
  20.460 +                }
  20.461 +            }
  20.462 +
  20.463 +            // remember the new results
  20.464 +            weakL.setResults(arr);
  20.465 +        }
  20.466 +
  20.467 +        /** Just delegates.
  20.468 +         */
  20.469 +        public void addLookupListener(LookupListener l) {
  20.470 +            synchronized (proxy()) {
  20.471 +                if (listeners == null) {
  20.472 +                    listeners = new EventListenerList();
  20.473 +                }
  20.474 +            }
  20.475 +
  20.476 +            listeners.add(LookupListener.class, l);
  20.477 +        }
  20.478 +
  20.479 +        /** Just delegates.
  20.480 +         */
  20.481 +        public void removeLookupListener(LookupListener l) {
  20.482 +            if (listeners != null) {
  20.483 +                listeners.remove(LookupListener.class, l);
  20.484 +            }
  20.485 +        }
  20.486 +
  20.487 +        /** Access to all instances in the result.
  20.488 +         * @return collection of all instances
  20.489 +         */
  20.490 +        @SuppressWarnings("unchecked")
  20.491 +        public java.util.Collection<T> allInstances() {
  20.492 +            return computeResult(0);
  20.493 +        }
  20.494 +
  20.495 +        /** Classes of all results. Set of the most concreate classes
  20.496 +         * that are registered in the system.
  20.497 +         * @return set of Class objects
  20.498 +         */
  20.499 +        @SuppressWarnings("unchecked")
  20.500 +        @Override
  20.501 +        public java.util.Set<Class<? extends T>> allClasses() {
  20.502 +            return (java.util.Set<Class<? extends T>>) computeResult(1);
  20.503 +        }
  20.504 +
  20.505 +        /** All registered items. The collection of all pairs of
  20.506 +         * ii and their classes.
  20.507 +         * @return collection of Lookup.Item
  20.508 +         */
  20.509 +        @SuppressWarnings("unchecked")
  20.510 +        @Override
  20.511 +        public java.util.Collection<? extends Item<T>> allItems() {
  20.512 +            return computeResult(2);
  20.513 +        }
  20.514 +
  20.515 +        /** Computes results from proxied lookups.
  20.516 +         * @param indexToCache 0 = allInstances, 1 = allClasses, 2 = allItems
  20.517 +         * @return the collection or set of the objects
  20.518 +         */
  20.519 +        private java.util.Collection computeResult(int indexToCache) {
  20.520 +            // results to use
  20.521 +            Lookup.Result<T>[] arr = myBeforeLookup();
  20.522 +
  20.523 +            // if the call to beforeLookup resulted in deletion of caches
  20.524 +            synchronized (proxy()) {
  20.525 +                if (getCache() != null) {
  20.526 +                    Collection result = getCache()[indexToCache];
  20.527 +                    if (result != null) {
  20.528 +                        return result;
  20.529 +                    }
  20.530 +                }
  20.531 +            }
  20.532 +
  20.533 +            // initialize the collection to hold result
  20.534 +            Collection<Object> compute;
  20.535 +            Collection<Object> ret;
  20.536 +
  20.537 +            if (indexToCache == 1) {
  20.538 +                HashSet<Object> s = new HashSet<Object>();
  20.539 +                compute = s;
  20.540 +                ret = Collections.unmodifiableSet(s);
  20.541 +            } else {
  20.542 +                List<Object> l = new ArrayList<Object>(arr.length * 2);
  20.543 +                compute = l;
  20.544 +                ret = Collections.unmodifiableList(l);
  20.545 +            }
  20.546 +
  20.547 +            // fill the collection
  20.548 +            for (int i = 0; i < arr.length; i++) {
  20.549 +                switch (indexToCache) {
  20.550 +                case 0:
  20.551 +                    compute.addAll(arr[i].allInstances());
  20.552 +                    break;
  20.553 +                case 1:
  20.554 +                    compute.addAll(arr[i].allClasses());
  20.555 +                    break;
  20.556 +                case 2:
  20.557 +                    compute.addAll(arr[i].allItems());
  20.558 +                    break;
  20.559 +                default:
  20.560 +                    assert false : "Wrong index: " + indexToCache;
  20.561 +                }
  20.562 +            }
  20.563 +            
  20.564 +            
  20.565 +
  20.566 +            synchronized (proxy()) {
  20.567 +                if (getCache() == null) {
  20.568 +                    // initialize the cache to indicate this result is in use
  20.569 +                    setCache(new Collection[3]);
  20.570 +                }
  20.571 +                
  20.572 +                if (arr == weakL.getResults()) {
  20.573 +                    // updates the results, if the results have not been
  20.574 +                    // changed during the computation of allInstances
  20.575 +                    getCache()[indexToCache] = ret;
  20.576 +                }
  20.577 +            }
  20.578 +
  20.579 +            return ret;
  20.580 +        }
  20.581 +
  20.582 +        /** When the result changes, fire the event.
  20.583 +         */
  20.584 +        public void resultChanged(LookupEvent ev) {
  20.585 +            collectFires(null);
  20.586 +        }
  20.587 +        
  20.588 +        protected void collectFires(Collection<Object> evAndListeners) {
  20.589 +            // clear cached instances
  20.590 +            Collection oldItems;
  20.591 +            Collection oldInstances;
  20.592 +            synchronized (proxy()) {
  20.593 +                if (getCache() == null) {
  20.594 +                    // nobody queried the result yet
  20.595 +                    return;
  20.596 +                }
  20.597 +                oldInstances = getCache()[0];
  20.598 +                oldItems = getCache()[2];
  20.599 +                
  20.600 +
  20.601 +                if (listeners == null || listeners.getListenerCount() == 0) {
  20.602 +                    // clear the cache
  20.603 +                    setCache(new Collection[3]);
  20.604 +                    return;
  20.605 +                }
  20.606 +                
  20.607 +                // ignore events if they arrive as a result of call to allItems
  20.608 +                // or allInstances, bellow...
  20.609 +                setCache(null);
  20.610 +            }
  20.611 +
  20.612 +            boolean modified = true;
  20.613 +
  20.614 +            if (oldItems != null) {
  20.615 +                Collection newItems = allItems();
  20.616 +                if (oldItems.equals(newItems)) {
  20.617 +                    modified = false;
  20.618 +                }
  20.619 +            } else {
  20.620 +                if (oldInstances != null) {
  20.621 +                    Collection newInstances = allInstances();
  20.622 +                    if (oldInstances.equals(newInstances)) {
  20.623 +                        modified = false;
  20.624 +                    }
  20.625 +                } else {
  20.626 +                    synchronized (proxy()) {
  20.627 +                        if (getCache() == null) {
  20.628 +                            // we have to initialize the cache
  20.629 +                            // to show that the result has been initialized
  20.630 +                            setCache(new Collection[3]);
  20.631 +                        }
  20.632 +                    }
  20.633 +                }
  20.634 +            }
  20.635 +            
  20.636 +            if (modified) {
  20.637 +                LookupEvent ev = new LookupEvent(this);
  20.638 +                AbstractLookup.notifyListeners(listeners.getListenerList(), ev, evAndListeners);
  20.639 +            }
  20.640 +        }
  20.641 +
  20.642 +        /** Implementation of my before lookup.
  20.643 +         * @return results to work on.
  20.644 +         */
  20.645 +        private Lookup.Result<T>[] myBeforeLookup() {
  20.646 +            Template<T> template = weakL.result.template;
  20.647 +            
  20.648 +            proxy().beforeLookup(template);
  20.649 +
  20.650 +            Lookup.Result<T>[] arr = initResults();
  20.651 +
  20.652 +            // invoke update on the results
  20.653 +            for (int i = 0; i < arr.length; i++) {
  20.654 +                if (arr[i] instanceof WaitableResult) {
  20.655 +                    WaitableResult w = (WaitableResult) arr[i];
  20.656 +                    w.beforeLookup(template);
  20.657 +                }
  20.658 +            }
  20.659 +
  20.660 +            return arr;
  20.661 +        }
  20.662 +
  20.663 +        /** Used by proxy results to synchronize before lookup.
  20.664 +         */
  20.665 +        protected void beforeLookup(Lookup.Template t) {
  20.666 +            if (t.getType() == weakL.result.template.getType()) {
  20.667 +                myBeforeLookup();
  20.668 +            }
  20.669 +        }
  20.670 +
  20.671 +        private Collection[] getCache() {
  20.672 +            return cache;
  20.673 +        }
  20.674 +
  20.675 +        private void setCache(Collection[] cache) {
  20.676 +            assert Thread.holdsLock(proxy());
  20.677 +            this.cache = cache;
  20.678 +        }
  20.679 +    }
  20.680 +    private static final class WeakRef<T> extends WeakReference<R> implements Runnable {
  20.681 +        final WeakResult<T> result;
  20.682 +        final ProxyLookup proxy;
  20.683 +        final Template<T> template;
  20.684 +        
  20.685 +        public WeakRef(R r, WeakResult<T> result, ProxyLookup proxy, Template<T> template) {
  20.686 +            super(r);
  20.687 +            this.result = result;
  20.688 +            this.template = template;
  20.689 +            this.proxy = proxy;
  20.690 +        }
  20.691 +
  20.692 +        public void run() {
  20.693 +            result.removeListeners();
  20.694 +            proxy.unregisterTemplate(template);
  20.695 +        }
  20.696 +    }
  20.697 +    
  20.698 +    
  20.699 +    private static final class WeakResult<T> extends WaitableResult<T> implements LookupListener, Runnable {
  20.700 +        /** all results */
  20.701 +        private Lookup.Result<T>[] results;
  20.702 +        private final WeakRef<T> result;
  20.703 +        
  20.704 +        public WeakResult(ProxyLookup proxy, R r, Template<T> t) {
  20.705 +            this.result = new WeakRef<T>(r, this, proxy, t);
  20.706 +        }
  20.707 +        
  20.708 +        final void removeListeners() {
  20.709 +            Lookup.Result<T>[] arr = this.getResults();
  20.710 +            if (arr == null) {
  20.711 +                return;
  20.712 +            }
  20.713 +
  20.714 +            for(int i = 0; i < arr.length; i++) {
  20.715 +                arr[i].removeLookupListener(this);
  20.716 +            }
  20.717 +        }
  20.718 +
  20.719 +        protected void beforeLookup(Lookup.Template t) {
  20.720 +            R r = result.get();
  20.721 +            if (r != null) {
  20.722 +                r.beforeLookup(t);
  20.723 +            } else {
  20.724 +                removeListeners();
  20.725 +            }
  20.726 +        }
  20.727 +
  20.728 +        protected void collectFires(Collection<Object> evAndListeners) {
  20.729 +            R<?> r = result.get();
  20.730 +            if (r != null) {
  20.731 +                r.collectFires(evAndListeners);
  20.732 +            } else {
  20.733 +                removeListeners();
  20.734 +            }
  20.735 +        }
  20.736 +
  20.737 +        public void addLookupListener(LookupListener l) {
  20.738 +            assert false;
  20.739 +        }
  20.740 +
  20.741 +        public void removeLookupListener(LookupListener l) {
  20.742 +            assert false;
  20.743 +        }
  20.744 +
  20.745 +        public Collection<T> allInstances() {
  20.746 +            assert false;
  20.747 +            return null;
  20.748 +        }
  20.749 +
  20.750 +        public void resultChanged(LookupEvent ev) {
  20.751 +            R r = result.get();
  20.752 +            if (r != null) {
  20.753 +                r.resultChanged(ev);
  20.754 +            } else {
  20.755 +                removeListeners();
  20.756 +            }
  20.757 +        }
  20.758 +
  20.759 +        @Override
  20.760 +        public Collection<? extends Item<T>> allItems() {
  20.761 +            assert false;
  20.762 +            return null;
  20.763 +        }
  20.764 +
  20.765 +        @Override
  20.766 +        public Set<Class<? extends T>> allClasses() {
  20.767 +            assert false;
  20.768 +            return null;
  20.769 +        }
  20.770 +
  20.771 +        public void run() {
  20.772 +            removeListeners();
  20.773 +        }
  20.774 +
  20.775 +        private Lookup.Result<T>[] getResults() {
  20.776 +            return results;
  20.777 +        }
  20.778 +
  20.779 +        private void setResults(Lookup.Result<T>[] results) {
  20.780 +            this.results = results;
  20.781 +        }
  20.782 +    } // end of WeakResult
  20.783 +    
  20.784 +    static abstract class ImmutableInternalData extends Object {
  20.785 +        static final ImmutableInternalData EMPTY = new EmptyInternalData();
  20.786 +        static final Lookup[] EMPTY_ARR = new Lookup[0];
  20.787 +
  20.788 +        
  20.789 +        protected ImmutableInternalData() {
  20.790 +        }
  20.791 +        
  20.792 +        public static ImmutableInternalData create(Object lkp, Map<Template, Reference<R>> results) {
  20.793 +            if (results.size() == 0 && lkp == EMPTY_ARR) {
  20.794 +                return EMPTY;
  20.795 +            }
  20.796 +            if (results.size() == 1) {
  20.797 +                Entry<Template,Reference<R>> e = results.entrySet().iterator().next();
  20.798 +                return new SingleInternalData(lkp, e.getKey(), e.getValue());
  20.799 +            }
  20.800 +            
  20.801 +            return new RealInternalData(lkp, results);
  20.802 +        }
  20.803 +
  20.804 +        protected abstract boolean isEmpty();
  20.805 +        protected abstract Map<Template, Reference<R>> getResults();
  20.806 +        protected abstract Object getRawLookups();
  20.807 +
  20.808 +        final Collection<Reference<R>> references() {
  20.809 +            return getResults().values();
  20.810 +        }
  20.811 +        
  20.812 +        final <T> ImmutableInternalData removeTemplate(ProxyLookup proxy, Template<T> template) {
  20.813 +            if (getResults().containsKey(template)) {
  20.814 +                HashMap<Template,Reference<R>> c = new HashMap<Template, Reference<ProxyLookup.R>>(getResults());
  20.815 +                Reference<R> ref = c.remove(template);
  20.816 +                if (ref != null && ref.get() != null) {
  20.817 +                    // seems like there is a reference to a result for this template
  20.818 +                    // thta is still alive
  20.819 +                    return this;
  20.820 +                }
  20.821 +                return create(getRawLookups(), c);
  20.822 +            } else {
  20.823 +                return this;
  20.824 +            }
  20.825 +        }
  20.826 +        
  20.827 +        <T> R<T> findResult(ProxyLookup proxy, ImmutableInternalData[] newData, Template<T> template) {
  20.828 +            assert Thread.holdsLock(proxy);
  20.829 +            
  20.830 +            Map<Template,Reference<R>> map = getResults();
  20.831 +            
  20.832 +            Reference<R> ref = map.get(template);
  20.833 +            R r = (ref == null) ? null : ref.get();
  20.834 +
  20.835 +            if (r != null) {
  20.836 +                newData[0] = this;
  20.837 +                return convertResult(r);
  20.838 +            }
  20.839 +            
  20.840 +            HashMap<Template, Reference<R>> res = new HashMap<Template, Reference<R>>(map);
  20.841 +            R<T> newR = new R<T>(proxy, template);
  20.842 +            res.put(template, new java.lang.ref.SoftReference<R>(newR));
  20.843 +            newR.data = newData[0] = create(getRawLookups(), res);
  20.844 +            return newR;
  20.845 +        }
  20.846 +        final ImmutableInternalData setLookupsNoFire(Lookup[] lookups, boolean skipCheck) {
  20.847 +            Object l;
  20.848 +            
  20.849 +            if (!skipCheck) {
  20.850 +                Lookup[] previous = getLookups(false);
  20.851 +                if (previous == lookups) {
  20.852 +                    return this;
  20.853 +                }
  20.854 +            
  20.855 +                if (previous.length == lookups.length) {
  20.856 +                    int same = 0;
  20.857 +                    for (int i = 0; i < previous.length; i++) {
  20.858 +                        if (lookups[i] != previous[i]) {
  20.859 +                            break;
  20.860 +                        }
  20.861 +                        same++;
  20.862 +                    }
  20.863 +                    if (same == previous.length) {
  20.864 +                        return this;
  20.865 +                    }
  20.866 +                }
  20.867 +            }
  20.868 +            
  20.869 +            if (lookups.length == 1) {
  20.870 +                l = lookups[0];
  20.871 +                assert l != null : "Cannot assign null delegate";
  20.872 +            } else {
  20.873 +                if (lookups.length == 0) {
  20.874 +                    l = EMPTY_ARR;
  20.875 +                } else {
  20.876 +                    l = lookups.clone();
  20.877 +                }
  20.878 +            }
  20.879 +            
  20.880 +            if (isEmpty() && l == EMPTY_ARR) {
  20.881 +                return this;
  20.882 +            }
  20.883 +            
  20.884 +            return create(l, getResults());
  20.885 +        }
  20.886 +        final Lookup[] getLookups(boolean clone) {
  20.887 +            Object l = this.getRawLookups();
  20.888 +            if (l instanceof Lookup) {
  20.889 +                return new Lookup[] { (Lookup)l };
  20.890 +            } else {
  20.891 +                Lookup[] arr = (Lookup[])l;
  20.892 +                if (clone) {
  20.893 +                    arr = arr.clone();
  20.894 +                }
  20.895 +                return arr;
  20.896 +            }
  20.897 +        }
  20.898 +        final List<Lookup> getLookupsList() {
  20.899 +            return Arrays.asList(getLookups(false));            
  20.900 +        }
  20.901 +
  20.902 +    } // end of ImmutableInternalData
  20.903 +    
  20.904 +    private static final class SingleInternalData extends ImmutableInternalData {
  20.905 +        /** lookups to delegate to (either Lookup or array of Lookups) */
  20.906 +        private final Object lookups;
  20.907 +        private final Template template;
  20.908 +        private final Reference<ProxyLookup.R> result;
  20.909 +                
  20.910 +        public SingleInternalData(Object lookups, Template<?> template, Reference<ProxyLookup.R> result) {
  20.911 +            this.lookups = lookups;
  20.912 +            this.template = template;
  20.913 +            this.result = result;
  20.914 +        }
  20.915 +
  20.916 +        protected final boolean isEmpty() {
  20.917 +            return false;
  20.918 +        }
  20.919 +
  20.920 +        protected Map<Template, Reference<R>> getResults() {
  20.921 +            return Collections.singletonMap(template, result);
  20.922 +        }
  20.923 +        
  20.924 +        protected Object getRawLookups() {
  20.925 +            return lookups;
  20.926 +        }
  20.927 +    }
  20.928 +    private static final class RealInternalData extends ImmutableInternalData {
  20.929 +        /** lookups to delegate to (either Lookup or array of Lookups) */
  20.930 +        private final Object lookups;
  20.931 +
  20.932 +        /** map of templates to currently active results */
  20.933 +        private final Map<Template,Reference<R>> results;
  20.934 +
  20.935 +        public RealInternalData(Object lookups, Map<Template, Reference<ProxyLookup.R>> results) {
  20.936 +            this.results = results;
  20.937 +            this.lookups = lookups;
  20.938 +        }
  20.939 +
  20.940 +        protected final boolean isEmpty() {
  20.941 +            return false;
  20.942 +        }
  20.943 +
  20.944 +        protected Map<Template, Reference<R>> getResults() {
  20.945 +            boolean strict = false;
  20.946 +            assert strict = true;
  20.947 +            return strict ? Collections.unmodifiableMap(results) : results;
  20.948 +        }
  20.949 +        
  20.950 +        protected Object getRawLookups() {
  20.951 +            return lookups;
  20.952 +        }
  20.953 +    }
  20.954 +    
  20.955 +    private static final class EmptyInternalData extends ImmutableInternalData {
  20.956 +        EmptyInternalData() {
  20.957 +        }
  20.958 +
  20.959 +        protected final boolean isEmpty() {
  20.960 +            return true;
  20.961 +        }
  20.962 +
  20.963 +        protected Map<Template, Reference<R>> getResults() {
  20.964 +            return Collections.emptyMap();
  20.965 +        }
  20.966 +
  20.967 +        @Override
  20.968 +        protected Object getRawLookups() {
  20.969 +            return EMPTY_ARR;
  20.970 +        }
  20.971 +    } // end of EmptyInternalData
  20.972 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ServiceProvider.java	Sat Oct 31 15:28:13 2009 +0100
    21.3 @@ -0,0 +1,102 @@
    21.4 +/*
    21.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    21.6 + *
    21.7 + * Copyright 2008 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 + * If you wish your version of this file to be governed by only the CDDL
   21.28 + * or only the GPL Version 2, indicate your decision by adding
   21.29 + * "[Contributor] elects to include this software in this distribution
   21.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   21.31 + * single choice of license, a recipient has the option to distribute
   21.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   21.33 + * to extend the choice of license to its licensees as provided above.
   21.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   21.35 + * Version 2 license, then the option applies only if the new code is
   21.36 + * made subject to such option by the copyright holder.
   21.37 + *
   21.38 + * Contributor(s):
   21.39 + *
   21.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   21.41 + */
   21.42 +
   21.43 +package org.openide.util.lookup;
   21.44 +
   21.45 +import java.lang.annotation.ElementType;
   21.46 +import java.lang.annotation.Retention;
   21.47 +import java.lang.annotation.RetentionPolicy;
   21.48 +import java.lang.annotation.Target;
   21.49 +import org.openide.util.Lookup;
   21.50 +
   21.51 +/**
   21.52 + * Declarative registration of a singleton service provider.
   21.53 + * By marking an implementation class with this annotation,
   21.54 + * you automatically register that implementation, normally in {@link Lookup#getDefault}.
   21.55 + * The class must be public and have a public no-argument constructor.
   21.56 + * <p>Example of usage:
   21.57 + * <pre>
   21.58 + * package my.module;
   21.59 + * import org.netbeans.spi.whatever.Thing;
   21.60 + * import org.openide.util.lookup.ServiceProvider;
   21.61 + * &#64;ServiceProvider(service=Thing.class)
   21.62 + * public class MyThing implements Thing {...}
   21.63 + * </pre>
   21.64 + * <p>would result in a resource file <code>META-INF/services/org.netbeans.spi.whatever.Thing</code>
   21.65 + * containing the single line of text: <code>my.module.MyThing</code>
   21.66 + * @see Lookups#metaInfServices(ClassLoader)
   21.67 + * @since org.openide.util 7.20
   21.68 + */
   21.69 +@Retention(RetentionPolicy.SOURCE)
   21.70 +@Target(ElementType.TYPE)
   21.71 +public @interface ServiceProvider {
   21.72 +
   21.73 +    /**
   21.74 +     * The interface (or abstract class) to register this implementation under.
   21.75 +     * It is an error if the implementation class is not in fact assignable to the interface.
   21.76 +     * <p>If you need to register one class under multiple interfaces, use {@link ServiceProviders}.
   21.77 +     * <p>Requests to look up the specified interface should result in this implementation.
   21.78 +     * Requests for any other types may or may not result in this implementation even if the
   21.79 +     * implementation is assignable to those types.
   21.80 +     */
   21.81 +    Class<?> service();
   21.82 +
   21.83 +    /**
   21.84 +     * An optional position in which to register this service relative to others.
   21.85 +     * Lower-numbered services are returned in the lookup result first.
   21.86 +     * Services with no specified position are returned last.
   21.87 +     */
   21.88 +    int position() default Integer.MAX_VALUE;
   21.89 +
   21.90 +    /**
   21.91 +     * An optional list of implementations (given as fully-qualified class names) which this implementation supersedes.
   21.92 +     * If specified, those implementations will not be loaded even if they were registered.
   21.93 +     * Useful on occasion to cancel a generic implementation and replace it with a more advanced one.
   21.94 +     */
   21.95 +    String[] supersedes() default {};
   21.96 +
   21.97 +    /**
   21.98 +     * An optional path to register this implementation in.
   21.99 +     * For example, <code>Projects/sometype/Nodes</code> could be used.
  21.100 +     * This style of registration would be recognized by {@link Lookups#forPath}
  21.101 +     * rather than {@link Lookup#getDefault}.
  21.102 +     */
  21.103 +    String path() default "";
  21.104 +
  21.105 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/ServiceProviders.java	Sat Oct 31 15:28:13 2009 +0100
    22.3 @@ -0,0 +1,60 @@
    22.4 +/*
    22.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    22.6 + *
    22.7 + * Copyright 2008 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 + * If you wish your version of this file to be governed by only the CDDL
   22.28 + * or only the GPL Version 2, indicate your decision by adding
   22.29 + * "[Contributor] elects to include this software in this distribution
   22.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   22.31 + * single choice of license, a recipient has the option to distribute
   22.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   22.33 + * to extend the choice of license to its licensees as provided above.
   22.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   22.35 + * Version 2 license, then the option applies only if the new code is
   22.36 + * made subject to such option by the copyright holder.
   22.37 + *
   22.38 + * Contributor(s):
   22.39 + *
   22.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   22.41 + */
   22.42 +
   22.43 +package org.openide.util.lookup;
   22.44 +
   22.45 +import java.lang.annotation.ElementType;
   22.46 +import java.lang.annotation.Retention;
   22.47 +import java.lang.annotation.RetentionPolicy;
   22.48 +import java.lang.annotation.Target;
   22.49 +
   22.50 +/**
   22.51 + * Similar to {@link ServiceProvider} but permits multiple registrations of one class.
   22.52 + * @since org.openide.util 7.20
   22.53 + */
   22.54 +@Retention(RetentionPolicy.SOURCE)
   22.55 +@Target(ElementType.TYPE)
   22.56 +public @interface ServiceProviders {
   22.57 +
   22.58 +    /**
   22.59 +     * List of service provider registrations.
   22.60 +     */
   22.61 +    ServiceProvider[] value();
   22.62 +
   22.63 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/SimpleLookup.java	Sat Oct 31 15:28:13 2009 +0100
    23.3 @@ -0,0 +1,250 @@
    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-2006 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 +package org.openide.util.lookup;
   23.45 +
   23.46 +import org.openide.util.Lookup;
   23.47 +import org.openide.util.LookupListener;
   23.48 +
   23.49 +import java.util.*;
   23.50 +
   23.51 +
   23.52 +/**
   23.53 + * Simple lookup implementation. It can be used to create temporary lookups
   23.54 + * that do not change over time. The result stores references to all objects
   23.55 + * passed in the constructor. Those objecst are the only ones returned as
   23.56 + * result.
   23.57 + * @author David Strupl
   23.58 + */
   23.59 +class SimpleLookup extends org.openide.util.Lookup {
   23.60 +    /** This variable is initialized in constructor and thus null
   23.61 +     * value is not allowed as its value. */
   23.62 +    private Collection<Item<?>> allItems;
   23.63 +
   23.64 +    /**
   23.65 +     * Creates new Result object with supplied instances parameter.
   23.66 +     * @param instances to be used to return from the lookup
   23.67 +     */
   23.68 +    SimpleLookup(Collection<Object> instances) {
   23.69 +        allItems = new ArrayList<Item<?>>(instances.size());
   23.70 +
   23.71 +        for (Iterator i = instances.iterator(); i.hasNext();) {
   23.72 +            allItems.add(new InstanceContent.SimpleItem<Object>(i.next()));
   23.73 +        }
   23.74 +    }
   23.75 +
   23.76 +    <T,R> SimpleLookup(Collection<T> keys, InstanceContent.Convertor<? super T,R> conv) {
   23.77 +        allItems = new ArrayList<Item<?>>(keys.size());
   23.78 +
   23.79 +        for (T item : keys) {
   23.80 +            allItems.add(new InstanceContent.ConvertingItem<T,R>(item, conv));
   23.81 +        }
   23.82 +    }
   23.83 +
   23.84 +    public String toString() {
   23.85 +        return "SimpleLookup" + lookup(new Template<Object>(Object.class)).allInstances();
   23.86 +    }
   23.87 +
   23.88 +    public <T> Result<T> lookup(Template<T> template) {
   23.89 +        if (template == null) {
   23.90 +            throw new NullPointerException();
   23.91 +        }
   23.92 +
   23.93 +        return new SimpleResult<T>(template);
   23.94 +    }
   23.95 +
   23.96 +    public <T> T lookup(Class<T> clazz) {
   23.97 +        for (Iterator i = allItems.iterator(); i.hasNext();) {
   23.98 +            Object o = i.next();
   23.99 +
  23.100 +            if (o instanceof AbstractLookup.Pair) {
  23.101 +                AbstractLookup.Pair<?> p = (AbstractLookup.Pair<?>)o;
  23.102 +                if (p.instanceOf(clazz)) {
  23.103 +                    Object ret = p.getInstance();
  23.104 +                    if (clazz.isInstance(ret)) {
  23.105 +                        return clazz.cast(ret);
  23.106 +                    }
  23.107 +                }
  23.108 +            }
  23.109 +        }
  23.110 +        return null;
  23.111 +    }
  23.112 +
  23.113 +    /** A method that defines matching between Item and Template.
  23.114 +     * @param item the item to match
  23.115 +     * @return true if item matches the template requirements, false if not
  23.116 +     */
  23.117 +    private static boolean matches(Template<?> t, AbstractLookup.Pair<?> item) {
  23.118 +        if (!AbstractLookup.matches(t, item, true)) {
  23.119 +            return false;
  23.120 +        }
  23.121 +
  23.122 +        Class<?> type = t.getType();
  23.123 +
  23.124 +        if ((type != null) && !type.isAssignableFrom(item.getType())) {
  23.125 +            return false;
  23.126 +        }
  23.127 +
  23.128 +        return true;
  23.129 +    }
  23.130 +
  23.131 +    /**
  23.132 +     * Result used in SimpleLookup. It holds a reference to the collection
  23.133 +     * passed in constructor. As the contents of this lookup result never
  23.134 +     * changes the addLookupListener and removeLookupListener are empty.
  23.135 +     */
  23.136 +    private class SimpleResult<T> extends Lookup.Result<T> {
  23.137 +        /** can be null and is initialized lazily */
  23.138 +        private Set<Class<? extends T>> classes;
  23.139 +
  23.140 +        /** can be null and is initialized lazily */
  23.141 +        private Collection<? extends Item<T>> items;
  23.142 +
  23.143 +        /** Template used for this result. It is never null.*/
  23.144 +        private Template<T> template;
  23.145 +
  23.146 +        /** can be null and is initialized lazily */
  23.147 +        private Collection<T> results;
  23.148 +
  23.149 +        /** Just remembers the supplied argument in variable template.*/
  23.150 +        SimpleResult(Template<T> template) {
  23.151 +            this.template = template;
  23.152 +        }
  23.153 +
  23.154 +        /**
  23.155 +         * Intentionally does nothing because the lookup does not change
  23.156 +         * and no notification is needed.
  23.157 +         */
  23.158 +        public void addLookupListener(LookupListener l) {
  23.159 +        }
  23.160 +
  23.161 +        /**
  23.162 +         * Intentionally does nothing because the lookup does not change
  23.163 +         * and no notification is needed.
  23.164 +         */
  23.165 +        public void removeLookupListener(LookupListener l) {
  23.166 +        }
  23.167 +
  23.168 +        /**
  23.169 +         * Lazy initializes the results collection. Uses a call to allItems
  23.170 +         * to obtain the instances.
  23.171 +         */
  23.172 +        public java.util.Collection<? extends T> allInstances() {
  23.173 +            synchronized (this) {
  23.174 +                if (results != null) {
  23.175 +                    return results;
  23.176 +                }
  23.177 +            }
  23.178 +
  23.179 +
  23.180 +            Collection<T> res = new ArrayList<T>(allItems.size());
  23.181 +
  23.182 +            for (Item<T> item : allItems()) {
  23.183 +                res.add(item.getInstance());
  23.184 +            }
  23.185 +
  23.186 +            synchronized (this) {
  23.187 +                results = Collections.unmodifiableCollection(res);
  23.188 +            }
  23.189 +
  23.190 +            return results;
  23.191 +        }
  23.192 +
  23.193 +        /**
  23.194 +         * Lazy initializes variable classes. Uses a call to allItems to
  23.195 +         * compute the result.
  23.196 +         */
  23.197 +        public Set<Class<? extends T>> allClasses() {
  23.198 +            synchronized (this) {
  23.199 +                if (classes != null) {
  23.200 +                    return classes;
  23.201 +                }
  23.202 +            }
  23.203 +
  23.204 +            Set<Class<? extends T>> res = new HashSet<Class<? extends T>>();
  23.205 +
  23.206 +            for (Item<T> item : allItems()) {
  23.207 +                res.add(item.getType());
  23.208 +            }
  23.209 +
  23.210 +            synchronized (this) {
  23.211 +                classes = Collections.unmodifiableSet(res);
  23.212 +            }
  23.213 +
  23.214 +            return classes;
  23.215 +        }
  23.216 +
  23.217 +        /**
  23.218 +         * Lazy initializes variable items. Creates an item for each
  23.219 +         * element in the instances collection. It puts either SimpleItem
  23.220 +         * or ConvertingItem to the collection.
  23.221 +         */
  23.222 +        public Collection<? extends Item<T>> allItems() {
  23.223 +            synchronized (this) {
  23.224 +                if (items != null) {
  23.225 +                    return items;
  23.226 +                }
  23.227 +            }
  23.228 +
  23.229 +            Collection<Item<T>> res = new ArrayList<Item<T>>(allItems.size());
  23.230 +
  23.231 +            for (Iterator<Item<?>> i = allItems.iterator(); i.hasNext();) {
  23.232 +                Item<?> o = i.next();
  23.233 +
  23.234 +                if (o instanceof AbstractLookup.Pair) {
  23.235 +                    if (matches(template, (AbstractLookup.Pair) o)) {
  23.236 +                        res.add(cast(o));
  23.237 +                    }
  23.238 +                }
  23.239 +            }
  23.240 +
  23.241 +            synchronized (this) {
  23.242 +                items = Collections.unmodifiableCollection(res);
  23.243 +            }
  23.244 +
  23.245 +            return items;
  23.246 +        }
  23.247 +
  23.248 +        @SuppressWarnings("unchecked")
  23.249 +        private Item<T> cast(Item<?> i) {
  23.250 +            return (Item<T>)i;
  23.251 +        }
  23.252 +    }
  23.253 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/SimpleProxyLookup.java	Sat Oct 31 15:28:13 2009 +0100
    24.3 @@ -0,0 +1,359 @@
    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 +package org.openide.util.lookup;
   24.45 +
   24.46 +import java.lang.ref.Reference;
   24.47 +import java.lang.ref.WeakReference;
   24.48 +import org.openide.util.Lookup;
   24.49 +import org.openide.util.LookupEvent;
   24.50 +import org.openide.util.LookupListener;
   24.51 +
   24.52 +import java.util.*;
   24.53 +
   24.54 +
   24.55 +/**
   24.56 + * Simple proxy lookup. Keeps reference to a lookup it delegates to and
   24.57 + * forwards all requests.
   24.58 + *
   24.59 + * @author Jaroslav Tulach
   24.60 + */
   24.61 +final class SimpleProxyLookup extends org.openide.util.Lookup {
   24.62 +    /** the provider to check for the status */
   24.63 +    private Provider provider;
   24.64 +
   24.65 +    /** the lookup we currently delegate to */
   24.66 +    private Lookup delegate;
   24.67 +
   24.68 +    /** map of all templates to Reference (results) associated to this lookup */
   24.69 +    private WeakHashMap<Template<?>,Reference<ProxyResult<?>>> results;
   24.70 +
   24.71 +    /**
   24.72 +     * @param provider provider to delegate to
   24.73 +     */
   24.74 +    SimpleProxyLookup(Provider provider) {
   24.75 +        this.provider = provider;
   24.76 +    }
   24.77 +
   24.78 +    /** Checks whether we still delegate to the same lookup */
   24.79 +    private Lookup checkLookup() {
   24.80 +        Lookup l = provider.getLookup();
   24.81 +
   24.82 +        // iterator over Reference (ProxyResult)
   24.83 +        Iterator<Reference<ProxyResult<?>>> toCheck = null;
   24.84 +
   24.85 +        synchronized (this) {
   24.86 +            if (l != delegate) {
   24.87 +                this.delegate = l;
   24.88 +
   24.89 +                if (results != null) {
   24.90 +                    toCheck = new ArrayList<Reference<ProxyResult<?>>>(results.values()).iterator();
   24.91 +                }
   24.92 +            }
   24.93 +        }
   24.94 +
   24.95 +        if (toCheck != null) {
   24.96 +            // update
   24.97 +            ArrayList<Object> evAndListeners = new ArrayList<Object>();
   24.98 +            for (Iterator<Reference<ProxyResult<?>>> it = toCheck; it.hasNext(); ) {
   24.99 +                java.lang.ref.Reference<ProxyResult<?>> ref = it.next();
  24.100 +                if (ref == null) {
  24.101 +                    continue;
  24.102 +                }
  24.103 +
  24.104 +                ProxyResult<?> p = ref.get();
  24.105 +
  24.106 +                if (p != null && p.updateLookup(l)) {
  24.107 +                    p.collectFires(evAndListeners);
  24.108 +                }
  24.109 +            }
  24.110 +            
  24.111 +            for (Iterator it = evAndListeners.iterator(); it.hasNext(); ) {
  24.112 +                LookupEvent ev = (LookupEvent)it.next();
  24.113 +                LookupListener ll = (LookupListener)it.next();
  24.114 +                ll.resultChanged(ev);
  24.115 +            }
  24.116 +        }
  24.117 +
  24.118 +        return delegate;
  24.119 +    }
  24.120 +
  24.121 +    @SuppressWarnings("unchecked")
  24.122 +    private static <T> ProxyResult<T> cast(ProxyResult<?> p) {
  24.123 +        return (ProxyResult<T>)p;
  24.124 +    }
  24.125 +
  24.126 +    public <T> Result<T> lookup(Template<T> template) {
  24.127 +        synchronized (this) {
  24.128 +            if (results == null) {
  24.129 +                results = new WeakHashMap<Template<?>,Reference<ProxyResult<?>>>();
  24.130 +            } else {
  24.131 +                Reference<ProxyResult<?>> ref = results.get(template);
  24.132 +
  24.133 +                if (ref != null) {
  24.134 +                    ProxyResult<?> p = ref.get();
  24.135 +
  24.136 +                    if (p != null) {
  24.137 +                        return cast(p);
  24.138 +                    }
  24.139 +                }
  24.140 +            }
  24.141 +
  24.142 +            ProxyResult<T> p = new ProxyResult<T>(template);
  24.143 +            Reference<ProxyResult<?>> ref = new WeakReference<ProxyResult<?>>(p);
  24.144 +            results.put(template, ref);
  24.145 +
  24.146 +            return p;
  24.147 +        }
  24.148 +    }
  24.149 +
  24.150 +    public <T> T lookup(Class<T> clazz) {
  24.151 +        if (clazz == null) {
  24.152 +            checkLookup();
  24.153 +            return null;
  24.154 +        }
  24.155 +        return checkLookup().lookup(clazz);
  24.156 +    }
  24.157 +
  24.158 +    public <T> Item<T> lookupItem(Template<T> template) {
  24.159 +        return checkLookup().lookupItem(template);
  24.160 +    }
  24.161 +
  24.162 +    /**
  24.163 +     * Result used in SimpleLookup. It holds a reference to the collection
  24.164 +     * passed in constructor. As the contents of this lookup result never
  24.165 +     * changes the addLookupListener and removeLookupListener are empty.
  24.166 +     */
  24.167 +    private final class ProxyResult<T> extends WaitableResult<T> implements LookupListener {
  24.168 +        /** Template used for this result. It is never null.*/
  24.169 +        private Template<T> template;
  24.170 +
  24.171 +        /** result to delegate to */
  24.172 +        private Lookup.Result<T> delegate;
  24.173 +
  24.174 +        /** listeners set */
  24.175 +        private javax.swing.event.EventListenerList listeners;
  24.176 +        private LookupListener lastListener;
  24.177 +
  24.178 +        /** Just remembers the supplied argument in variable template.*/
  24.179 +        ProxyResult(Template<T> template) {
  24.180 +            this.template = template;
  24.181 +        }
  24.182 +
  24.183 +        /** Checks state of the result
  24.184 +         */
  24.185 +        private Result<T> checkResult() {
  24.186 +            updateLookup(checkLookup());
  24.187 +
  24.188 +            return this.delegate;
  24.189 +        }
  24.190 +
  24.191 +        /** Updates the state of the lookup.
  24.192 +         * @return true if the lookup really changed
  24.193 +         */
  24.194 +        public boolean updateLookup(Lookup l) {
  24.195 +            Collection<? extends Item<T>> oldPairs = (delegate != null) ? delegate.allItems() : null;
  24.196 +
  24.197 +            LookupListener removedListener;
  24.198 +
  24.199 +            synchronized (this) {
  24.200 +                if ((delegate != null) && (lastListener != null)) {
  24.201 +                    removedListener = lastListener;
  24.202 +                    delegate.removeLookupListener(lastListener);
  24.203 +                } else {
  24.204 +                    removedListener = null;
  24.205 +                }
  24.206 +            }
  24.207 +
  24.208 +            // cannot call to foreign code 
  24.209 +            Lookup.Result<T> res = l.lookup(template);
  24.210 +
  24.211 +            synchronized (this) {
  24.212 +                if (removedListener == lastListener) {
  24.213 +                    delegate = res;
  24.214 +                    lastListener = new WeakResult<T>(this, delegate);
  24.215 +                    delegate.addLookupListener(lastListener);
  24.216 +                }
  24.217 +            }
  24.218 +
  24.219 +            if (oldPairs == null) {
  24.220 +                // nobody knows about a change
  24.221 +                return false;
  24.222 +            }
  24.223 +
  24.224 +            Collection<? extends Item<T>> newPairs = delegate.allItems();
  24.225 +
  24.226 +            // See #34961 for explanation.
  24.227 +            if (!(oldPairs instanceof List)) {
  24.228 +                if (oldPairs == Collections.EMPTY_SET) {
  24.229 +                    // avoid allocation
  24.230 +                    oldPairs = Collections.emptyList();
  24.231 +                } else {
  24.232 +                    oldPairs = new ArrayList<Item<T>>(oldPairs);
  24.233 +                }
  24.234 +            }
  24.235 +
  24.236 +            if (!(newPairs instanceof List)) {
  24.237 +                newPairs = new ArrayList<Item<T>>(newPairs);
  24.238 +            }
  24.239 +
  24.240 +            return !oldPairs.equals(newPairs);
  24.241 +        }
  24.242 +
  24.243 +        public synchronized void addLookupListener(LookupListener l) {
  24.244 +            if (listeners == null) {
  24.245 +                listeners = new javax.swing.event.EventListenerList();
  24.246 +            }
  24.247 +
  24.248 +            listeners.add(LookupListener.class, l);
  24.249 +        }
  24.250 +
  24.251 +        public synchronized void removeLookupListener(LookupListener l) {
  24.252 +            if (listeners != null) {
  24.253 +                listeners.remove(LookupListener.class, l);
  24.254 +            }
  24.255 +        }
  24.256 +
  24.257 +        public java.util.Collection<? extends T> allInstances() {
  24.258 +            return checkResult().allInstances();
  24.259 +        }
  24.260 +
  24.261 +        public Set<Class<? extends T>> allClasses() {
  24.262 +            return checkResult().allClasses();
  24.263 +        }
  24.264 +
  24.265 +        public Collection<? extends Item<T>> allItems() {
  24.266 +            return checkResult().allItems();
  24.267 +        }
  24.268 +
  24.269 +        protected void beforeLookup(Lookup.Template t) {
  24.270 +            Lookup.Result r = checkResult();
  24.271 +
  24.272 +            if (r instanceof WaitableResult) {
  24.273 +                ((WaitableResult) r).beforeLookup(t);
  24.274 +            }
  24.275 +        }
  24.276 +
  24.277 +        /** A change in lookup occured.
  24.278 +         * @param ev event describing the change
  24.279 +         *
  24.280 +         */
  24.281 +        public void resultChanged(LookupEvent anEvent) {
  24.282 +            collectFires(null);
  24.283 +        } 
  24.284 +        
  24.285 +        protected void collectFires(Collection<Object> evAndListeners) {
  24.286 +            javax.swing.event.EventListenerList l = this.listeners;
  24.287 +
  24.288 +            if (l == null) {
  24.289 +                return;
  24.290 +            }
  24.291 +
  24.292 +            Object[] listeners = l.getListenerList();
  24.293 +
  24.294 +            if (listeners.length == 0) {
  24.295 +                return;
  24.296 +            }
  24.297 +
  24.298 +            LookupEvent ev = new LookupEvent(this);
  24.299 +            AbstractLookup.notifyListeners(listeners, ev, evAndListeners);
  24.300 +        }
  24.301 +    }
  24.302 +     // end of ProxyResult
  24.303 +    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
  24.304 +        private Lookup.Result source;
  24.305 +        private Reference<ProxyResult<T>> result;
  24.306 +        
  24.307 +        public WeakResult(ProxyResult<T> r, Lookup.Result<T> s) {
  24.308 +            this.result = new WeakReference<ProxyResult<T>>(r);
  24.309 +            this.source = s;
  24.310 +        }
  24.311 +        
  24.312 +        protected void beforeLookup(Lookup.Template t) {
  24.313 +            ProxyResult r = (ProxyResult)result.get();
  24.314 +            if (r != null) {
  24.315 +                r.beforeLookup(t);
  24.316 +            } else {
  24.317 +                source.removeLookupListener(this);
  24.318 +            }
  24.319 +        }
  24.320 +
  24.321 +        protected void collectFires(Collection<Object> evAndListeners) {
  24.322 +            ProxyResult<T> r = result.get();
  24.323 +            if (r != null) {
  24.324 +                r.collectFires(evAndListeners);
  24.325 +            } else {
  24.326 +                source.removeLookupListener(this);
  24.327 +            }
  24.328 +        }
  24.329 +
  24.330 +        public void addLookupListener(LookupListener l) {
  24.331 +            assert false;
  24.332 +        }
  24.333 +
  24.334 +        public void removeLookupListener(LookupListener l) {
  24.335 +            assert false;
  24.336 +        }
  24.337 +
  24.338 +        public Collection<T> allInstances() {
  24.339 +            assert false;
  24.340 +            return null;
  24.341 +        }
  24.342 +
  24.343 +        public void resultChanged(LookupEvent ev) {
  24.344 +            ProxyResult r = (ProxyResult)result.get();
  24.345 +            if (r != null) {
  24.346 +                r.resultChanged(ev);
  24.347 +            } else {
  24.348 +                source.removeLookupListener(this);
  24.349 +            }
  24.350 +        }
  24.351 +
  24.352 +        public Collection<? extends Item<T>> allItems() {
  24.353 +            assert false;
  24.354 +            return null;
  24.355 +        }
  24.356 +
  24.357 +        public Set<Class<? extends T>> allClasses() {
  24.358 +            assert false;
  24.359 +            return null;
  24.360 +        }
  24.361 +    } // end of WeakResult
  24.362 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/SingletonLookup.java	Sat Oct 31 15:28:13 2009 +0100
    25.3 @@ -0,0 +1,173 @@
    25.4 +/*
    25.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    25.6 + * 
    25.7 + * Copyright 2008 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 + * If you wish your version of this file to be governed by only the CDDL
   25.28 + * or only the GPL Version 2, indicate your decision by adding
   25.29 + * "[Contributor] elects to include this software in this distribution
   25.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   25.31 + * single choice of license, a recipient has the option to distribute
   25.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   25.33 + * to extend the choice of license to its licensees as provided above.
   25.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   25.35 + * Version 2 license, then the option applies only if the new code is
   25.36 + * made subject to such option by the copyright holder.
   25.37 + * 
   25.38 + * Contributor(s):
   25.39 + * 
   25.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   25.41 + */
   25.42 +
   25.43 +package org.openide.util.lookup;
   25.44 +
   25.45 +import java.util.Collection;
   25.46 +import java.util.Collections;
   25.47 +import java.util.Set;
   25.48 +import org.openide.util.Lookup;
   25.49 +import org.openide.util.LookupListener;
   25.50 +
   25.51 +/**
   25.52 + * Unmodifiable lookup that contains just one fixed object.
   25.53 + *
   25.54 + * @author Marian Petras
   25.55 + */
   25.56 +class SingletonLookup extends Lookup {
   25.57 +
   25.58 +    private final Object objectToLookup;
   25.59 +    private final String id;
   25.60 +
   25.61 +    SingletonLookup(Object objectToLookup) {
   25.62 +        this(objectToLookup, null);
   25.63 +    }
   25.64 +
   25.65 +    SingletonLookup(Object objectToLookup, String id) {
   25.66 +        if (objectToLookup == null) {
   25.67 +            throw new IllegalArgumentException("null");                 //NOI18N
   25.68 +        }
   25.69 +
   25.70 +        this.objectToLookup = objectToLookup;
   25.71 +        this.id = id;
   25.72 +    }
   25.73 +
   25.74 +    @Override
   25.75 +    public <T> T lookup(Class<T> clazz) {
   25.76 +        if (clazz == null) {
   25.77 +            throw new IllegalArgumentException("null");                 //NOI18N
   25.78 +        }
   25.79 +
   25.80 +        return (clazz.isInstance(objectToLookup))
   25.81 +               ? clazz.cast(objectToLookup)
   25.82 +               : null;
   25.83 +    }
   25.84 +
   25.85 +    @Override
   25.86 +    public <T> Result<T> lookup(Template<T> template) {
   25.87 +        if (template == null) {
   25.88 +            throw new IllegalArgumentException("null");                 //NOI18N
   25.89 +        }
   25.90 +
   25.91 +        Lookup.Item<T> item = lookupItem(template);
   25.92 +        if (item != null) {
   25.93 +            return new SingletonResult<T>(item);
   25.94 +        } else {
   25.95 +            return Lookup.EMPTY.lookup(template);
   25.96 +        }
   25.97 +    }
   25.98 +
   25.99 +    @Override
  25.100 +    public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
  25.101 +        if (clazz == null) {
  25.102 +            throw new IllegalArgumentException("null");                 //NOI18N
  25.103 +        }
  25.104 +
  25.105 +        return (clazz.isInstance(objectToLookup))
  25.106 +               ? Collections.singletonList(clazz.cast(objectToLookup))
  25.107 +               : Collections.<T>emptyList();
  25.108 +    }
  25.109 +
  25.110 +    @Override
  25.111 +    @SuppressWarnings("unchecked")
  25.112 +    public <T> Item<T> lookupItem(Template<T> template) {
  25.113 +        if (template == null) {
  25.114 +            throw new IllegalArgumentException("null");                 //NOI18N
  25.115 +        }
  25.116 +
  25.117 +        String templateId = template.getId();
  25.118 +        if ((templateId != null) && !templateId.equals(id)) {
  25.119 +            return null;
  25.120 +        }
  25.121 +
  25.122 +        Object templateInst = template.getInstance();
  25.123 +        if ((templateInst != null) && (objectToLookup != templateInst)) {
  25.124 +            return null;
  25.125 +        }
  25.126 +
  25.127 +        Class<T> clazz = template.getType();
  25.128 +        if ((clazz != null) && !clazz.isInstance(objectToLookup)) {
  25.129 +            return null;
  25.130 +        }
  25.131 +
  25.132 +        Lookup.Item<T> item;
  25.133 +        if (clazz != null) {
  25.134 +            item = Lookups.lookupItem(clazz.cast(objectToLookup), id);
  25.135 +        } else {
  25.136 +            item = Lookups.lookupItem((T) objectToLookup, id);
  25.137 +        }
  25.138 +        return item;
  25.139 +    }
  25.140 +
  25.141 +    static class SingletonResult<T> extends Lookup.Result<T> {
  25.142 +
  25.143 +        private final Lookup.Item<T> item;
  25.144 +
  25.145 +        SingletonResult(Lookup.Item<T> item) {
  25.146 +            this.item = item;
  25.147 +        }
  25.148 +
  25.149 +        @Override
  25.150 +        public void addLookupListener(LookupListener l) {
  25.151 +            // this result never changes - no need to register a listener
  25.152 +        }
  25.153 +
  25.154 +        @Override
  25.155 +        public void removeLookupListener(LookupListener l) {
  25.156 +            // this result never changes - no need to register a listener
  25.157 +        }
  25.158 +
  25.159 +        @Override
  25.160 +        public Set<Class<? extends T>> allClasses() {
  25.161 +            return Collections.<Class<? extends T>>singleton(item.getType());
  25.162 +        }
  25.163 +
  25.164 +        @Override
  25.165 +        public Collection<? extends Item<T>> allItems() {
  25.166 +            return Collections.singletonList(item);
  25.167 +        }
  25.168 +
  25.169 +        @Override
  25.170 +        public Collection<? extends T> allInstances() {
  25.171 +            return Collections.singletonList(item.getInstance());
  25.172 +        }
  25.173 +
  25.174 +    }
  25.175 +
  25.176 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/WaitableResult.java	Sat Oct 31 15:28:13 2009 +0100
    26.3 @@ -0,0 +1,62 @@
    26.4 +/*
    26.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    26.6 + *
    26.7 + * Copyright 1997-2009 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 + * Contributor(s):
   26.28 + *
   26.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   26.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   26.31 + * Microsystems, Inc. All Rights Reserved.
   26.32 + *
   26.33 + * If you wish your version of this file to be governed by only the CDDL
   26.34 + * or only the GPL Version 2, indicate your decision by adding
   26.35 + * "[Contributor] elects to include this software in this distribution
   26.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   26.37 + * single choice of license, a recipient has the option to distribute
   26.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   26.39 + * to extend the choice of license to its licensees as provided above.
   26.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   26.41 + * Version 2 license, then the option applies only if the new code is
   26.42 + * made subject to such option by the copyright holder.
   26.43 + */
   26.44 +package org.openide.util.lookup;
   26.45 +
   26.46 +import java.util.Collection;
   26.47 +import org.openide.util.Lookup;
   26.48 +
   26.49 +
   26.50 +/** A special subclass of lookup that is able to wait before queries.
   26.51 + *
   26.52 + * @author  Jaroslav Tulach
   26.53 + */
   26.54 +abstract class WaitableResult<T> extends Lookup.Result<T> {
   26.55 +    /** Used by proxy results to synchronize before lookup.
   26.56 +     */
   26.57 +    protected abstract void beforeLookup(Lookup.Template t);
   26.58 +
   26.59 +    /** Needed to group notification of outside the package listeners
   26.60 +     * after all AbstractLookup and ProxyLookups have been updated.
   26.61 +     * @param evAndListeners LookupEvent, LookupListener, LookupEvent, LookupListener, etc.
   26.62 +     */
   26.63 +    protected abstract void collectFires(Collection<Object> evAndListeners);
   26.64 +     
   26.65 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/doc-files/index.html	Sat Oct 31 15:28:13 2009 +0100
    27.3 @@ -0,0 +1,208 @@
    27.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    27.5 +<!--
    27.6 +   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    27.7 +   -
    27.8 +   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    27.9 +   -
   27.10 +   - The contents of this file are subject to the terms of either the GNU
   27.11 +   - General Public License Version 2 only ("GPL") or the Common
   27.12 +   - Development and Distribution License("CDDL") (collectively, the
   27.13 +   - "License"). You may not use this file except in compliance with the
   27.14 +   - License. You can obtain a copy of the License at
   27.15 +   - http://www.netbeans.org/cddl-gplv2.html
   27.16 +   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   27.17 +   - specific language governing permissions and limitations under the
   27.18 +   - License.  When distributing the software, include this License Header
   27.19 +   - Notice in each file and include the License file at
   27.20 +   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   27.21 +   - particular file as subject to the "Classpath" exception as provided
   27.22 +   - by Sun in the GPL Version 2 section of the License file that
   27.23 +   - accompanied this code. If applicable, add the following below the
   27.24 +   - License Header, with the fields enclosed by brackets [] replaced by
   27.25 +   - your own identifying information:
   27.26 +   - "Portions Copyrighted [year] [name of copyright owner]"
   27.27 +   -
   27.28 +   - Contributor(s):
   27.29 +   -
   27.30 +   - The Original Software is NetBeans. The Initial Developer of the Original
   27.31 +   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   27.32 +   - Microsystems, Inc. All Rights Reserved.
   27.33 +   -
   27.34 +   - If you wish your version of this file to be governed by only the CDDL
   27.35 +   - or only the GPL Version 2, indicate your decision by adding
   27.36 +   - "[Contributor] elects to include this software in this distribution
   27.37 +   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   27.38 +   - single choice of license, a recipient has the option to distribute
   27.39 +   - your version of this file under either the CDDL, the GPL Version 2 or
   27.40 +   - to extend the choice of license to its licensees as provided above.
   27.41 +   - However, if you add GPL Version 2 code and therefore, elected the GPL
   27.42 +   - Version 2 license, then the option applies only if the new code is
   27.43 +   - made subject to such option by the copyright holder.
   27.44 +  -->
   27.45 +<HTML>
   27.46 +<HEAD>
   27.47 +<TITLE>Lookup Library</TITLE>
   27.48 +<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
   27.49 +</HEAD>
   27.50 +<BODY>
   27.51 +
   27.52 +<P>
   27.53 +
   27.54 +This is the home page of the <em>lookup library</em> implementation, which 
   27.55 +is intended to solve a general problem that every <cite>component-based system</CITE>
   27.56 +has had to face: how different components <b>register</b> to the system 
   27.57 +and how other parts of the system can <b>look</b> them <b>up</B>. 
   27.58 +<P>
   27.59 +There already are libraries trying to solve this problem, usually by querying for 
   27.60 +an interface and finding its appropriate implementaion. The most famous is 
   27.61 +<A href="http://www.jini.org/">Jini</A>, the platform for development of
   27.62 +distributed network services. Our library does something similar, but tries 
   27.63 +to stay small and easy
   27.64 +to use. The NetBeans <em>Lookup
   27.65 +Library</EM>'s main focus is a modular application consisting of independent modules
   27.66 +that want to communicate with each other. It does not try to solve networking or
   27.67 +legacy application integration. It is simple but powerful.
   27.68 +
   27.69 +<H2>Why would you want to use it?</H2>
   27.70 +
   27.71 +A well-written modular program separates <em>development</EM>
   27.72 +and <em>deployment</EM>.
   27.73 +There are many situations where a component needs some functionality but
   27.74 +does not actually care about the implementation. It is up to the <em>system
   27.75 +adminstrator</em> that deploys (installs) the application to decide which 
   27.76 +implementation to use.
   27.77 +<P>
   27.78 +The most simple and most often used method for allowing other implementations
   27.79 +to be plugged in is the <em>system property</em> pattern:
   27.80 +
   27.81 +<pre>
   27.82 +    <font class="keyword">public</font> <font class="type">Toolkit</font> <font class="function-name">getDefaultToolkit</font> () {
   27.83 +        java.awt.<font class="type">Toolkit</font> <font class="variable-name">t</font> = <font class="constant">null</font>;
   27.84 +        <font class="type">String</font> <font class="variable-name">classname</font> = System.getProperty (<font class="string">"java.awt.Toolkit"</font>);
   27.85 +        <font class="keyword">if</font> (classname != <font class="constant">null</font>) {
   27.86 +            <font class="keyword">try</font> {
   27.87 +                <font class="type">Class</font> <font class="variable-name">c</font> = Class.forName (classname);
   27.88 +                t = (java.awt.<font class="type">Toolkit</font>)c.newInstance ();
   27.89 +            } <font class="keyword">catch</font> (<font class="type">Exception</font> <font class="variable-name">ex</font>) {
   27.90 +                System.out.println (<font class="string">"Cannot initialize toolkit: "</font> + classname);
   27.91 +                ex.printStackTrace ();
   27.92 +            }
   27.93 +        }
   27.94 +        <font class="comment">// fallback </font>
   27.95 +        <font class="keyword">if</font> (t == <font class="constant">null</font>) {
   27.96 +            t = <font class="keyword">new</font> <font class="type">GenericAWTToolkit</font> ();
   27.97 +        }
   27.98 +    }
   27.99 +</pre>
  27.100 +
  27.101 +    
  27.102 +The idea is simple. The <em>deployer</em> can start the Java VM with the flag
  27.103 +<code>-Djava.awt.Toolkit=org.myorg.MyToolkit</code> where the <code>MyToolkit</code>
  27.104 +is his class with default constructor and the code in the <code>getDefaultToolkit</CODE>
  27.105 +method will instantiate the class and use it.
  27.106 +<P>
  27.107 +In principle this is general enough of a solution and works well, except that writing the 
  27.108 +code above is error prone and it also requires passing the arguments to the virtual machine. 
  27.109 +It would be much nicer if the registation could be done just by putting a JAR file with the <code>MyToolkit</code> class
  27.110 +into the application classpath.
  27.111 +<P>
  27.112 +Actually this has been realized also by the JDK development team and addressed in
  27.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>. 
  27.114 +The <code>MyToolkit</code> could be registered by adding a file 
  27.115 +<code>/META-INF/services/java.awt.Toolkit</code> with one line
  27.116 +<code>org.myorg.MyToolkit</code> into the JAR file that contains the
  27.117 +<code>MyToolkit</CODE> implementation. The code in <code>getDefaultToolkit</CODE>
  27.118 +will scan all JAR files in classpath and search for that file,
  27.119 +create an instance of <code>MyToolkit</code> and use it. 
  27.120 +The deployer can influence which toolkit will be created by 
  27.121 +adding the right JAR files into the classpath.
  27.122 +<P>
  27.123 +Of course the code to access the <code>META-INF/services/</code> files is even
  27.124 +more error prone than the <em>property pattern</EM>.  And this is exactly the
  27.125 +place where the <em>lookup library</em> can help. It provides an implementation of
  27.126 +the search algorithm with an easy interface. Just write:
  27.127 +<pre>
  27.128 +    <font class="keyword">import</font> <font class="type">java.awt.Toolkit</font>;
  27.129 +    <font class="keyword">import</font> <font class="type">org.openide.util.Lookup;</font>;
  27.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>);
  27.131 +</PRE>
  27.132 +and if the JAR with <code>MyToolkit</CODE> is in the class path, the simple call 
  27.133 +above will do the rest.
  27.134 +<P>
  27.135 +So whenever one writes an application divided into several independent modules (jar files)
  27.136 +that are being developed and deployed independently, there is a need for registering
  27.137 +and discovering components. First of all, a set of interfaces can be defined to enable 
  27.138 +inter-module communication (like the abstract class <code>java.awt.Toolkit</CODE>).
  27.139 +After that a set of modules providing implementation can written (<code>MyToolkit</code> and other concurent implementations)
  27.140 +and after that, whenever a module trying to utilitize the functionality wants to access
  27.141 +the <code>Toolkit</code> via lookup, the real implementation is returned.
  27.142 +<P>
  27.143 +It is the responsibility of lookup to find a suitable implementation of the
  27.144 +requested service and return an object implementing the service. This is the
  27.145 +the basic functionality and while the library provides you with a little bit
  27.146 +more, even this simple usage might be extremaly useful: the client code knows
  27.147 +nothing about the implementation and the implementation can be switched in
  27.148 +deployment time by simply replacing one implementation jar with other. There
  27.149 +is no code change required.
  27.150 +
  27.151 +<H2> Local lookup usage </H2>
  27.152 +The example in previous paragraph demostrated the usage of lookup as a global
  27.153 +registry (by using the <CODE>Lookup.getDefault()</CODE> call). One can also
  27.154 +consider another scenario where the lookup can help.
  27.155 +<P>
  27.156 +Let's switch hats to be an API designer for a while. The goal is to introduce a
  27.157 +new object into the system. But you either are not sure yet what all the roles
  27.158 +of the new object will be or you (more importantly) want to be able to add (or
  27.159 +change) roles of the object dynamically. So why not to introduce following
  27.160 +method to the object's interface:
  27.161 +<pre>
  27.162 +<font class="keyword">public class </FONT> <font class="type">MorphingObject</FONT> {
  27.163 +    <font class="keyword">public</FONT> <font class="type"><a href="@TOP@org/openide/util/Lookup.html">Lookup</A></FONT> getLookup() {
  27.164 +        <font class="keyword">return</FONT> <font class="variable-name">myLookup;</FONT>
  27.165 +    }
  27.166 +    ...
  27.167 +}
  27.168 +</pre>
  27.169 +By exposing the method getLookup you can attach different functionality to the
  27.170 +MorphingObject at runtime and whoever gets a reference to your object can ask it
  27.171 +whether the object supports a given interface like this:
  27.172 +<pre>
  27.173 +<font class="type">MorphingObject</FONT> <font class="variable-name">morph</FONT> = ...
  27.174 +<font class="type">AnInterface</font> <font class="variable-name">impl</font> = (<font
  27.175 +class="type">AnInterface</font>)morph.getLookup().<a
  27.176 +href="@TOP@org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(AnInterface.<font class="keyword">class</font>);
  27.177 +<font class="keyword">if</font> (impl == <font class="constant">null</font>) {
  27.178 +    <font class="keyword">return;</font><font class="comment">/* AnInterface not supported now! */</font>
  27.179 +}
  27.180 +impl.useIt();
  27.181 +</PRE>
  27.182 +
  27.183 +<H2>Additional functionality</H2>
  27.184 +The NetBeans lookup library also provides:
  27.185 +<UL>
  27.186 +<LI>Support for dynamically changing the lookup content.</LI>
  27.187 +<LI>The ability to return multiple results.</LI>
  27.188 +<LI>Notification of changes. After retrieving the result, the client can attach a
  27.189 +listener and be notified when the result of the lookup is changed.</LI>
  27.190 +<LI>Lazy initialization of the implementation. The implementation objects are
  27.191 +initialized only after someone asks for them. Even the implementation classes
  27.192 +are not loaded if they are not going to be used! </LI>
  27.193 +</UL>
  27.194 +
  27.195 +<H2>Further information</H2>
  27.196 +<UL>
  27.197 +  <LI><A HREF="lookup-api.html">Lookup Library APIs</A> for those writing the client code.
  27.198 +Specifying the query, getting the result and listenning on changes.</LI>
  27.199 +  <LI><A HREF="lookup-spi.html">Lookup Library SPIs</A> for those writing the
  27.200 +implementaion code and registering it with lookup. Includes also writing own
  27.201 +lookup implementation.</LI>
  27.202 +  <LI>Download <A HREF="http://www.netbeans.org/">NetBeans platform</A> which
  27.203 +contains <code>org-openide-util.jar</code></LI>
  27.204 +    <A HREF="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/lookup/">
  27.205 +    implementation package (org.openide.util.lookup) </A>
  27.206 +    + classes Lookup, LookupEvent, LookupListener in
  27.207 +    <A href="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/">util package</A></LI>
  27.208 +  <li><a href="http://www.martinfowler.com/articles/injection.html">Inversion of Control Containers and the Dependency Injection pattern</a> (Martin Fowler)</li>
  27.209 +</UL>
  27.210 +</BODY>
  27.211 +</HTML>
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/doc-files/lookup-api.html	Sat Oct 31 15:28:13 2009 +0100
    28.3 @@ -0,0 +1,188 @@
    28.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    28.5 +<!--
    28.6 +   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    28.7 +   -
    28.8 +   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    28.9 +   -
   28.10 +   - The contents of this file are subject to the terms of either the GNU
   28.11 +   - General Public License Version 2 only ("GPL") or the Common
   28.12 +   - Development and Distribution License("CDDL") (collectively, the
   28.13 +   - "License"). You may not use this file except in compliance with the
   28.14 +   - License. You can obtain a copy of the License at
   28.15 +   - http://www.netbeans.org/cddl-gplv2.html
   28.16 +   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   28.17 +   - specific language governing permissions and limitations under the
   28.18 +   - License.  When distributing the software, include this License Header
   28.19 +   - Notice in each file and include the License file at
   28.20 +   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   28.21 +   - particular file as subject to the "Classpath" exception as provided
   28.22 +   - by Sun in the GPL Version 2 section of the License file that
   28.23 +   - accompanied this code. If applicable, add the following below the
   28.24 +   - License Header, with the fields enclosed by brackets [] replaced by
   28.25 +   - your own identifying information:
   28.26 +   - "Portions Copyrighted [year] [name of copyright owner]"
   28.27 +   -
   28.28 +   - Contributor(s):
   28.29 +   -
   28.30 +   - The Original Software is NetBeans. The Initial Developer of the Original
   28.31 +   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   28.32 +   - Microsystems, Inc. All Rights Reserved.
   28.33 +   -
   28.34 +   - If you wish your version of this file to be governed by only the CDDL
   28.35 +   - or only the GPL Version 2, indicate your decision by adding
   28.36 +   - "[Contributor] elects to include this software in this distribution
   28.37 +   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   28.38 +   - single choice of license, a recipient has the option to distribute
   28.39 +   - your version of this file under either the CDDL, the GPL Version 2 or
   28.40 +   - to extend the choice of license to its licensees as provided above.
   28.41 +   - However, if you add GPL Version 2 code and therefore, elected the GPL
   28.42 +   - Version 2 license, then the option applies only if the new code is
   28.43 +   - made subject to such option by the copyright holder.
   28.44 +  -->
   28.45 +<HTML>
   28.46 +<HEAD>
   28.47 +<TITLE>Lookup Library API</TITLE>
   28.48 +<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
   28.49 +</HEAD>
   28.50 +<BODY>
   28.51 +<H1>Lookup library API</H1>
   28.52 +<p>
   28.53 +This document describes usage of the API provided by the Lookup Library. In this
   28.54 +document we assume that someone has already provided us with a lookup
   28.55 +implementation (for those seeking how to write a lookup implementation please
   28.56 +check <A href="lookup-spi.html">the SPI document</A>).
   28.57 +
   28.58 +<H2> Getting the lookup </H2>
   28.59 +
   28.60 +The first question you might ask is this: how can I get hold of a
   28.61 +lookup instance? There are basically two ways how you can get it.
   28.62 +
   28.63 +<H3> Global lookup </H3>
   28.64 +As you can see in the
   28.65 +
   28.66 +<a href="@TOP@org/openide/util/Lookup.html">Lookup</a>
   28.67 +
   28.68 +Javadoc there is a static method
   28.69 +
   28.70 +<pre><a href="@TOP@org/openide/util/Lookup.html#getDefault()">public static Lookup getDefault()</a></pre>
   28.71 +
   28.72 +The object returned from this method is
   28.73 +a global lookup that can serve as a central place for registering services.
   28.74 +The default implementation is a lookup that implements
   28.75 +<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">
   28.76 +the JDK JAR services</A>
   28.77 +mechanism and delegates to <samp>META-INF/services/name.of.Class</samp> files.
   28.78 +<P>
   28.79 +If you want to add your class to this lookup just create a file in your
   28.80 +jar file under the <code>META-INF</code> directory (e.g. <samp>META-INF/services/com.my.APIClass</samp>)
   28.81 +and let the file contain only one line of text
   28.82 +
   28.83 +<pre>com.foo.impl.ImplOfTheAPI</pre>
   28.84 +
   28.85 +<p>(This is more easily done using the <code>@ServiceProvider</code> annotation.)</p>
   28.86 +
   28.87 +The following code will return you a newly created instance of
   28.88 +<code>com.foo.impl.ImplOfTheAPI</code>:
   28.89 +
   28.90 +<PRE>
   28.91 +   <font class="keyword">import</FONT> org.openide.util.Lookup;
   28.92 +   return Lookup.getDefault().lookup(com.my.APIClass.class);
   28.93 +</PRE>
   28.94 +
   28.95 +<H3> Local lookup </H3>
   28.96 +
   28.97 +This is just a reminder that whenever you find a method called getLookup
   28.98 +or similar returning a lookup instance, the provided lookup is <EM>not</EM> the
   28.99 +general lookup described in the previous paragraph. Rather, it is a private lookup
  28.100 +implementation that is usually bound to the object you invoked the method on.
  28.101 +
  28.102 +<H2> Use of Lookup.Template and Lookup.Result </H2>
  28.103 +
  28.104 +There are more ways how you can ask lookup besides the variant with one class
  28.105 +parameter. If you want more functionality, you have to implement the interface
  28.106 +Lookup.Template and pass an instance of such object to the lookup call.
  28.107 +<p>
  28.108 +<EM>Note:</EM> If you use Lookup.Template, the object returned from the lookup is
  28.109 +<EM>not</EM> the object you are looking for but rather a result object
  28.110 +(Lookup.Result). You can call methods on such a result object to get the actual
  28.111 +results.
  28.112 +<p>
  28.113 +Let's examine following example:
  28.114 +
  28.115 +<pre>
  28.116 +        <font class="keyword">import</FONT> org.openide.util.Lookup;
  28.117 +
  28.118 +        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
  28.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>);
  28.120 +        Lookup.<font class="type">Result</font> <font class="variable-name">result</font> = lookup.lookup(template);
  28.121 +        <font class="type">Collection</font> <font class="variable-name">c</font> = result.allInstances();
  28.122 +        <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = c.iterator(); i.hasNext(); ) {
  28.123 +            <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
  28.124 +            s.callMyService();
  28.125 +        }
  28.126 +</pre>
  28.127 +
  28.128 +In this example the call to method lookup(...) returns immediately because the
  28.129 +result object can be constructed even without real results. The first time you
  28.130 +ask for the result object by calling r.allInstances(), the lookup has to supply you
  28.131 +the real results and this method can block until the required data are really
  28.132 +available.
  28.133 +<p>
  28.134 +If you are not interested in all objects as in the previous example, you can use the
  28.135 +template to ask for one resulting object (wrapped in special Item instance):
  28.136 +<pre>
  28.137 +        <font class="keyword">import</FONT> org.openide.util.Lookup;
  28.138 +
  28.139 +        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
  28.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>);
  28.141 +        Lookup.<font class="type">Item</font> <font class="variable-name">item</font> = lookup.lookupItem(template);
  28.142 +        <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)item.getInstance();
  28.143 +        s.callMyService();
  28.144 +</pre>
  28.145 +
  28.146 +Again, the Item object can construct the real instance only if you call
  28.147 +getInstance. The item can be useful even without calling getInstance - you can get
  28.148 +its display name or an unique id. You can use this information, for example, for
  28.149 +constructing menu items without the need to instantiate (or even load!)
  28.150 +the class implementing the functionality. Only when the real functionality is
  28.151 +needed (e.g. the user has selected the menu item) you can call getInstance
  28.152 +and call the real meat of the implementation.
  28.153 +
  28.154 +<H2> Listenning on lookup changes </H2>
  28.155 +There is one additional piece of functionality bound to the Lookup.Result object worth
  28.156 +mentioning: you can attach a listener to it and be informed about any changes in
  28.157 +the lookup. This might be extremly usefull when the lookup dynamically changes
  28.158 +(from other threads). The listener can keep state of your object up-to-date even
  28.159 +in cases where the lookup changes asynchronously.
  28.160 +<p>
  28.161 +So here is some sample code using the listenner:
  28.162 +
  28.163 +<pre>
  28.164 +        <font class="keyword">import</FONT> org.openide.util.Lookup;
  28.165 +        <font class="keyword">import</FONT> org.openide.util.LookupListener;
  28.166 +        <font class="keyword">import</FONT> org.openide.util.LookupEvent;
  28.167 +
  28.168 +        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
  28.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>);
  28.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);
  28.171 +        result.addLookupListener(<font class="keyword">new</font> <font class="type">LookupListener</font>() {
  28.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>) {
  28.173 +                reaction(result);
  28.174 +            }
  28.175 +        });
  28.176 +        reaction(result);
  28.177 +    }
  28.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>) {
  28.179 +        <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = r.allInstances().iterator(); i.hasNext(); ) {
  28.180 +            <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
  28.181 +            s.callMyService();
  28.182 +        }
  28.183 +    }
  28.184 +</pre>
  28.185 +
  28.186 +Please note that we first attach a listener and then call the reaction method.
  28.187 +This ensures that we always get the newest possible state. Also you must be
  28.188 +careful in the reaction method since it can be called from two different
  28.189 +threads simultaneously (your code has to be prepared for this).
  28.190 +</BODY>
  28.191 +</HTML>
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/doc-files/lookup-spi.html	Sat Oct 31 15:28:13 2009 +0100
    29.3 @@ -0,0 +1,147 @@
    29.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    29.5 +<!--
    29.6 +   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    29.7 +   -
    29.8 +   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    29.9 +   -
   29.10 +   - The contents of this file are subject to the terms of either the GNU
   29.11 +   - General Public License Version 2 only ("GPL") or the Common
   29.12 +   - Development and Distribution License("CDDL") (collectively, the
   29.13 +   - "License"). You may not use this file except in compliance with the
   29.14 +   - License. You can obtain a copy of the License at
   29.15 +   - http://www.netbeans.org/cddl-gplv2.html
   29.16 +   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   29.17 +   - specific language governing permissions and limitations under the
   29.18 +   - License.  When distributing the software, include this License Header
   29.19 +   - Notice in each file and include the License file at
   29.20 +   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   29.21 +   - particular file as subject to the "Classpath" exception as provided
   29.22 +   - by Sun in the GPL Version 2 section of the License file that
   29.23 +   - accompanied this code. If applicable, add the following below the
   29.24 +   - License Header, with the fields enclosed by brackets [] replaced by
   29.25 +   - your own identifying information:
   29.26 +   - "Portions Copyrighted [year] [name of copyright owner]"
   29.27 +   -
   29.28 +   - Contributor(s):
   29.29 +   -
   29.30 +   - The Original Software is NetBeans. The Initial Developer of the Original
   29.31 +   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   29.32 +   - Microsystems, Inc. All Rights Reserved.
   29.33 +   -
   29.34 +   - If you wish your version of this file to be governed by only the CDDL
   29.35 +   - or only the GPL Version 2, indicate your decision by adding
   29.36 +   - "[Contributor] elects to include this software in this distribution
   29.37 +   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   29.38 +   - single choice of license, a recipient has the option to distribute
   29.39 +   - your version of this file under either the CDDL, the GPL Version 2 or
   29.40 +   - to extend the choice of license to its licensees as provided above.
   29.41 +   - However, if you add GPL Version 2 code and therefore, elected the GPL
   29.42 +   - Version 2 license, then the option applies only if the new code is
   29.43 +   - made subject to such option by the copyright holder.
   29.44 +  -->
   29.45 +<HTML>
   29.46 +<HEAD>
   29.47 +<TITLE>Lookup Library SPI</TITLE>
   29.48 +<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
   29.49 +</HEAD>
   29.50 +<BODY>
   29.51 +<H1>Lookup library SPI</H1>
   29.52 +This document describe usage of the SPI provided by the Lookup Library
   29.53 +(for those seeking how to use lookup instance please
   29.54 +check <A href="lookup-api.html">the API document</A>).
   29.55 +<p>
   29.56 +By using the SPI you can create lookups that can be used by the users of the
   29.57 +Lookup API. While the Lookup API consists of a couple of classes in the package
   29.58 +<em>org.openide.util.*</EM>,
   29.59 +the SPI has its own package <em>org.openide.util.lookup.*</EM>.
   29.60 +
   29.61 +<H2> Simple lookups </H2>
   29.62 +Let us start with the simplest case. You have decided that your newly created
   29.63 +object will provide an API in the form of a getLookup() method. You have to
   29.64 +return a functional lookup from this call. You can use static methods in class
   29.65 +<a href="@TOP@org/openide/util/lookup/Lookups.html">
   29.66 +<code>Lookups</code></A> to create a lookup for you. If you want only one
   29.67 +object to be returned, just call 
   29.68 +<a href="@TOP@org/openide/util/lookup/Lookups.html#singleton(java.lang.Object)">
   29.69 +<code>Lookups.singleton(x)</code></A> where x is the object to be 
   29.70 +returned by the lookup. Or if you want to supply more objects, use a call to the method
   29.71 +<a href="@TOP@org/openide/util/lookup/Lookups.html#fixed(java.lang.Object...)">
   29.72 +<code>fixed(Object []x)</CODE></A>.
   29.73 +<EM> Note: </EM> The lookups returned from methods <code>singleton(...)</code> and
   29.74 +<code>fixed(...)</code> do <EM>
   29.75 +not </EM> support dynamic changes and attaching listeners. Their content is
   29.76 +fixed from the time you call the creating method.
   29.77 +
   29.78 +<H2> ProxyLookup </H2>
   29.79 +There can be situations where you get a lookup object from someone else and you
   29.80 +want your lookup to return exactly the instances from the original lookup plus
   29.81 +your own results. Here the class ProxyLookup comes into the play.
   29.82 +<p>
   29.83 +You simply create a new lookup like this:
   29.84 +
   29.85 +<pre>
   29.86 +    <font class="keyword">import</FONT> org.openide.util.Lookup;
   29.87 +    <font class="keyword">import</FONT> org.openide.util.lookup.*;
   29.88 +
   29.89 +    <font class="type">Lookup</font> <font class="variable-name">lookup1</font> = ...;
   29.90 +
   29.91 +    <font class="type">Lookup</font> <font class="variable-name">lookup2</font> = Lookups.singleton(MyService.<font class="keyword">class</font>);
   29.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 });
   29.93 +</pre>
   29.94 +
   29.95 +<H2> AbstractLookup </H2>
   29.96 +<!-- This paragraph originally copied from
   29.97 +@TOP@org/openide/doc-files/services-api.html#lookup-impl
   29.98 +-->
   29.99 +
  29.100 +<p>The most powerful way to provide a lookup is to directly define
  29.101 +what instances and items it should provide, by subclassing. For this,
  29.102 +
  29.103 +<a href="@TOP@org/openide/util/lookup/AbstractLookup.html"><code>AbstractLookup</code></a>
  29.104 +
  29.105 +is recommended as it is easiest to use.
  29.106 +
  29.107 +<p>The simplest way to use <code>AbstractLookup</code> is to use its
  29.108 +public constructor (in which case you need not subclass it). Here you
  29.109 +provide an
  29.110 +
  29.111 +<a href="@TOP@org/openide/util/lookup/AbstractLookup.Content.html"><code>AbstractLookup.Content</code></a>
  29.112 +
  29.113 +object which you have created and hold on to privately, and which
  29.114 +keeps track of instances and permits them to be registered and
  29.115 +deregistered. Often
  29.116 +
  29.117 +<a href="@TOP@org/openide/util/lookup/InstanceContent.html"><code>InstanceContent</code></a>
  29.118 +
  29.119 +is used as the content implementation. To add something to the lookup,
  29.120 +simply use
  29.121 +
  29.122 +<a href="@TOP@org/openide/util/lookup/InstanceContent.html#add(java.lang.Object)"><code>add(Object)</code></a>
  29.123 +
  29.124 +(and <code>remove(Object)</code> for the reverse). These may be called
  29.125 +at any time and will update the set of registered instances (firing
  29.126 +result changes as needed).
  29.127 +
  29.128 +<pre>
  29.129 +    <font class="keyword">import</FONT> org.openide.util.lookup.*;
  29.130 +    <font class="type">InstanceContent</font> <font class="variable-name">ic</font> = <font class="keyword">new</font> <font class="type">InstanceContent</font> ();
  29.131 +    ic.add(firstObject);
  29.132 +    <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">AbstractLookup</font> (ic);
  29.133 +</pre>
  29.134 +
  29.135 +<p>In case it is expensive to actually compute the object in the
  29.136 +lookup, but there is some cheap "key" which can easily generate it,
  29.137 +you may instead register the key by passing in an
  29.138 +
  29.139 +<a href="@TOP@org/openide/util/lookup/InstanceContent.Convertor.html"><code>InstanceContent.Convertor</code></a>.
  29.140 +
  29.141 +This convertor translates the key to the real instance that the lookup
  29.142 +client sees, if and when needed. For example, if you have a long list
  29.143 +of class names and wish to register default instances of each class,
  29.144 +you might actually register the class name as the key, and supply a
  29.145 +convertor which really loads the class and instantiates it. This makes
  29.146 +it easy to set up the lookup, but nothing is really loaded until
  29.147 +someone asks for it.
  29.148 +
  29.149 +</BODY>
  29.150 +</HTML>
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/openide.util.lookup/src/org/openide/util/lookup/package.html	Sat Oct 31 15:28:13 2009 +0100
    30.3 @@ -0,0 +1,48 @@
    30.4 +<!--
    30.5 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    30.6 +
    30.7 +Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    30.8 +
    30.9 +
   30.10 +The contents of this file are subject to the terms of either the GNU
   30.11 +General Public License Version 2 only ("GPL") or the Common
   30.12 +Development and Distribution License("CDDL") (collectively, the
   30.13 +"License"). You may not use this file except in compliance with the
   30.14 +License. You can obtain a copy of the License at
   30.15 +http://www.netbeans.org/cddl-gplv2.html
   30.16 +or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   30.17 +specific language governing permissions and limitations under the
   30.18 +License.  When distributing the software, include this License Header
   30.19 +Notice in each file and include the License file at
   30.20 +nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   30.21 +particular file as subject to the "Classpath" exception as provided
   30.22 +by Sun in the GPL Version 2 section of the License file that
   30.23 +accompanied this code. If applicable, add the following below the
   30.24 +License Header, with the fields enclosed by brackets [] replaced by
   30.25 +your own identifying information:
   30.26 +"Portions Copyrighted [year] [name of copyright owner]"
   30.27 +
   30.28 +Contributor(s):
   30.29 +
   30.30 +The Original Software is NetBeans. The Initial Developer of the Original
   30.31 +Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   30.32 +Microsystems, Inc. All Rights Reserved.
   30.33 +
   30.34 +If you wish your version of this file to be governed by only the CDDL
   30.35 +or only the GPL Version 2, indicate your decision by adding
   30.36 +"[Contributor] elects to include this software in this distribution
   30.37 +under the [CDDL or GPL Version 2] license." If you do not indicate a
   30.38 +single choice of license, a recipient has the option to distribute
   30.39 +your version of this file under either the CDDL, the GPL Version 2 or
   30.40 +to extend the choice of license to its licensees as provided above.
   30.41 +However, if you add GPL Version 2 code and therefore, elected the GPL
   30.42 +Version 2 license, then the option applies only if the new code is
   30.43 +made subject to such option by the copyright holder.
   30.44 +-->
   30.45 +
   30.46 +<html>
   30.47 +<body>
   30.48 +Support classes for the Registration and {@link org.openide.util.Lookup} extension mechanism.
   30.49 +Read more: <a href="doc-files/index.html">Lookup Library</a>
   30.50 +</body>
   30.51 +</html>
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/openide.util.lookup/test/unit/src/org/bar/Comparator2.java	Sat Oct 31 15:28:13 2009 +0100
    31.3 @@ -0,0 +1,7 @@
    31.4 +
    31.5 +package org.bar;
    31.6 +
    31.7 +public class Comparator2 implements java.util.Comparator {
    31.8 +    public int compare(Object o1, Object o2) {return 0;}
    31.9 +    public boolean equals(Object obj) {return true;}
   31.10 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/openide.util.lookup/test/unit/src/org/bar/Comparator3.java	Sat Oct 31 15:28:13 2009 +0100
    32.3 @@ -0,0 +1,7 @@
    32.4 +
    32.5 +package org.bar;
    32.6 +
    32.7 +public class Comparator3 implements java.util.Comparator {
    32.8 +    public int compare(Object o1, Object o2) {return 0;}
    32.9 +    public boolean equals(Object obj) {return true;}
   32.10 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/openide.util.lookup/test/unit/src/org/bar/Implementation2.java	Sat Oct 31 15:28:13 2009 +0100
    33.3 @@ -0,0 +1,3 @@
    33.4 +package org.bar;
    33.5 +import org.foo.Interface;
    33.6 +public class Implementation2 implements Interface {}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/openide.util.lookup/test/unit/src/org/bar/Iterator2.java	Sat Oct 31 15:28:13 2009 +0100
    34.3 @@ -0,0 +1,11 @@
    34.4 +
    34.5 +package org.bar;
    34.6 +
    34.7 +public class Iterator2 implements java.util.Iterator {
    34.8 +    public boolean hasNext() {return false;}
    34.9 +    
   34.10 +    public Object next() {return null;}
   34.11 +    
   34.12 +    public void remove() {}
   34.13 +   
   34.14 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/openide.util.lookup/test/unit/src/org/foo/Interface.java	Sat Oct 31 15:28:13 2009 +0100
    35.3 @@ -0,0 +1,2 @@
    35.4 +package org.foo;
    35.5 +public interface Interface {}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/openide.util.lookup/test/unit/src/org/foo/impl/Comparator1.java	Sat Oct 31 15:28:13 2009 +0100
    36.3 @@ -0,0 +1,7 @@
    36.4 +
    36.5 +package org.foo.impl;
    36.6 +
    36.7 +public class Comparator1 implements java.util.Comparator {
    36.8 +    public int compare(Object o1, Object o2) {return 0;}
    36.9 +    public boolean equals(Object obj) {return true;}
   36.10 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/openide.util.lookup/test/unit/src/org/foo/impl/Implementation1.java	Sat Oct 31 15:28:13 2009 +0100
    37.3 @@ -0,0 +1,3 @@
    37.4 +package org.foo.impl;
    37.5 +import org.foo.Interface;
    37.6 +public class Implementation1 implements Interface {}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/openide.util.lookup/test/unit/src/org/foo/impl/Iterator1.java	Sat Oct 31 15:28:13 2009 +0100
    38.3 @@ -0,0 +1,11 @@
    38.4 +
    38.5 +package org.foo.impl;
    38.6 +
    38.7 +public class Iterator1 implements java.util.Iterator {
    38.8 +    public boolean hasNext() {return false;}
    38.9 +    
   38.10 +    public Object next() {return null;}
   38.11 +    
   38.12 +    public void remove() {}
   38.13 +   
   38.14 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/openide.util.lookup/test/unit/src/org/foo/impl/Runnable1.java	Sat Oct 31 15:28:13 2009 +0100
    39.3 @@ -0,0 +1,6 @@
    39.4 +
    39.5 +package org.foo.impl;
    39.6 +
    39.7 +public class Runnable1 implements Runnable {
    39.8 +   public void run () {}
    39.9 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupArrayStorageTest.java	Sat Oct 31 15:28:13 2009 +0100
    40.3 @@ -0,0 +1,120 @@
    40.4 +/*
    40.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    40.6 + *
    40.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    40.8 + *
    40.9 + * The contents of this file are subject to the terms of either the GNU
   40.10 + * General Public License Version 2 only ("GPL") or the Common
   40.11 + * Development and Distribution License("CDDL") (collectively, the
   40.12 + * "License"). You may not use this file except in compliance with the
   40.13 + * License. You can obtain a copy of the License at
   40.14 + * http://www.netbeans.org/cddl-gplv2.html
   40.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   40.16 + * specific language governing permissions and limitations under the
   40.17 + * License.  When distributing the software, include this License Header
   40.18 + * Notice in each file and include the License file at
   40.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   40.20 + * particular file as subject to the "Classpath" exception as provided
   40.21 + * by Sun in the GPL Version 2 section of the License file that
   40.22 + * accompanied this code. If applicable, add the following below the
   40.23 + * License Header, with the fields enclosed by brackets [] replaced by
   40.24 + * your own identifying information:
   40.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   40.26 + *
   40.27 + * Contributor(s):
   40.28 + *
   40.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   40.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   40.31 + * Microsystems, Inc. All Rights Reserved.
   40.32 + *
   40.33 + * If you wish your version of this file to be governed by only the CDDL
   40.34 + * or only the GPL Version 2, indicate your decision by adding
   40.35 + * "[Contributor] elects to include this software in this distribution
   40.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   40.37 + * single choice of license, a recipient has the option to distribute
   40.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   40.39 + * to extend the choice of license to its licensees as provided above.
   40.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   40.41 + * Version 2 license, then the option applies only if the new code is
   40.42 + * made subject to such option by the copyright holder.
   40.43 + */
   40.44 +
   40.45 +package org.openide.util.lookup;
   40.46 +
   40.47 +import junit.framework.*;
   40.48 +import org.netbeans.junit.*;
   40.49 +import org.openide.util.Lookup;
   40.50 +
   40.51 +public class AbstractLookupArrayStorageTest extends AbstractLookupBaseHid {
   40.52 +    public AbstractLookupArrayStorageTest(java.lang.String testName) {
   40.53 +        super(testName, null);
   40.54 +    }
   40.55 +
   40.56 +    public static TestSuite suite () {
   40.57 +        NbTestSuite suite = new NbTestSuite ();
   40.58 +        suite.addTest (new PL (2));
   40.59 +        suite.addTest (new AL (1));
   40.60 +        suite.addTest (new AL (-1));
   40.61 +        suite.addTest (new PL (-1));
   40.62 +        suite.addTest (new AL (5));
   40.63 +        suite.addTest (new PL (3));
   40.64 +        suite.addTest (new AL (2000));
   40.65 +        suite.addTest (new PL (2000));
   40.66 +        return suite;
   40.67 +    }
   40.68 +
   40.69 +    static final class AL extends ArrayTestSuite {
   40.70 +        public AL (int trash) {
   40.71 +            super (trash);
   40.72 +        }
   40.73 +        
   40.74 +        public Lookup createLookup (Lookup lookup) {
   40.75 +            return lookup;
   40.76 +        }
   40.77 +        
   40.78 +        public void clearCaches () {
   40.79 +        }
   40.80 +        
   40.81 +    }
   40.82 +    
   40.83 +    static final class PL extends ArrayTestSuite {
   40.84 +        public PL (int trash) {
   40.85 +            super (trash);
   40.86 +        }
   40.87 +        
   40.88 +        public Lookup createLookup (Lookup lookup) {
   40.89 +            return  new ProxyLookup (new Lookup[] { lookup });
   40.90 +        }
   40.91 +        
   40.92 +        public void clearCaches () {
   40.93 +        }
   40.94 +        
   40.95 +    }
   40.96 +    
   40.97 +    private static abstract class ArrayTestSuite extends NbTestSuite 
   40.98 +    implements AbstractLookupBaseHid.Impl {
   40.99 +        private int trash;
  40.100 +        
  40.101 +        public ArrayTestSuite (int trash) {
  40.102 +            super (AbstractLookupArrayStorageTest.class);
  40.103 +            this.trash = trash;
  40.104 +            
  40.105 +            int cnt = this.countTestCases();
  40.106 +            for (int i = 0; i < cnt; i++) {
  40.107 +                Object o = this.testAt (i);
  40.108 +                AbstractLookupBaseHid t = (AbstractLookupBaseHid)o;
  40.109 +                t.impl = this;
  40.110 +            }
  40.111 +        }
  40.112 +        
  40.113 +        public Lookup createInstancesLookup (InstanceContent ic) {
  40.114 +            if (trash == -1) {
  40.115 +                return new AbstractLookup (ic, new ArrayStorage ());
  40.116 +            } else {
  40.117 +                return new AbstractLookup (ic, new ArrayStorage (new Integer (trash)));
  40.118 +            }
  40.119 +        }
  40.120 +        
  40.121 +        
  40.122 +    }
  40.123 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupAsynchExecutorTest.java	Sat Oct 31 15:28:13 2009 +0100
    41.3 @@ -0,0 +1,108 @@
    41.4 +/*
    41.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    41.6 + *
    41.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    41.8 + *
    41.9 + * The contents of this file are subject to the terms of either the GNU
   41.10 + * General Public License Version 2 only ("GPL") or the Common
   41.11 + * Development and Distribution License("CDDL") (collectively, the
   41.12 + * "License"). You may not use this file except in compliance with the
   41.13 + * License. You can obtain a copy of the License at
   41.14 + * http://www.netbeans.org/cddl-gplv2.html
   41.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   41.16 + * specific language governing permissions and limitations under the
   41.17 + * License.  When distributing the software, include this License Header
   41.18 + * Notice in each file and include the License file at
   41.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   41.20 + * particular file as subject to the "Classpath" exception as provided
   41.21 + * by Sun in the GPL Version 2 section of the License file that
   41.22 + * accompanied this code. If applicable, add the following below the
   41.23 + * License Header, with the fields enclosed by brackets [] replaced by
   41.24 + * your own identifying information:
   41.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   41.26 + *
   41.27 + * Contributor(s):
   41.28 + *
   41.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   41.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   41.31 + * Microsystems, Inc. All Rights Reserved.
   41.32 + *
   41.33 + * If you wish your version of this file to be governed by only the CDDL
   41.34 + * or only the GPL Version 2, indicate your decision by adding
   41.35 + * "[Contributor] elects to include this software in this distribution
   41.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   41.37 + * single choice of license, a recipient has the option to distribute
   41.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   41.39 + * to extend the choice of license to its licensees as provided above.
   41.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   41.41 + * Version 2 license, then the option applies only if the new code is
   41.42 + * made subject to such option by the copyright holder.
   41.43 + */
   41.44 +
   41.45 +package org.openide.util.lookup;
   41.46 +
   41.47 +import java.util.ArrayList;
   41.48 +import java.util.List;
   41.49 +import java.util.concurrent.Executor;
   41.50 +import org.netbeans.junit.NbTestCase;
   41.51 +import org.openide.util.Lookup;
   41.52 +import org.openide.util.LookupEvent;
   41.53 +import org.openide.util.LookupListener;
   41.54 +
   41.55 +public class AbstractLookupAsynchExecutorTest extends NbTestCase implements Executor {
   41.56 +    private List<Runnable> toRun = new ArrayList<Runnable>();
   41.57 +
   41.58 +
   41.59 +    public AbstractLookupAsynchExecutorTest(java.lang.String testName) {
   41.60 +        super(testName);
   41.61 +    }
   41.62 +
   41.63 +    public void testCanProxyLookupHaveWrongResults() {
   41.64 +        final InstanceContent ic = new InstanceContent(this);
   41.65 +        final AbstractLookup lookup = new AbstractLookup(ic);
   41.66 +
   41.67 +        class L implements LookupListener {
   41.68 +            ProxyLookup pl;
   41.69 +            Lookup.Result<String> original;
   41.70 +            Lookup.Result<String> wrapped;
   41.71 +            boolean ok;
   41.72 +
   41.73 +            public void test() {
   41.74 +                pl = new ProxyLookup(lookup);
   41.75 +                original = lookup.lookupResult(String.class);
   41.76 +
   41.77 +                original.addLookupListener(this);
   41.78 +
   41.79 +                wrapped = pl.lookupResult(String.class);
   41.80 +
   41.81 +                assertEquals("Original empty", 0, original.allInstances().size());
   41.82 +                assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
   41.83 +
   41.84 +                ic.add("Hello!");
   41.85 +            }
   41.86 +
   41.87 +            public void resultChanged(LookupEvent ev) {
   41.88 +                ok = true;
   41.89 +                assertContainsHello();
   41.90 +            }
   41.91 +
   41.92 +            public void assertContainsHello() {
   41.93 +                assertEquals("Original has hello", 1, original.allInstances().size());
   41.94 +                assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
   41.95 +            }
   41.96 +
   41.97 +        }
   41.98 +        L listener = new L();
   41.99 +        listener.test();
  41.100 +        listener.assertContainsHello();
  41.101 +        for (Runnable r : toRun) {
  41.102 +            r.run();
  41.103 +        }
  41.104 +        assertTrue("Listener called", listener.ok);
  41.105 +    }
  41.106 +
  41.107 +    public void execute(Runnable command) {
  41.108 +        toRun.add(command);
  41.109 +    }
  41.110 +
  41.111 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java	Sat Oct 31 15:28:13 2009 +0100
    42.3 @@ -0,0 +1,2088 @@
    42.4 +/*
    42.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    42.6 + *
    42.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    42.8 + *
    42.9 + * The contents of this file are subject to the terms of either the GNU
   42.10 + * General Public License Version 2 only ("GPL") or the Common
   42.11 + * Development and Distribution License("CDDL") (collectively, the
   42.12 + * "License"). You may not use this file except in compliance with the
   42.13 + * License. You can obtain a copy of the License at
   42.14 + * http://www.netbeans.org/cddl-gplv2.html
   42.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   42.16 + * specific language governing permissions and limitations under the
   42.17 + * License.  When distributing the software, include this License Header
   42.18 + * Notice in each file and include the License file at
   42.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   42.20 + * particular file as subject to the "Classpath" exception as provided
   42.21 + * by Sun in the GPL Version 2 section of the License file that
   42.22 + * accompanied this code. If applicable, add the following below the
   42.23 + * License Header, with the fields enclosed by brackets [] replaced by
   42.24 + * your own identifying information:
   42.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   42.26 + *
   42.27 + * Contributor(s):
   42.28 + *
   42.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   42.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   42.31 + * Microsystems, Inc. All Rights Reserved.
   42.32 + *
   42.33 + * If you wish your version of this file to be governed by only the CDDL
   42.34 + * or only the GPL Version 2, indicate your decision by adding
   42.35 + * "[Contributor] elects to include this software in this distribution
   42.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   42.37 + * single choice of license, a recipient has the option to distribute
   42.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   42.39 + * to extend the choice of license to its licensees as provided above.
   42.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   42.41 + * Version 2 license, then the option applies only if the new code is
   42.42 + * made subject to such option by the copyright holder.
   42.43 + */
   42.44 +
   42.45 +package org.openide.util.lookup;
   42.46 +
   42.47 +import java.io.ByteArrayInputStream;
   42.48 +import java.io.ByteArrayOutputStream;
   42.49 +import java.io.ObjectInputStream;
   42.50 +import java.io.ObjectOutputStream;
   42.51 +import java.io.Serializable;
   42.52 +import java.lang.ref.WeakReference;
   42.53 +import java.lang.ref.Reference;
   42.54 +import java.util.ArrayList;
   42.55 +import java.util.Arrays;
   42.56 +import java.util.Collection;
   42.57 +import java.util.Collections;
   42.58 +import java.util.Iterator;
   42.59 +import java.util.LinkedList;
   42.60 +import java.util.List;
   42.61 +import java.util.concurrent.Executors;
   42.62 +import java.util.concurrent.TimeUnit;
   42.63 +import javax.swing.ActionMap;
   42.64 +import javax.swing.InputMap;
   42.65 +import org.netbeans.junit.NbTestCase;
   42.66 +import org.openide.util.Lookup;
   42.67 +import org.openide.util.Lookup.Template;
   42.68 +import org.openide.util.LookupEvent;
   42.69 +import org.openide.util.LookupListener;
   42.70 +
   42.71 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   42.72 +public class AbstractLookupBaseHid extends NbTestCase {
   42.73 +    private static AbstractLookupBaseHid running;
   42.74 +
   42.75 +    /** instance content to work with */
   42.76 +    InstanceContent ic;
   42.77 +    /** the lookup to work on */
   42.78 +    protected Lookup instanceLookup;
   42.79 +    /** the lookup created to work with */
   42.80 +    private Lookup lookup;
   42.81 +    /** implementation of methods that can influence the behaviour */
   42.82 +    Impl impl;
   42.83 +    
   42.84 +    protected AbstractLookupBaseHid(String testName, Impl impl) {
   42.85 +        super(testName);
   42.86 +        if (impl == null && (this instanceof Impl)) {
   42.87 +            impl = (Impl)this;
   42.88 +        }
   42.89 +        this.impl = impl;
   42.90 +    }
   42.91 +    
   42.92 +    protected @Override void setUp() {
   42.93 +        this.ic = new InstanceContent ();
   42.94 +        
   42.95 +        beforeActualTest(getName());
   42.96 +        
   42.97 +        this.instanceLookup = createInstancesLookup (ic);
   42.98 +        this.lookup = createLookup (instanceLookup);
   42.99 +        running = this;
  42.100 +    }        
  42.101 +    
  42.102 +    protected @Override void tearDown() {
  42.103 +        running = null;
  42.104 +    }
  42.105 +    
  42.106 +    /** The methods to influence test behaviour */
  42.107 +    public static interface Impl {
  42.108 +        /** Creates the initial abstract lookup.
  42.109 +         */
  42.110 +        public Lookup createInstancesLookup (InstanceContent ic);
  42.111 +        /** Creates an lookup for given lookup. This class just returns 
  42.112 +         * the object passed in, but subclasses can be different.
  42.113 +         * @param lookup in lookup
  42.114 +         * @return a lookup to use
  42.115 +         */
  42.116 +        public Lookup createLookup (Lookup lookup);
  42.117 +        
  42.118 +        /** If the impl has any caches that would prevent the system
  42.119 +         * to not garbage collect correctly, then clear them now.
  42.120 +         */
  42.121 +        public void clearCaches ();
  42.122 +    }
  42.123 +    
  42.124 +    private Lookup createInstancesLookup (InstanceContent ic) {
  42.125 +        return impl.createInstancesLookup (ic);
  42.126 +    }
  42.127 +    
  42.128 +    private Lookup createLookup (Lookup lookup) {
  42.129 +        return impl.createLookup (lookup);
  42.130 +    }
  42.131 +    
  42.132 +    /** instances that we register */
  42.133 +    private static Object[] INSTANCES = new Object[] {
  42.134 +        new Integer (10), 
  42.135 +        new Object ()
  42.136 +    };
  42.137 +    
  42.138 +    /** Test if first is really first.
  42.139 +     */
  42.140 +    public void testFirst () {
  42.141 +        Integer i1 = 1;
  42.142 +        Integer i2 = 2;
  42.143 +        
  42.144 +        ic.add (i1);
  42.145 +        ic.add (i2);
  42.146 +        
  42.147 +        Integer found = lookup.lookup(Integer.class);
  42.148 +        if (found != i1) {
  42.149 +            fail ("First object is not first: " + found + " != " + i1);
  42.150 +        }
  42.151 +        
  42.152 +        List<Integer> list = new ArrayList<Integer>();
  42.153 +        list.add (i2);
  42.154 +        list.add (i1);
  42.155 +        ic.set (list, null);
  42.156 +        
  42.157 +        found = lookup.lookup (Integer.class);
  42.158 +        if (found != i2) {
  42.159 +            fail ("Second object is not first after reorder: " + found + " != " + i2);
  42.160 +        }
  42.161 +        
  42.162 +    }
  42.163 +
  42.164 +    public void testToString() {
  42.165 +        String txt = lookup.toString();
  42.166 +        assertNotNull("Something is there", txt);
  42.167 +        assertTrue("Something2: " + txt, txt.length() > 0);
  42.168 +    }
  42.169 +
  42.170 +
  42.171 +    /** Tests ordering of items in the lookup.
  42.172 +    */
  42.173 +    public void testOrder () {
  42.174 +        addInstances (INSTANCES);
  42.175 +
  42.176 +        if (INSTANCES[0] != lookup.lookup (INSTANCES[0].getClass ())) {
  42.177 +            fail ("First object in intances not found");
  42.178 +        }
  42.179 +
  42.180 +        Iterator<?> all = lookup.lookupAll(Object.class).iterator();
  42.181 +        checkIterator ("Difference between instances added and found", all, Arrays.asList (INSTANCES));
  42.182 +    }
  42.183 +    
  42.184 +    /** Checks the reorder of items in lookup reflects the result.
  42.185 +     * Testing both classes and interfaces, because they are often treated
  42.186 +     * especially.
  42.187 +     */
  42.188 +    public void testReorder () {
  42.189 +        String s1 = "s2";
  42.190 +        String s2 = "s1";
  42.191 +        Runnable r1 = new Runnable () {
  42.192 +            public void run () {}
  42.193 +        };
  42.194 +        Runnable r2 = new Runnable () {
  42.195 +            public void run () {}
  42.196 +        };
  42.197 +        List<Object> l = new ArrayList<Object>();
  42.198 +
  42.199 +        l.add (s1);
  42.200 +        l.add (s2);
  42.201 +        l.add (r1);
  42.202 +        l.add (r2);
  42.203 +        ic.set (l, null);
  42.204 +     
  42.205 +        assertEquals ("s1 is found", s1, lookup.lookup (String.class));
  42.206 +        assertEquals ("r1 is found", r1, lookup.lookup (Runnable.class));
  42.207 +        
  42.208 +        Collections.reverse (l);
  42.209 +        
  42.210 +        ic.set (l, null);
  42.211 +        
  42.212 +        assertEquals ("s2 is found", s2, lookup.lookup (String.class));
  42.213 +        assertEquals ("r2 is found", r2, lookup.lookup (Runnable.class));
  42.214 +    }
  42.215 +    
  42.216 +    /** Tries to set empty collection to the lookup.
  42.217 +     */
  42.218 +    public void testSetEmpty () {
  42.219 +        ic.add ("A serializable string");
  42.220 +        lookup.lookup (Serializable.class);
  42.221 +        
  42.222 +        ic.set (Collections.emptyList(), null);
  42.223 +    }
  42.224 +    
  42.225 +    /** Tests a more complex reorder on nodes.
  42.226 +     */
  42.227 +    public void testComplexReorder () {
  42.228 +        Integer i1 = 1;
  42.229 +        Long i2 = 2L;
  42.230 +        
  42.231 +        List<Object> l = new ArrayList<Object>();
  42.232 +        l.add (i1);
  42.233 +        l.add (i2);
  42.234 +        ic.set (l, null);
  42.235 +        
  42.236 +        assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
  42.237 +        assertEquals ("Find long", i2, lookup.lookup (Long.class));
  42.238 +        assertEquals ("Find number", i1, lookup.lookup (Number.class));
  42.239 +        
  42.240 +        Collections.reverse (l);
  42.241 +        
  42.242 +        ic.set (l, null);
  42.243 +        
  42.244 +        assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
  42.245 +        assertEquals ("Find long", i2, lookup.lookup (Long.class));
  42.246 +        assertEquals ("Find number", i2, lookup.lookup (Number.class));
  42.247 +    }
  42.248 +    
  42.249 +    /** Checks whether setPairs keeps the order.
  42.250 +     */
  42.251 +    public void testSetPairs () {
  42.252 +        // test setPairs method
  42.253 +        List<Object> li = new ArrayList<Object>();
  42.254 +        li.addAll (Arrays.asList (INSTANCES));
  42.255 +        ic.set (li, null);
  42.256 +        
  42.257 +        Lookup.Result<Object> res = lookup.lookupResult(Object.class);
  42.258 +        Iterator<?> all = res.allInstances().iterator();
  42.259 +        checkIterator ("Original order not kept", all, li);
  42.260 +        
  42.261 +        // reverse the order
  42.262 +        Collections.reverse (li);
  42.263 +        
  42.264 +        // change the pairs
  42.265 +        LL listener = new LL (res);
  42.266 +        res.addLookupListener (listener);
  42.267 +        ic.set (li, null);
  42.268 +        if (listener.getCount () != 1) {
  42.269 +            fail ("Result has not changed even we set reversed order");
  42.270 +        }
  42.271 +        
  42.272 +        all = res.allInstances ().iterator ();
  42.273 +        checkIterator ("Reversed order not kept", all, li);
  42.274 +    }
  42.275 +
  42.276 +    /** Checks whether setPairs fires correct events.
  42.277 +     */
  42.278 +    public void testSetPairsFire () {
  42.279 +        // test setPairs method
  42.280 +        List<Object> li = new ArrayList<Object>();
  42.281 +        li.addAll (Arrays.asList (INSTANCES));
  42.282 +        ic.set (li, null);
  42.283 +        
  42.284 +        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
  42.285 +        Iterator<?> all = res.allInstances().iterator();
  42.286 +        checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
  42.287 +        
  42.288 +        // change the pairs
  42.289 +        LL listener = new LL (res);
  42.290 +        res.addLookupListener (listener);
  42.291 +
  42.292 +        List<Object> l2 = new ArrayList<Object>(li);
  42.293 +        l2.remove (INSTANCES[0]);
  42.294 +        ic.set (l2, null);
  42.295 +
  42.296 +        all = lookup.lookupAll(Object.class).iterator();
  42.297 +        checkIterator ("The removed integer is not noticed", all, l2);
  42.298 +
  42.299 +        if (listener.getCount () != 1) {
  42.300 +            fail ("Nothing has not been fired");
  42.301 +        }
  42.302 +    }
  42.303 +
  42.304 +    /** Checks whether set pairs does not fire when they should not.
  42.305 +    */
  42.306 +    public void testSetPairsDoesNotFire () {
  42.307 +        Object tmp = new Object ();
  42.308 +
  42.309 +        List<Object> li = new ArrayList<Object>();
  42.310 +        li.add (tmp);
  42.311 +        li.addAll (Arrays.asList (INSTANCES));
  42.312 +        ic.set (li, null);
  42.313 +        
  42.314 +        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
  42.315 +        Iterator<?> all = res.allInstances ().iterator ();
  42.316 +        checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
  42.317 +        
  42.318 +        // change the pairs
  42.319 +        LL listener = new LL (res);
  42.320 +        res.addLookupListener (listener);
  42.321 +
  42.322 +        List<Object> l2 = new ArrayList<Object>(li);
  42.323 +        l2.remove (tmp);
  42.324 +        ic.set (l2, null);
  42.325 +
  42.326 +        all = lookup.lookupAll(Object.class).iterator();
  42.327 +        checkIterator ("The removed integer is not noticed", all, l2);
  42.328 +
  42.329 +        if (listener.getCount () != 0) {
  42.330 +            fail ("Something has been fired");
  42.331 +        }
  42.332 +    }
  42.333 +    
  42.334 +    /** Test whether after registration it is possible to find registered objects
  42.335 +    * 
  42.336 +     */
  42.337 +    public void testLookupAndAdd () throws Exception {
  42.338 +        addInstances (INSTANCES);
  42.339 +
  42.340 +        for (int i = 0; i < INSTANCES.length; i++) {
  42.341 +            Object obj = INSTANCES[i];
  42.342 +            findAll (lookup, obj.getClass (), true);
  42.343 +        }
  42.344 +    }
  42.345 +
  42.346 +    /** Tries to find all classes and superclasses in the lookup.
  42.347 +    */
  42.348 +    private void findAll(Lookup lookup, Class<?> clazz, boolean shouldBeThere) {
  42.349 +        if (clazz == null) return;
  42.350 +
  42.351 +        Object found = lookup.lookup (clazz);
  42.352 +        if (found == null) {
  42.353 +            if (shouldBeThere) {
  42.354 +                // should find at either instance or something else, but must
  42.355 +                // find at least something
  42.356 +                fail ("Lookup (" + clazz.getName () + ") found nothing");
  42.357 +            }
  42.358 +        } else {
  42.359 +            if (!shouldBeThere) {
  42.360 +                // should find at either instance or something else, but must
  42.361 +                // find at least something
  42.362 +                fail ("Lookup (" + clazz.getName () + ") found " + found);
  42.363 +            }
  42.364 +        }
  42.365 +
  42.366 +        Lookup.Result<?> res = lookup.lookupResult(clazz);
  42.367 +        Collection<?> collection = res.allInstances();
  42.368 +
  42.369 +        for (int i = 0; i < INSTANCES.length; i++) {
  42.370 +            boolean isSubclass = clazz.isInstance (INSTANCES[i]);
  42.371 +            boolean isThere = collection.contains (INSTANCES[i]);
  42.372 +
  42.373 +            if (isSubclass != isThere) {
  42.374 +                // a problem found
  42.375 +                // should find at either instance or something else, but must
  42.376 +                // find at least something
  42.377 +                fail ("Lookup.Result (" + clazz.getName () + ") for " + INSTANCES[i] + " is subclass: " + isSubclass + " isThere: " + isThere);
  42.378 +            }
  42.379 +        }
  42.380 +
  42.381 +        // go on for superclasses
  42.382 +
  42.383 +        findAll (lookup, clazz.getSuperclass (), shouldBeThere);
  42.384 +
  42.385 +        Class[] ies = clazz.getInterfaces ();
  42.386 +        for (int i = 0; i < ies.length; i++) {
  42.387 +            findAll (lookup, ies[i], shouldBeThere);
  42.388 +        }
  42.389 +    }
  42.390 +    
  42.391 +    /** Test if it is possible to remove a registered object. */
  42.392 +    public void testRemoveRegisteredObject() {
  42.393 +        Integer inst = new Integer(10);
  42.394 +        
  42.395 +        ic.add(inst);
  42.396 +        if (lookup.lookup(inst.getClass()) == null) {
  42.397 +            // should find an instance
  42.398 +            fail("Lookup (" + inst.getClass().getName () + ") found nothing");
  42.399 +        }
  42.400 +        
  42.401 +        ic.remove(inst);
  42.402 +        if (lookup.lookup(inst.getClass()) != null) {
  42.403 +            // should NOT find an instance
  42.404 +            fail("Lookup (" + inst.getClass().getName () +
  42.405 +                ") found an instance after remove operation");
  42.406 +        }
  42.407 +    }
  42.408 +    
  42.409 +    public void testCanReturnReallyStrangeResults () throws Exception {
  42.410 +        class QueryingPair extends AbstractLookup.Pair<Object> {
  42.411 +            private Integer i = 434;
  42.412 +            
  42.413 +            //
  42.414 +            // do the test
  42.415 +            //
  42.416 +            
  42.417 +            public void doTest () throws Exception {
  42.418 +                ic.add (i);
  42.419 +                ic.addPair (this);
  42.420 +                
  42.421 +                Object found = lookup.lookup (QueryingPair.class);
  42.422 +                assertEquals ("This object is found", this, found);
  42.423 +            }
  42.424 +            
  42.425 +            
  42.426 +            //
  42.427 +            // Implementation of pair
  42.428 +            // 
  42.429 +        
  42.430 +            public String getId() {
  42.431 +                return getType ().toString();
  42.432 +            }
  42.433 +
  42.434 +            public String getDisplayName() {
  42.435 +                return getId ();
  42.436 +            }
  42.437 +
  42.438 +            public Class<?> getType() {
  42.439 +                return getClass ();
  42.440 +            }
  42.441 +
  42.442 +            protected boolean creatorOf(Object obj) {
  42.443 +                return obj == this;
  42.444 +            }
  42.445 +
  42.446 +            protected boolean instanceOf(Class<?> c) {
  42.447 +                assertEquals ("Integer found or exception is thrown", i, lookup.lookup (Integer.class));
  42.448 +                return c.isAssignableFrom(getType ());
  42.449 +            }
  42.450 +
  42.451 +            public Object getInstance() {
  42.452 +                return this;
  42.453 +            }
  42.454 +            
  42.455 +            
  42.456 +        }
  42.457 +        
  42.458 +        
  42.459 +        QueryingPair qp = new QueryingPair ();
  42.460 +        qp.doTest ();
  42.461 +    }
  42.462 +    
  42.463 +    /** Test of firing events. */
  42.464 +    public void testLookupListener() {
  42.465 +        Object inst = 10;
  42.466 +        Lookup.Result<?> res = lookup.lookupResult(inst.getClass());
  42.467 +        res.allInstances ();
  42.468 +        
  42.469 +        LL listener = new LL(res);
  42.470 +        res.addLookupListener(listener);
  42.471 +        
  42.472 +        ic.add(inst);
  42.473 +        if (listener.getCount() == 0) {
  42.474 +            fail("None event fired during NbLookup.addPair()");
  42.475 +        }
  42.476 +        
  42.477 +        ic.remove(inst);
  42.478 +        if (listener.getCount() == 0) {
  42.479 +            fail("None event fired during NbLookup.removePair()");
  42.480 +        }
  42.481 +        
  42.482 +        ic.add(inst);
  42.483 +        if (listener.getCount() == 0) {
  42.484 +            fail("None event fired during second NbLookup.addPair()");
  42.485 +        }
  42.486 +        
  42.487 +        ic.remove(inst);
  42.488 +        if (listener.getCount() == 0) {
  42.489 +            fail("None event fired during second NbLookup.removePair()");
  42.490 +        }
  42.491 +    }
  42.492 +    
  42.493 +    /** Testing identity of the lookup.
  42.494 +     */
  42.495 +    public void testId () {
  42.496 +        Lookup.Template<?> templ;
  42.497 +        int cnt;
  42.498 +        
  42.499 +        addInstances (INSTANCES);
  42.500 +        
  42.501 +        Lookup.Result<?> res = lookup.lookupResult(Object.class);
  42.502 +        for (AbstractLookup.Item<?> item : res.allItems()) {
  42.503 +            
  42.504 +            templ = new Lookup.Template<Object>(null, item.getId(), null);
  42.505 +            cnt = lookup.lookup (templ).allInstances ().size ();
  42.506 +            if (cnt != 1) {
  42.507 +                fail ("Identity lookup failed. Instances = " + cnt);
  42.508 +            }
  42.509 +
  42.510 +            templ = makeTemplate(item.getType(), item.getId());
  42.511 +            cnt = lookup.lookup (templ).allInstances ().size ();
  42.512 +            if (cnt != 1) {
  42.513 +                fail ("Identity lookup with type failed. Instances = " + cnt);
  42.514 +            }
  42.515 +            
  42.516 +            templ = makeTemplate(this.getClass(), item.getId());
  42.517 +            cnt = lookup.lookup (templ).allInstances ().size ();
  42.518 +            if (cnt != 0) {
  42.519 +                fail ("Identity lookup with wrong type failed. Instances = " + cnt);
  42.520 +            }
  42.521 +            
  42.522 +            templ = new Lookup.Template<Object>(null, null, item.getInstance());
  42.523 +            cnt = lookup.lookup (templ).allInstances ().size ();
  42.524 +            if (cnt != 1) {
  42.525 +                fail ("Instance lookup failed. Instances = " + cnt);
  42.526 +            }
  42.527 +
  42.528 +            templ = new Lookup.Template<Object>(null, item.getId(), item.getInstance());
  42.529 +            cnt = lookup.lookup (templ).allInstances ().size ();
  42.530 +            if (cnt != 1) {
  42.531 +                fail ("Instance & identity lookup failed. Instances = " + cnt);
  42.532 +            }
  42.533 +            
  42.534 +        }
  42.535 +    }
  42.536 +    private static <T> Lookup.Template<T> makeTemplate(Class<T> clazz, String id) { // captures type parameter
  42.537 +        return new Lookup.Template<T>(clazz, id, null);
  42.538 +    }
  42.539 +    
  42.540 +    /** Tests adding and removing.
  42.541 +     */
  42.542 +    public void testAddAndRemove () throws Exception {
  42.543 +        Object map = new javax.swing.ActionMap ();
  42.544 +        LL ll = new LL ();
  42.545 +        
  42.546 +        Lookup.Result<?> res = lookup.lookupResult(map.getClass());
  42.547 +        res.allItems();
  42.548 +        res.addLookupListener (ll);
  42.549 +        ll.source = res;
  42.550 +        
  42.551 +        ic.add (map);
  42.552 +        
  42.553 +        assertEquals ("First change when adding", ll.getCount (), 1);
  42.554 +        
  42.555 +        ic.remove (map);
  42.556 +        
  42.557 +        assertEquals ("Second when removing", ll.getCount (), 1);
  42.558 +        
  42.559 +        ic.add (map);
  42.560 +        
  42.561 +        assertEquals ("Third when readding", ll.getCount (), 1);
  42.562 +        
  42.563 +        ic.remove (map);
  42.564 +        
  42.565 +        assertEquals ("Forth when reremoving", ll.getCount (), 1);
  42.566 +        
  42.567 +    }
  42.568 +    
  42.569 +    /** Will a class garbage collect even it is registered in lookup.
  42.570 +     */
  42.571 +    public void testGarbageCollect () throws Exception {
  42.572 +        ClassLoader l = new CL ();
  42.573 +        Class<?> c = l.loadClass(Garbage.class.getName());
  42.574 +        Reference<?> ref = new WeakReference<Object>(c);
  42.575 +
  42.576 +        lookup.lookup (c);
  42.577 +        
  42.578 +        // now test garbage collection
  42.579 +        c = null;
  42.580 +        l = null;
  42.581 +        impl.clearCaches ();
  42.582 +        assertGC ("The classloader has not been garbage collected!", ref);
  42.583 +    }
  42.584 +                
  42.585 +    /** Items are the same as results.
  42.586 +     */
  42.587 +    public void testItemsAndIntances () {
  42.588 +        addInstances (INSTANCES);
  42.589 +        
  42.590 +        Lookup.Result<Object> r = lookup.lookupResult(Object.class);
  42.591 +        Collection<? extends Lookup.Item<?>> items = r.allItems();
  42.592 +        Collection<?> insts = r.allInstances();
  42.593 +        
  42.594 +        if (items.size () != insts.size ()) {
  42.595 +            fail ("Different size of sets");
  42.596 +        }
  42.597 +
  42.598 +        for (Lookup.Item<?> item : items) {
  42.599 +            if (!insts.contains (item.getInstance ())) {
  42.600 +                fail ("Intance " + item.getInstance () + " is missing in " + insts);
  42.601 +            }
  42.602 +        }
  42.603 +    }
  42.604 +    
  42.605 +    /** Checks search for interface.
  42.606 +     */
  42.607 +    public void testSearchForInterface () {
  42.608 +        Lookup.Template<Serializable> t = new Lookup.Template<Serializable>(Serializable.class, null, null);
  42.609 +        
  42.610 +        assertNull("Nothing to find", lookup.lookupItem (t));
  42.611 +        
  42.612 +        Serializable s = new Serializable () {};
  42.613 +        ic.add (s);
  42.614 +        
  42.615 +        Lookup.Item item = lookup.lookupItem (t);
  42.616 +        assertNotNull ("Something found", item);
  42.617 +    }
  42.618 +
  42.619 +    /** Test to add broken item if it incorrectly answers instanceOf questions.
  42.620 +     */
  42.621 +    public void testIncorectInstanceOf40364 () {
  42.622 +        final Long sharedLong = new Long (0);
  42.623 +        
  42.624 +        class P extends AbstractLookup.Pair<Object> {
  42.625 +            public boolean isLong;
  42.626 +            
  42.627 +            P (boolean b) {
  42.628 +                isLong = b;
  42.629 +            }
  42.630 +            
  42.631 +            protected boolean creatorOf (Object obj) {
  42.632 +                return obj == sharedLong;
  42.633 +            }
  42.634 +            
  42.635 +            public String getDisplayName () {
  42.636 +                return "";
  42.637 +            }
  42.638 +            
  42.639 +            public String getId () {
  42.640 +                return "";
  42.641 +            }
  42.642 +            
  42.643 +            public Object getInstance () {
  42.644 +                return sharedLong;
  42.645 +            }
  42.646 +            
  42.647 +            public Class<?> getType() {
  42.648 +                return isLong ? Long.class : Number.class;
  42.649 +            }
  42.650 +            
  42.651 +            protected boolean instanceOf(Class<?> c) {
  42.652 +                return c.isAssignableFrom (getType ());
  42.653 +            }
  42.654 +    
  42.655 +            public @Override int hashCode() {
  42.656 +                return getClass ().hashCode ();
  42.657 +            }    
  42.658 +
  42.659 +            public @Override boolean equals(Object obj) {
  42.660 +                return obj != null && getClass ().equals (obj.getClass ());
  42.661 +            }
  42.662 +        }
  42.663 +        
  42.664 +        // to create the right structure in the lookup
  42.665 +        lookup.lookup (Object.class);
  42.666 +        lookup.lookup (Long.class);
  42.667 +        lookup.lookup (Number.class);
  42.668 +        
  42.669 +        P lng1 = new P (true);
  42.670 +        ic.addPair (lng1);
  42.671 +
  42.672 +        P lng2 = new P (false);
  42.673 +        ic.setPairs (Collections.singleton (lng2));
  42.674 +        
  42.675 +        Collection<? extends Lookup.Item<?>> res = lookup.lookupResult(Object.class).allItems();
  42.676 +        assertEquals ("Just one pair", 1, res.size ());
  42.677 +    }
  42.678 +
  42.679 +    public void testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly () throws Exception {
  42.680 +        class X implements TestInterfaceInheritanceA, TestInterfaceInheritanceB {
  42.681 +        }
  42.682 +        final X shared = new X ();
  42.683 +        
  42.684 +        class P extends AbstractLookup.Pair<Object> {
  42.685 +            public int howLong;
  42.686 +            
  42.687 +            P (int b) {
  42.688 +                howLong = b;
  42.689 +            }
  42.690 +            
  42.691 +            protected boolean creatorOf (Object obj) {
  42.692 +                return obj == shared;
  42.693 +            }
  42.694 +            
  42.695 +            public String getDisplayName () {
  42.696 +                return "";
  42.697 +            }
  42.698 +            
  42.699 +            public String getId () {
  42.700 +                return "";
  42.701 +            }
  42.702 +            
  42.703 +            public Object getInstance () {
  42.704 +                return shared;
  42.705 +            }
  42.706 +            
  42.707 +            public Class<?> getType() {
  42.708 +                return howLong == 0 ? TestInterfaceInheritanceB.class : TestInterfaceInheritanceA.class;
  42.709 +            }
  42.710 +            
  42.711 +            protected boolean instanceOf(Class<?> c) {
  42.712 +                return c.isAssignableFrom (getType ());
  42.713 +            }
  42.714 +    
  42.715 +            public @Override int hashCode() {
  42.716 +                return getClass ().hashCode ();
  42.717 +            }    
  42.718 +
  42.719 +            public @Override boolean equals(Object obj) {
  42.720 +                if (obj instanceof P) {
  42.721 +                    P p = (P)obj;
  42.722 +                    if (this.howLong > 0) {
  42.723 +                        this.howLong--;
  42.724 +                        return false;
  42.725 +                    }
  42.726 +                    if (p.howLong > 0) {
  42.727 +                        p.howLong--;
  42.728 +                        return false;
  42.729 +                    }
  42.730 +                    return getClass ().equals (p.getClass ());
  42.731 +                }
  42.732 +                return false;
  42.733 +            }
  42.734 +        }
  42.735 +        
  42.736 +        // to create the right structure in the lookup
  42.737 +        Lookup.Result<?> a = lookup.lookupResult(TestInterfaceInheritanceA.class);
  42.738 +        Lookup.Result<?> b = lookup.lookupResult(TestInterfaceInheritanceB.class);
  42.739 +        
  42.740 +        P lng1 = new P (0);
  42.741 +        ic.addPair (lng1);
  42.742 +        
  42.743 +        assertEquals ("One in a", 1, a.allItems ().size ());
  42.744 +        assertEquals ("One in b", 1, b.allItems ().size ());
  42.745 +
  42.746 +        P lng2 = new P (1);
  42.747 +        
  42.748 +
  42.749 +        /* Following call used to generate this exception:
  42.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
  42.751 +	at org.openide.util.lookup.ALPairComparator.compare(ALPairComparator.java:52)
  42.752 +	at java.util.Arrays.mergeSort(Arrays.java:1284)
  42.753 +	at java.util.Arrays.sort(Arrays.java:1223)
  42.754 +	at java.util.Collections.sort(Collections.java:159)
  42.755 +	at org.openide.util.lookup.InheritanceTree.retainAllInterface(InheritanceTree.java:753)
  42.756 +	at org.openide.util.lookup.InheritanceTree.retainAll(InheritanceTree.java:183)
  42.757 +	at org.openide.util.lookup.DelegatingStorage.retainAll(DelegatingStorage.java:83)
  42.758 +	at org.openide.util.lookup.AbstractLookup.setPairsAndCollectListeners(AbstractLookup.java:238)
  42.759 +	at org.openide.util.lookup.AbstractLookup.setPairs(AbstractLookup.java:203)
  42.760 +	at org.openide.util.lookup.AbstractLookup$Content.setPairs(AbstractLookup.java:885)
  42.761 +	at org.openide.util.lookup.AbstractLookupBaseHid.testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly(AbstractLookupBaseHid.java:696)
  42.762 +	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  42.763 +	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  42.764 +	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  42.765 +	at org.netbeans.junit.NbTestCase.run(NbTestCase.java:119)
  42.766 +    */  
  42.767 +        ic.setPairs (Collections.singleton (lng2));
  42.768 +
  42.769 +        
  42.770 +    }
  42.771 +    
  42.772 +    public void testInstancesArePreservedFoundWhenFixing48590 () throws Exception {
  42.773 +        class X implements Runnable, Serializable {
  42.774 +            public void run () {
  42.775 +                
  42.776 +            }
  42.777 +            
  42.778 +            public void assertOnlyMe (String msg, Lookup.Result<?> res) {
  42.779 +                Collection<?> col = res.allInstances();
  42.780 +                assertEquals (msg + " just one", 1, col.size ());
  42.781 +                assertSame (msg + " and it is me", this, col.iterator ().next ());
  42.782 +            }
  42.783 +        }
  42.784 +        
  42.785 +        Lookup.Result<?> runnable = lookup.lookupResult(Runnable.class);
  42.786 +        Lookup.Result<?> serial = lookup.lookupResult(Serializable.class);
  42.787 +        
  42.788 +        
  42.789 +        X x = new X ();
  42.790 +        ic.add (x);
  42.791 +        
  42.792 +        
  42.793 +        x.assertOnlyMe ("x implements it (1)", runnable);
  42.794 +        x.assertOnlyMe ("x implements it (2)", serial);
  42.795 +        
  42.796 +        ic.set (Collections.singleton (x), null);
  42.797 +        
  42.798 +        x.assertOnlyMe ("x implements it (3)", runnable);
  42.799 +        x.assertOnlyMe ("x implements it (4)", serial);
  42.800 +    }
  42.801 +    
  42.802 +    /** Testing lookup of inherited classes. */
  42.803 +    public void testInheritance() {
  42.804 +        class A {}
  42.805 +        class B extends A implements java.rmi.Remote {}
  42.806 +        class BB extends B {}
  42.807 +        class C extends A implements java.rmi.Remote {}
  42.808 +        class D extends A {}
  42.809 +        
  42.810 +        A[] types = {new B(), new BB(), new C(), new D()};
  42.811 +        
  42.812 +        for (int i = 0; i < types.length; i++) {
  42.813 +            ic.add(types[i]);
  42.814 +            if (lookup.lookup(types[i].getClass()) == null) {
  42.815 +                // should find an instance
  42.816 +                fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
  42.817 +            }
  42.818 +        }
  42.819 +        
  42.820 +        int size1, size2;
  42.821 +        
  42.822 +        //interface query
  42.823 +        size1 = lookup.lookupAll(java.rmi.Remote.class).size();
  42.824 +        size2 = countInstances(types, java.rmi.Remote.class);
  42.825 +        
  42.826 +        if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
  42.827 +        
  42.828 +        // superclass query
  42.829 +        size1 = lookup.lookupAll(A.class).size();
  42.830 +        size2 = countInstances(types, A.class);
  42.831 +        
  42.832 +        if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
  42.833 +    }
  42.834 +    
  42.835 +    /** Test interface inheritance.
  42.836 +     */
  42.837 +    public void testInterfaceInheritance() {
  42.838 +        TestInterfaceInheritanceA[] types = {
  42.839 +            new TestInterfaceInheritanceB() {},
  42.840 +            new TestInterfaceInheritanceBB() {},
  42.841 +            new TestInterfaceInheritanceC() {},
  42.842 +            new TestInterfaceInheritanceD() {}
  42.843 +        };
  42.844 +        
  42.845 +        for (int i = 0; i < types.length; i++) {
  42.846 +            ic.add(types[i]);
  42.847 +            if (lookup.lookup(types[i].getClass()) == null) {
  42.848 +                // should find an instance
  42.849 +                fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
  42.850 +            }
  42.851 +        }
  42.852 +        
  42.853 +        int size1, size2;
  42.854 +        
  42.855 +        //interface query
  42.856 +        LL l = new LL ();
  42.857 +        Lookup.Result<?> res = lookup.lookupResult(java.rmi.Remote.class);
  42.858 +        l.source = res;
  42.859 +        size1 = res.allInstances().size();
  42.860 +        size2 = countInstances(types, java.rmi.Remote.class);
  42.861 +        
  42.862 +        if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
  42.863 +        
  42.864 +        // superclass query
  42.865 +        size1 = lookup.lookupAll(TestInterfaceInheritanceA.class).size();
  42.866 +        size2 = countInstances(types, TestInterfaceInheritanceA.class);
  42.867 +        
  42.868 +        if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
  42.869 +        
  42.870 +        res.addLookupListener (l);
  42.871 +        ic.remove (types[0]);
  42.872 +        
  42.873 +        if (l.getCount () != 1) {
  42.874 +            fail ("No notification that a Remote is removed");
  42.875 +        }
  42.876 +    }
  42.877 +    
  42.878 +    /** Checks whether the AbstractLookup is guarded against modifications
  42.879 +     * while doing some kind of modification.
  42.880 +     */
  42.881 +    public void testModificationArePreventedWhenDoingModifications () throws Exception {
  42.882 +        BrokenPair broken = new BrokenPair (true, false);
  42.883 +        ic.addPair (broken);
  42.884 +        
  42.885 +        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
  42.886 +        Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
  42.887 +        assertEquals ("Broken is found", broken, item);
  42.888 +    }
  42.889 +    
  42.890 +    public void testModificationArePreventedWhenDoingModificationsResult () throws Exception {
  42.891 +        BrokenPair broken = new BrokenPair (false, true);
  42.892 +        ic.addPair (broken);
  42.893 +        
  42.894 +        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
  42.895 +        
  42.896 +        Collection<? extends BrokenPair> c = lookup.lookup (templ).allInstances();
  42.897 +        assertEquals ("One item", 1, c.size ());
  42.898 +        assertEquals ("Broken is found again", broken, c.iterator().next ());
  42.899 +    }
  42.900 +    
  42.901 +    public void testModificationArePreventedWhenDoingModificationsItemAndResult () throws Exception {
  42.902 +        BrokenPair broken = new BrokenPair (false, true);
  42.903 +        ic.addPair (broken);
  42.904 +        
  42.905 +        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
  42.906 +        Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
  42.907 +        assertEquals ("Broken is found", broken, item);
  42.908 +        
  42.909 +        Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
  42.910 +        assertEquals ("One item", 1, c.size ());
  42.911 +        assertEquals ("Broken is found again", broken, c.iterator().next ());
  42.912 +    }
  42.913 +
  42.914 +    public void testModificationArePreventedWhenDoingModificationsResultAndItem () throws Exception {
  42.915 +        BrokenPair broken = new BrokenPair (false, true);
  42.916 +        ic.addPair (broken);
  42.917 +        
  42.918 +        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
  42.919 +        Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
  42.920 +        assertEquals ("One item", 1, c.size ());
  42.921 +        assertEquals ("Broken is found again", broken, c.iterator().next ());
  42.922 +        
  42.923 +        Object item = lookup.lookupItem (templ);
  42.924 +        assertEquals ("Broken is found", broken, item);
  42.925 +    }
  42.926 +    
  42.927 +    public void testAddALotOfPairsIntoTheLookupOneByOne () throws Exception {
  42.928 +        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
  42.929 +        for (int i = 0; i < 1000; i++) {
  42.930 +            ic.add(i);
  42.931 +        }
  42.932 +        assertEquals (
  42.933 +            "there is the right count", 
  42.934 +            1000, 
  42.935 +            res.allItems().size ()
  42.936 +        );
  42.937 +    }
  42.938 +    
  42.939 +    public void testAddALotOfPairsIntoTheLookup () throws Exception {
  42.940 +        List<Integer> arr = new ArrayList<Integer>();
  42.941 +        for (int i = 0; i < 1000; i++) {
  42.942 +            arr.add(i);
  42.943 +        }
  42.944 +        ic.set (arr, null);
  42.945 +        
  42.946 +        assertEquals (
  42.947 +            "there is the right count", 
  42.948 +            1000, 
  42.949 +            lookup.lookupResult(Integer.class).allItems().size()
  42.950 +        );
  42.951 +    }
  42.952 +
  42.953 +    
  42.954 +    public void testDoubleAddIssue35274 () throws Exception {
  42.955 +        class P extends AbstractLookup.Pair<Object> {
  42.956 +            protected boolean creatorOf(Object obj) { return false; }
  42.957 +            public String getDisplayName() { return ""; }
  42.958 +            public String getId() { return ""; }
  42.959 +            public Object getInstance() { return null; }
  42.960 +            public Class<?> getType() { return Object.class; }
  42.961 +            protected boolean instanceOf(Class<?> c) { return c.isAssignableFrom(getType ()); }
  42.962 +            public @Override int hashCode() {return getClass().hashCode();}
  42.963 +            public @Override boolean equals(Object obj) {return getClass() == obj.getClass();}
  42.964 +        }
  42.965 +        
  42.966 +        P p = new P ();
  42.967 +        
  42.968 +        ic.addPair (p);
  42.969 +        ic.addPair (p);
  42.970 +        
  42.971 +        Lookup.Result<Object> result = lookup.lookupResult(Object.class);
  42.972 +        Collection res = result.allItems ();
  42.973 +        assertEquals ("One item there", 1, res.size ());
  42.974 +        assertTrue ("It is the p", p == res.iterator ().next ());
  42.975 +        
  42.976 +        P p2 = new P ();
  42.977 +        ic.addPair (p2);
  42.978 +        
  42.979 +        Reference<?> ref = new WeakReference<Object>(result);
  42.980 +        result = null;
  42.981 +        assertGC ("The result can disappear", ref);
  42.982 +        
  42.983 +        impl.clearCaches ();
  42.984 +        
  42.985 +        result = lookup.lookupResult(Object.class);
  42.986 +        res = result.allItems ();
  42.987 +        assertEquals ("One item is still there", 1, res.size ());
  42.988 +        assertTrue ("But the p2 replaced p", p2 == res.iterator ().next ());
  42.989 +        
  42.990 +    }
  42.991 +    
  42.992 +    /** Test for proper serialization.
  42.993 +     */
  42.994 +    public void testSerializationSupport () throws Exception {
  42.995 +        doSerializationSupport (1);
  42.996 +    }
  42.997 +    public void testDoubleSerializationSupport () throws Exception {
  42.998 +        doSerializationSupport (2);
  42.999 +    }
 42.1000 +
 42.1001 +    private void doSerializationSupport (int count) throws Exception {
 42.1002 +        if (lookup instanceof Serializable) {
 42.1003 +            ic.addPair (new SerialPair ("1"));
 42.1004 +            ic.addPair (new SerialPair ("2"));
 42.1005 +            ic.addPair (new SerialPair ("3"));
 42.1006 +
 42.1007 +            Lookup l = (Lookup)reserialize(lookup);
 42.1008 +
 42.1009 +            assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
 42.1010 +
 42.1011 +            assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
 42.1012 +
 42.1013 +            while (count-- > 0) {
 42.1014 +                l = (Lookup)reserialize(l);
 42.1015 +            }
 42.1016 +
 42.1017 +            assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
 42.1018 +
 42.1019 +            assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
 42.1020 +        }
 42.1021 +    }
 42.1022 +
 42.1023 +    /** When a lookup with two different versions of the same class 
 42.1024 +     * get's serialized, the results may be very bad. 
 42.1025 +     */
 42.1026 +    public void testSerializationOfTwoClassesWithTheSameName () throws Exception {
 42.1027 +        if (lookup instanceof Serializable) {
 42.1028 +            doTwoSerializedClasses (false, false);
 42.1029 +        }
 42.1030 +    }
 42.1031 +    public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSave () throws Exception {
 42.1032 +        if (lookup instanceof Serializable) {
 42.1033 +            doTwoSerializedClasses (true, false);
 42.1034 +        }
 42.1035 +    }
 42.1036 +    public void testSerializationOfTwoClassesWithTheSameNameWithBroken () throws Exception {
 42.1037 +        if (lookup instanceof Serializable) {
 42.1038 +            doTwoSerializedClasses (false, true);
 42.1039 +        }
 42.1040 +    }
 42.1041 +    public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSaveWithBroken () throws Exception {
 42.1042 +        if (lookup instanceof Serializable) {
 42.1043 +            doTwoSerializedClasses (true, true);
 42.1044 +        }
 42.1045 +    }
 42.1046 +   
 42.1047 +    private void doTwoSerializedClasses (boolean queryBeforeSerialization, boolean useBroken) throws Exception {
 42.1048 +        ClassLoader loader = new CL ();
 42.1049 +        Class c = loader.loadClass (Garbage.class.getName ());
 42.1050 +
 42.1051 +        // in case of InheritanceTree it creates a slot for class Garbage
 42.1052 +        lookup.lookup(c);
 42.1053 +
 42.1054 +        // but creates new instance and adds it into the lookup
 42.1055 +        // without querying for it
 42.1056 +        loader = new CL ();
 42.1057 +        c = loader.loadClass (Garbage.class.getName ());
 42.1058 +
 42.1059 +        Object theInstance = c.newInstance ();
 42.1060 +
 42.1061 +        ic.addPair (new SerialPair (theInstance));
 42.1062 +
 42.1063 +        Broken2Pair broken = null;
 42.1064 +        if (useBroken) {
 42.1065 +            broken = new Broken2Pair ();
 42.1066 +            ic.addPair (broken);
 42.1067 +            
 42.1068 +            assertNull (
 42.1069 +                "We need to create the slot for the List as " +
 42.1070 +                "the Broken2Pair will ask for it after deserialization", 
 42.1071 +                lookup.lookup (java.awt.List.class)
 42.1072 +            );
 42.1073 +        }
 42.1074 +
 42.1075 +        if (queryBeforeSerialization) {
 42.1076 +            assertEquals ("Instance is found", theInstance, lookup.lookup (c));
 42.1077 +        }
 42.1078 +        
 42.1079 +        // replace the old lookup with new one
 42.1080 +        lookup = (Lookup)reserialize(lookup);
 42.1081 +        
 42.1082 +        Lookup.Result result = lookup.lookup (new Lookup.Template (Garbage.class));
 42.1083 +        assertEquals ("One item is the result", 1, result.allInstances ().size ());
 42.1084 +        Object r = result.allInstances ().iterator ().next ();
 42.1085 +        assertNotNull("A value is found", r);
 42.1086 +        assertEquals ("It is of the right class", Garbage.class, r.getClass());
 42.1087 +    }
 42.1088 +   
 42.1089 +    /** Test of reorder and item change which used to fail on interfaces.
 42.1090 +     */
 42.1091 +    public void testReoderingIssue13779 () throws Exception {
 42.1092 +        LinkedList arr = new LinkedList ();
 42.1093 +        
 42.1094 +        class R extends Exception implements Cloneable {
 42.1095 +        }
 42.1096 +        Object o1 = new R ();
 42.1097 +        Object o2 = new R ();
 42.1098 +        Object o3 = new R ();
 42.1099 +        
 42.1100 +        arr.add (o1);
 42.1101 +        arr.add (o2);
 42.1102 +        
 42.1103 +        ic.set (arr, null);
 42.1104 +        
 42.1105 +        Lookup.Result objectResult = lookup.lookup (new Lookup.Template (Exception.class));
 42.1106 +        Lookup.Result interfaceResult = lookup.lookup (new Lookup.Template (Cloneable.class));
 42.1107 +        objectResult.allItems ();
 42.1108 +        interfaceResult.allItems ();
 42.1109 +        
 42.1110 +        LL l1 = new LL (objectResult);
 42.1111 +        LL l2 = new LL (interfaceResult);
 42.1112 +        
 42.1113 +        objectResult.addLookupListener(l1);
 42.1114 +        interfaceResult.addLookupListener(l2);
 42.1115 +        
 42.1116 +        arr.addFirst (o3);
 42.1117 +        
 42.1118 +        ic.set (arr, null);
 42.1119 +        
 42.1120 +        assertEquals ("One change on objects", 1, l1.getCount ());
 42.1121 +        assertEquals ("One change on interfaces", 1, l2.getCount ());
 42.1122 +        
 42.1123 +        arr.addFirst (new Cloneable () { });
 42.1124 +        ic.set (arr, null);
 42.1125 +        
 42.1126 +        assertEquals ("No change on objects", 0, l1.getCount ());
 42.1127 +        assertEquals ("But one change on interfaces", 1, l2.getCount ());
 42.1128 +        
 42.1129 +    }
 42.1130 +    
 42.1131 +    public void testDeadlockBetweenProxyResultAndLookupIssue47772 () throws Exception {
 42.1132 +        final String myModule = "My Module";
 42.1133 +        ic.add (myModule);
 42.1134 +        
 42.1135 +        class MyProxy extends ProxyLookup {
 42.1136 +            public MyProxy () {
 42.1137 +                super (new Lookup[] { lookup });
 42.1138 +            }
 42.1139 +        }
 42.1140 +        final MyProxy my = new MyProxy ();
 42.1141 +        
 42.1142 +        final Lookup.Result allModules = my.lookup (new Lookup.Template (String.class));
 42.1143 +        
 42.1144 +        class PairThatNeedsInfoAboutModules extends AbstractLookup.Pair {
 42.1145 +            public String getDisplayName () {
 42.1146 +                return "Need a module";
 42.1147 +            }
 42.1148 +            public String getId () {
 42.1149 +                return getDisplayName ();
 42.1150 +            }
 42.1151 +            public Class getType () {
 42.1152 +                return Integer.class;
 42.1153 +            }
 42.1154 +            protected boolean instanceOf (Class c) {
 42.1155 +                if (c == Integer.class) {
 42.1156 +                    synchronized (this) {
 42.1157 +                        notifyAll ();
 42.1158 +                        try {
 42.1159 +                            wait (1000);
 42.1160 +                        } catch (InterruptedException ex) {
 42.1161 +                            fail (ex.getMessage ());
 42.1162 +                        }
 42.1163 +                    }
 42.1164 +                    java.util.Collection coll = allModules.allInstances ();
 42.1165 +                    assertEquals ("Size is 1", 1, coll.size ());
 42.1166 +                    assertEquals ("My module is there", myModule, coll.iterator ().next ());
 42.1167 +                }
 42.1168 +                return c.isAssignableFrom (Integer.class);
 42.1169 +            }
 42.1170 +            
 42.1171 +            public Object getInstance () {
 42.1172 +                return new Integer (10);
 42.1173 +            }
 42.1174 +            
 42.1175 +            protected boolean creatorOf (Object obj) {
 42.1176 +                return new Integer (10).equals (obj);
 42.1177 +            }
 42.1178 +        }
 42.1179 +        
 42.1180 +        PairThatNeedsInfoAboutModules pair = new PairThatNeedsInfoAboutModules ();
 42.1181 +        ic.addPair (pair);
 42.1182 +        
 42.1183 +        synchronized (pair) {
 42.1184 +            class BlockInInstanceOf implements Runnable {
 42.1185 +                public void run () {
 42.1186 +                    Integer i = my.lookup(Integer.class);
 42.1187 +                    assertEquals (new Integer (10), i);
 42.1188 +                }
 42.1189 +            }
 42.1190 +            BlockInInstanceOf blk = new BlockInInstanceOf ();
 42.1191 +            Executors.newSingleThreadScheduledExecutor().schedule(blk, 0, TimeUnit.MICROSECONDS);
 42.1192 +            pair.wait ();
 42.1193 +        }
 42.1194 +        
 42.1195 +        java.util.Collection coll = allModules.allInstances ();
 42.1196 +        assertEquals ("Size is 1", 1, coll.size ());
 42.1197 +        assertEquals ("My module is there", myModule, coll.iterator ().next ());
 42.1198 +    }
 42.1199 +
 42.1200 +    public void testAWayToGenerateProblem13779 () {
 42.1201 +        ic.add (new Integer (1));
 42.1202 +        ic.add (new Integer (2));
 42.1203 +        ic.add (new Integer (1));
 42.1204 +        ic.add (new Integer (2));
 42.1205 +        
 42.1206 +        Collection c = lookup.lookup (new Lookup.Template (Integer.class)).allInstances ();
 42.1207 +        assertEquals ("There are two objects", 2, c.size ());
 42.1208 +        
 42.1209 +    }
 42.1210 +    
 42.1211 +    /** Replacing items with different objects.
 42.1212 +     */
 42.1213 +    public void testReplacingObjectsDoesNotGenerateException () throws Exception {
 42.1214 +        LinkedList arr = new LinkedList ();
 42.1215 +        
 42.1216 +        class R extends Exception implements Cloneable {
 42.1217 +        }
 42.1218 +        arr.add (new R ());
 42.1219 +        arr.add (new R ());
 42.1220 +        
 42.1221 +        ic.set (arr, null);
 42.1222 +        
 42.1223 +        arr.clear();
 42.1224 +        
 42.1225 +        arr.add (new R ());
 42.1226 +        arr.add (new R ());
 42.1227 +        
 42.1228 +        ic.set (arr, null);
 42.1229 +    }
 42.1230 +
 42.1231 +    public void testAfterDeserializationNoQueryIsPeformedOnAlreadyQueriedObjects() throws Exception {
 42.1232 +        if (! (lookup instanceof Serializable)) {
 42.1233 +            // well this test works only for serializable lookups
 42.1234 +            return;
 42.1235 +        }
 42.1236 +        
 42.1237 +        SerialPair my = new SerialPair ("no");
 42.1238 +        ic.addPair (my);
 42.1239 +        
 42.1240 +        Lookup.Result res = lookup.lookup (new Lookup.Template (String.class));
 42.1241 +        assertEquals ("One instance", 1, res.allInstances().size ());
 42.1242 +        assertEquals ("my.instanceOf called once", 1, my.countInstanceOf);
 42.1243 +        
 42.1244 +        Lookup serial = (Lookup)reserialize(lookup);
 42.1245 +        
 42.1246 +        Lookup.Result r2 = serial.lookup(new Lookup.Template(String.class));
 42.1247 +        
 42.1248 +        assertEquals ("One item", 1, r2.allItems ().size ());
 42.1249 +        Object one = r2.allItems().iterator().next ();
 42.1250 +        assertEquals ("The right class", SerialPair.class, one.getClass());
 42.1251 +        SerialPair p = (SerialPair)one;
 42.1252 +        
 42.1253 +        assertEquals ("p.instanceOf has not been queried", 0, p.countInstanceOf);
 42.1254 +    }
 42.1255 +    
 42.1256 +    /** Checks the iterator */
 42.1257 +    private <T> void checkIterator(String msg, Iterator<? extends T> it1, List<? extends T> list) {
 42.1258 +        int cnt = 0;
 42.1259 +        Iterator<? extends T> it2 = list.iterator();
 42.1260 +        while (it1.hasNext () && it2.hasNext ()) {
 42.1261 +            T n1 = it1.next();
 42.1262 +            T n2 = it2.next();
 42.1263 +            
 42.1264 +            if (n1 != n2) {
 42.1265 +                fail (msg + " iterator[" + cnt + "] = " + n1 + " but list[" + cnt + "] = " + n2);
 42.1266 +            }
 42.1267 +            
 42.1268 +            cnt++;
 42.1269 +        }
 42.1270 +        
 42.1271 +        if (it1.hasNext ()) {
 42.1272 +            fail ("Iterator has more elements than list");
 42.1273 +        }
 42.1274 +        
 42.1275 +        if (it2.hasNext ()) {
 42.1276 +            fail ("List has more elements than iterator");
 42.1277 +        }
 42.1278 +    }
 42.1279 +    
 42.1280 +    
 42.1281 +    public void testResultsAreUnmodifyableOrAtLeastTheyDoNotPropagateToCache() throws Exception {
 42.1282 +        String s = "Ahoj";
 42.1283 +        
 42.1284 +        ic.add(s);
 42.1285 +        
 42.1286 +        Lookup.Result res = lookup.lookup(new Template(String.class));
 42.1287 +        
 42.1288 +        for (int i = 1; i < 5; i++) {
 42.1289 +            Collection c1 = res.allInstances();
 42.1290 +            Collection c2 = res.allClasses();
 42.1291 +            Collection c3 = res.allItems();
 42.1292 +
 42.1293 +            assertTrue(i + ": c1 has it", c1.contains(s));
 42.1294 +            assertTrue(i + ": c2 has it", c2.contains(s.getClass()));
 42.1295 +            assertEquals(i + ": c3 has one", 1, c3.size());
 42.1296 +            Lookup.Item item = (Lookup.Item) c3.iterator().next();
 42.1297 +            assertEquals(i + ": c3 has it", s, item.getInstance());
 42.1298 +
 42.1299 +            try {
 42.1300 +                c1.remove(s);
 42.1301 +                assertEquals("No elements now", 0, c1.size());
 42.1302 +            } catch (UnsupportedOperationException ex) {
 42.1303 +                // ok, this need not be supported
 42.1304 +            }
 42.1305 +            try {
 42.1306 +                c2.remove(s.getClass());
 42.1307 +                assertEquals("No elements now", 0, c2.size());
 42.1308 +            } catch (UnsupportedOperationException ex) {
 42.1309 +                // ok, this need not be supported
 42.1310 +            }
 42.1311 +            try {
 42.1312 +                c3.remove(item);
 42.1313 +                assertEquals("No elements now", 0, c3.size());
 42.1314 +            } catch (UnsupportedOperationException ex) {
 42.1315 +                // ok, this need not be supported
 42.1316 +            }
 42.1317 +        }
 42.1318 +    }
 42.1319 +    
 42.1320 +    public void testSomeProblemWithDVBFrameworkSeemsToBeInLookup() {
 42.1321 +        for (int i = 0; i < 5; i++) {
 42.1322 +            ic.add(lookup);
 42.1323 +            assertEquals("Can be found", lookup, lookup.lookup(lookup.getClass()));
 42.1324 +            ic.set(Collections.EMPTY_LIST, null);
 42.1325 +        }        
 42.1326 +    }
 42.1327 +
 42.1328 +    public void testListeningAndQueryingByTwoListenersInstances() {
 42.1329 +        doListeningAndQueryingByTwoListeners(0);
 42.1330 +    }
 42.1331 +    public void testListeningAndQueryingByTwoListenersClasses() {
 42.1332 +        doListeningAndQueryingByTwoListeners(1);        
 42.1333 +    }
 42.1334 +    public void testListeningAndQueryingByTwoListenersItems() {
 42.1335 +        doListeningAndQueryingByTwoListeners(2);
 42.1336 +    }
 42.1337 +    
 42.1338 +    
 42.1339 +    private void doListeningAndQueryingByTwoListeners(final int type) {
 42.1340 +        class L implements LookupListener {
 42.1341 +            Lookup.Result integer = lookup.lookup(new Template(Integer.class));
 42.1342 +            Lookup.Result number = lookup.lookup(new Template(Number.class));
 42.1343 +            Lookup.Result serial = lookup.lookup(new Template(Serializable.class));
 42.1344 +            
 42.1345 +            {
 42.1346 +                integer.addLookupListener(this);
 42.1347 +                number.addLookupListener(this);
 42.1348 +                serial.addLookupListener(this);
 42.1349 +            }
 42.1350 +            
 42.1351 +            int round;
 42.1352 +            
 42.1353 +            public void resultChanged(LookupEvent ev) {
 42.1354 +                Collection c1 = get(type, integer);
 42.1355 +                Collection c2 = get(type, number);
 42.1356 +                Collection c3 = get(type, serial);
 42.1357 +                
 42.1358 +                assertEquals("round " + round + " c1 vs. c2", c1, c2);
 42.1359 +                assertEquals("round " + round + " c1 vs. c3", c1, c3);
 42.1360 +                assertEquals("round " + round + " c2 vs. c3", c2, c3);
 42.1361 +                
 42.1362 +                round++;
 42.1363 +            }            
 42.1364 +
 42.1365 +            private Collection get(int type, Lookup.Result res) {
 42.1366 +                Collection c;
 42.1367 +                switch(type) {
 42.1368 +                    case 0: c = res.allInstances(); break;
 42.1369 +                    case 1: c = res.allClasses(); break;
 42.1370 +                    case 2: c = res.allItems(); break;
 42.1371 +                    default: c = null; fail("Type: " + type); break;
 42.1372 +                }
 42.1373 +                
 42.1374 +                assertNotNull(c);
 42.1375 +                return new ArrayList(c);
 42.1376 +            }
 42.1377 +        }
 42.1378 +        
 42.1379 +        L listener = new L();
 42.1380 +        listener.resultChanged(null);
 42.1381 +        
 42.1382 +        for(int i = 0; i < 100; i++) {
 42.1383 +            ic.add(new Integer(i));
 42.1384 +        }
 42.1385 +        
 42.1386 +        assertEquals("3x100+1 checks", 301, listener.round);
 42.1387 +    }
 42.1388 +    
 42.1389 +    public void testChangeOfNodeDoesNotFireChangeInActionMap() {
 42.1390 +        ActionMap am = new ActionMap();
 42.1391 +        Lookup s = Lookups.singleton(am);
 42.1392 +        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, false);
 42.1393 +    }
 42.1394 +    public void testChangeOfNodeDoesNotFireChangeInActionMapSimple() {
 42.1395 +        ActionMap am = new ActionMap();
 42.1396 +        Lookup s = Lookups.singleton(am);
 42.1397 +        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, true);
 42.1398 +    }
 42.1399 +
 42.1400 +    public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookupSimple() {
 42.1401 +        doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(true);
 42.1402 +    }
 42.1403 +    
 42.1404 +    public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup() {
 42.1405 +        doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(false);
 42.1406 +    }
 42.1407 +    private void doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(boolean wrapBySimple) {
 42.1408 +        final ActionMap am = new ActionMap();
 42.1409 +        
 42.1410 +        class Before extends AbstractLookup {
 42.1411 +            public InstanceContent ic;
 42.1412 +            public Before() {
 42.1413 +                this(new InstanceContent());
 42.1414 +            }
 42.1415 +            
 42.1416 +            private Before(InstanceContent ic) {
 42.1417 +                super(ic);
 42.1418 +                this.ic = ic;
 42.1419 +            }
 42.1420 +
 42.1421 +            protected @Override void beforeLookup(Template template) {
 42.1422 +                if (ic != null) {
 42.1423 +                    ic.add(am);
 42.1424 +                    ic = null;
 42.1425 +                }
 42.1426 +            }
 42.1427 +        }
 42.1428 +        
 42.1429 +        Before s = new Before();
 42.1430 +        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, wrapBySimple);
 42.1431 +        
 42.1432 +        assertNull("beforeLookup called once", s.ic);
 42.1433 +    }
 42.1434 +    
 42.1435 +    private void doChangeOfNodeDoesNotFireChangeInActionMap(final ActionMap am, Lookup actionMapLookup, final boolean wrapBySimple) {
 42.1436 +        Lookup[] lookups = { lookup, actionMapLookup };
 42.1437 +        
 42.1438 +        class Provider implements Lookup.Provider {
 42.1439 +            ProxyLookup delegate;
 42.1440 +            Lookup query;
 42.1441 +            
 42.1442 +            public Provider(Lookup[] arr) {
 42.1443 +                if (wrapBySimple) {
 42.1444 +                    delegate = new ProxyLookup(arr);
 42.1445 +                    query = Lookups.proxy(this);
 42.1446 +                } else {
 42.1447 +                    query = delegate = new ProxyLookup(arr);
 42.1448 +                }
 42.1449 +            }
 42.1450 +            
 42.1451 +            public Lookup getLookup() {
 42.1452 +                return delegate;
 42.1453 +            }
 42.1454 +            
 42.1455 +            public void setLookups(Lookup... arr) {
 42.1456 +                if (wrapBySimple) {
 42.1457 +                    delegate = new ProxyLookup(arr);                    
 42.1458 +                } else {
 42.1459 +                    delegate.setLookups(arr);
 42.1460 +                }
 42.1461 +            }
 42.1462 +        }
 42.1463 +        
 42.1464 +        Provider p = new Provider(lookups);
 42.1465 +        
 42.1466 +        Lookup.Result res = p.query.lookup(new Lookup.Template(ActionMap.class));
 42.1467 +        LL ll = new LL();
 42.1468 +        res.addLookupListener(ll);
 42.1469 +
 42.1470 +        Collection c = res.allInstances();
 42.1471 +        assertFalse("Has next", c.isEmpty());
 42.1472 +        
 42.1473 +        ActionMap am1 = (ActionMap)c.iterator().next();
 42.1474 +        assertEquals("Am is there", am, am1);
 42.1475 +        
 42.1476 +        assertEquals("No change in first get", 0, ll.getCount());
 42.1477 +        
 42.1478 +        Object m1 = new InputMap();
 42.1479 +        Object m2 = new InputMap();
 42.1480 +        
 42.1481 +        ic.add(m1);
 42.1482 +        assertEquals("No change in ActionMap 1", 0, ll.getCount());
 42.1483 +        ic.set(Collections.singletonList(m2), null);
 42.1484 +        assertEquals("No change in ActionMap 2", 0, ll.getCount());
 42.1485 +        ic.add(m2);
 42.1486 +        assertEquals("No change in ActionMap 3", 0, ll.getCount());
 42.1487 +        p.setLookups(lookup, actionMapLookup, Lookup.EMPTY);
 42.1488 +        assertEquals("No change in ActionMap 4", 0, ll.getCount());
 42.1489 +        
 42.1490 +        ActionMap am2 = p.query.lookup(ActionMap.class);
 42.1491 +        assertEquals("Still the same action map", am, am2);
 42.1492 +        
 42.1493 +        
 42.1494 +        class Before extends AbstractLookup {
 42.1495 +            public InstanceContent ic;
 42.1496 +            public Before() {
 42.1497 +                this(new InstanceContent());
 42.1498 +            }
 42.1499 +            
 42.1500 +            private Before(InstanceContent ic) {
 42.1501 +                super(ic);
 42.1502 +                this.ic = ic;
 42.1503 +            }
 42.1504 +
 42.1505 +            protected @Override void beforeLookup(Template template) {
 42.1506 +                if (ic != null) {
 42.1507 +                    ic.add(am);
 42.1508 +                    ic = null;
 42.1509 +                }
 42.1510 +            }
 42.1511 +        }
 42.1512 +        
 42.1513 +        Before s = new Before();
 42.1514 +        
 42.1515 +        // adding different Before, but returning the same instance
 42.1516 +        // this happens with metaInfServices lookup often, moreover
 42.1517 +        // it adds the instance in beforeLookup, which confuses a lot
 42.1518 +        p.setLookups(new Lookup[]{ lookup, new Before() });
 42.1519 +        assertEquals("No change in ActionMap 5", 0, ll.getCount());
 42.1520 +        
 42.1521 +        
 42.1522 +    }
 42.1523 +
 42.1524 +    public void testTasklistsCase() throws Exception {
 42.1525 +        ic.remove(new Object());
 42.1526 +    }
 42.1527 +    
 42.1528 +    
 42.1529 +
 42.1530 +    public void testMultipleListeners() {
 42.1531 +        Object object = new ImplementationObject();
 42.1532 +        ic.add(object);
 42.1533 +        
 42.1534 +        Listener[] listeners = new Listener[4];
 42.1535 +        Lookup.Result result = lookup.lookup(new Lookup.Template(LookupObject.class));
 42.1536 +        for(int i = 0; i < listeners.length; ++i) {
 42.1537 +            listeners[i] = new Listener();
 42.1538 +            result.addLookupListener(listeners[i]);
 42.1539 +        }
 42.1540 +        // initialize listening
 42.1541 +        result.allItems();
 42.1542 +        
 42.1543 +        ic.remove(object);
 42.1544 +        
 42.1545 +        // Apparently, only odd-numbered listeners get called when there are multiple LookupListeners on a result
 42.1546 +        //for(int i = 0; i < listeners.length; ++i) {
 42.1547 +        //    System.out.println("Listener " + i + ": " + listeners[i].wasCalled());            
 42.1548 +        //}
 42.1549 +        for(int i = 0; i < listeners.length; ++i) {
 42.1550 +            assertTrue("Listener " + i + " called", listeners[i].wasCalled());
 42.1551 +        }
 42.1552 +    }
 42.1553 +
 42.1554 +    static Object reserialize(Object o) throws Exception {
 42.1555 +        ByteArrayOutputStream os = new ByteArrayOutputStream();
 42.1556 +        ObjectOutputStream oos = new ObjectOutputStream(os);
 42.1557 +        oos.writeObject(o);
 42.1558 +        oos.close();
 42.1559 +
 42.1560 +        ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
 42.1561 +        ObjectInputStream ois = new ObjectInputStream(is);
 42.1562 +        return ois.readObject();
 42.1563 +    }
 42.1564 +    
 42.1565 +    private class Listener implements LookupListener {
 42.1566 +        private boolean listenerCalled = false;
 42.1567 +        
 42.1568 +        public void resultChanged(LookupEvent ev) {
 42.1569 +            listenerCalled = true;
 42.1570 +        }
 42.1571 +        
 42.1572 +        public boolean wasCalled() {
 42.1573 +            return listenerCalled;
 42.1574 +        }
 42.1575 +        
 42.1576 +        public void reset() {
 42.1577 +            listenerCalled = false;
 42.1578 +        }
 42.1579 +    }
 42.1580 +    
 42.1581 +    private interface LookupObject {}
 42.1582 +    private class ImplementationObject implements LookupObject {}
 42.1583 +    private class NullObject implements LookupObject {}
 42.1584 +    
 42.1585 +    
 42.1586 +    public void testReturnSomethingElseThenYouClaimYouWillReturn() {
 42.1587 +        class Liar extends AbstractLookup.Pair {
 42.1588 +            public Object obj;
 42.1589 +            
 42.1590 +            protected boolean instanceOf(Class c) {
 42.1591 +                return c.isAssignableFrom(String.class);
 42.1592 +            }
 42.1593 +
 42.1594 +            protected boolean creatorOf(Object obj) {
 42.1595 +                return this.obj == obj;
 42.1596 +            }
 42.1597 +
 42.1598 +            public Object getInstance() {
 42.1599 +                return this.obj;
 42.1600 +            }
 42.1601 +
 42.1602 +            public Class getType() {
 42.1603 +                return String.class;
 42.1604 +            }
 42.1605 +
 42.1606 +            public String getId() {
 42.1607 +                return String.class.getName();
 42.1608 +            }
 42.1609 +
 42.1610 +            public String getDisplayName() {
 42.1611 +                return getId();
 42.1612 +            }
 42.1613 +        }
 42.1614 +        
 42.1615 +        
 42.1616 +        Liar l = new Liar();
 42.1617 +        l.obj = new Integer(5);
 42.1618 +        
 42.1619 +        this.ic.addPair(l);
 42.1620 +        
 42.1621 +        Collection c = lookup.lookup(new Lookup.Template(String.class)).allInstances();
 42.1622 +        assertTrue("It is empty: " + c, c.isEmpty());
 42.1623 +    }
 42.1624 +
 42.1625 +    public void testCanProxyLookupHaveWrongResults() {
 42.1626 +        class L implements LookupListener {
 42.1627 +            ProxyLookup pl;
 42.1628 +            Lookup.Result<String> original;
 42.1629 +            Lookup.Result<String> wrapped;
 42.1630 +            boolean ok;
 42.1631 +
 42.1632 +            public void test() {
 42.1633 +                pl = new ProxyLookup(lookup);
 42.1634 +                original = lookup.lookupResult(String.class);
 42.1635 +
 42.1636 +                original.addLookupListener(this);
 42.1637 +
 42.1638 +                wrapped = pl.lookupResult(String.class);
 42.1639 +
 42.1640 +                assertEquals("Original empty", 0, original.allInstances().size());
 42.1641 +                assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
 42.1642 +
 42.1643 +                ic.add("Hello!");
 42.1644 +            }
 42.1645 +
 42.1646 +            public void resultChanged(LookupEvent ev) {
 42.1647 +                ok = true;
 42.1648 +
 42.1649 +                assertEquals("Original has hello", 1, original.allInstances().size());
 42.1650 +                assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
 42.1651 +            }
 42.1652 +
 42.1653 +        }
 42.1654 +        L listener = new L();
 42.1655 +        listener.test();
 42.1656 +        assertTrue("Listener called", listener.ok);
 42.1657 +    }
 42.1658 +
 42.1659 +    public void testObjectFromInstanceContentConverterDisappearsIfNotReferenced() {
 42.1660 +        Conv converter = new Conv("foo");
 42.1661 +        ic.add (converter, converter);
 42.1662 +        Lookup lkp = instanceLookup;
 42.1663 +        StringBuilder sb = lookup.lookup (StringBuilder.class);
 42.1664 +        assertNotNull (sb);
 42.1665 +        int hash = System.identityHashCode(sb);
 42.1666 +        assertEquals ("foo", sb.toString());
 42.1667 +        Reference<StringBuilder> r = new WeakReference<StringBuilder>(sb);
 42.1668 +        sb = null;
 42.1669 +        assertGC("Lookup held onto object", r);
 42.1670 +        sb = lookup.lookup (StringBuilder.class);
 42.1671 +        assertNotSame(hash, System.identityHashCode(sb));
 42.1672 +        r = new WeakReference<StringBuilder>(sb);
 42.1673 +        sb = null;
 42.1674 +        assertGC("Lookup held onto object", r);
 42.1675 +        ic.remove (converter, converter);
 42.1676 +        Reference <InstanceContent.Convertor> cref = new WeakReference<InstanceContent.Convertor>(converter);
 42.1677 +        converter = null;
 42.1678 +        assertGC("Converter still referenced", cref); 
 42.1679 +
 42.1680 +        sb = lkp.lookup(StringBuilder.class);
 42.1681 +        assertNull ("Converter removed from lookup, but object it " +
 42.1682 +                "created still present:'" + sb +"'", sb);
 42.1683 +        converter = new Conv("bar");
 42.1684 +        ic.add (converter, converter);
 42.1685 +        assertNotNull (lkp.lookup(StringBuilder.class));
 42.1686 +        assertEquals ("bar", lkp.lookup(StringBuilder.class).toString());
 42.1687 +    }
 42.1688 +
 42.1689 +    private static class Conv implements InstanceContent.Convertor<Conv, StringBuilder> {
 42.1690 +        private final String str;
 42.1691 +        private Conv (String str) {
 42.1692 +            this.str = str;
 42.1693 +        }
 42.1694 +
 42.1695 +        public StringBuilder convert(Conv obj) {
 42.1696 +            return new StringBuilder (str);
 42.1697 +        }
 42.1698 +
 42.1699 +        public Class<? extends StringBuilder> type(Conv obj) {
 42.1700 +            return StringBuilder.class;
 42.1701 +        }
 42.1702 +
 42.1703 +        public String id(Conv obj) {
 42.1704 +            return "Foo";
 42.1705 +        }
 42.1706 +
 42.1707 +        public String displayName(Conv obj) {
 42.1708 +            return "Foo";
 42.1709 +        }
 42.1710 +    } // end of Conv
 42.1711 +
 42.1712 +    public void testCanGCResults() throws Exception {
 42.1713 +        class L implements LookupListener {
 42.1714 +            int cnt;
 42.1715 +            
 42.1716 +            public void resultChanged(LookupEvent ev) {
 42.1717 +                cnt++;
 42.1718 +            }
 42.1719 +            
 42.1720 +        }
 42.1721 +        L listener1 = new L();
 42.1722 +        L listener2 = new L();
 42.1723 +        
 42.1724 +        Lookup.Result<String> res1 = this.instanceLookup.lookupResult(String.class);
 42.1725 +        Lookup.Result<String> res2 = this.lookup.lookupResult(String.class);
 42.1726 +        
 42.1727 +        assertEquals("Empty1", 0, res1.allItems().size());
 42.1728 +        assertEquals("Empty2", 0, res2.allItems().size());
 42.1729 +        
 42.1730 +        res1.addLookupListener(listener1);
 42.1731 +        res2.addLookupListener(listener2);
 42.1732 +        
 42.1733 +        addInstances(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
 42.1734 +        this.ic.add("Ahoj");
 42.1735 +        
 42.1736 +        assertEquals("Change1", 1, listener1.cnt);
 42.1737 +        assertEquals("Change2", 1, listener2.cnt);
 42.1738 +        
 42.1739 +        assertEquals("Full1", 1, res1.allItems().size());
 42.1740 +        assertEquals("Full2", 1, res2.allItems().size());
 42.1741 +        
 42.1742 +        
 42.1743 +        Reference<Object> ref2 = new WeakReference<Object>(res2);
 42.1744 +        res2 = null;
 42.1745 +        assertGC("Result can disappear", ref2);
 42.1746 +    }
 42.1747 +    
 42.1748 +    void beforeActualTest(String n) {
 42.1749 +        if (n.equals("testEqualsIsNotCalledTooMuch")) {
 42.1750 +            CntPair.cnt = 0;
 42.1751 +            CntPair.hashCnt = 0;
 42.1752 +            CntPair.instances = 0;
 42.1753 +            int how = 1000;
 42.1754 +
 42.1755 +            for(int i = 0; i < how; i++) {
 42.1756 +                this.ic.addPair(new CntPair("x" + i));
 42.1757 +            }
 42.1758 +
 42.1759 +            assertEquals("No equals called", 0, CntPair.cnt);
 42.1760 +            assertEquals("1000 instances ", how, CntPair.instances);
 42.1761 +        }
 42.1762 +    }
 42.1763 +    
 42.1764 +    public void testEqualsIsNotCalledTooMuch() throws Exception {
 42.1765 +        // most of the work done in beforeActualTest
 42.1766 +
 42.1767 +        // desirable: assertEquals("no comparitions", 0, CntPair.cnt);
 42.1768 +        // works for InheritanceTree, but not for ArrayStorage, but array
 42.1769 +        // storages are generally small
 42.1770 +        
 42.1771 +        if (CntPair.cnt > 12000) {
 42.1772 +            fail("Too much comparitions " + CntPair.cnt);
 42.1773 +        }
 42.1774 +        if (CntPair.hashCnt > 40000) {
 42.1775 +            fail("Too much hashes: " + CntPair.hashCnt);
 42.1776 +        }
 42.1777 +        
 42.1778 +        assertEquals("instaces is enough", 1000, CntPair.instances);
 42.1779 +    }
 42.1780 +    
 42.1781 +    /** Adds instances to the instance lookup.
 42.1782 +     */
 42.1783 +    private void addInstances (Object... instances) {
 42.1784 +        for (int i = 0; i < instances.length; i++) {
 42.1785 +            ic.add(instances[i]);
 42.1786 +        }
 42.1787 +    }
 42.1788 +    
 42.1789 +    /** Count instances of clazz in an array. */
 42.1790 +    private int countInstances (Object[] objs, Class clazz) {
 42.1791 +        int count = 0;
 42.1792 +        for (int i = 0; i < objs.length; i++) {
 42.1793 +            if (clazz.isInstance(objs[i])) count++;
 42.1794 +        }
 42.1795 +        return count;
 42.1796 +    }
 42.1797 +    
 42.1798 +    /** Counting listener */
 42.1799 +    protected static class LL implements LookupListener {
 42.1800 +        private int count = 0;
 42.1801 +        public Object source;
 42.1802 +        public Thread changesIn;
 42.1803 +        
 42.1804 +        public LL () {
 42.1805 +            this (null);
 42.1806 +        }
 42.1807 +        
 42.1808 +        public LL (Object source) {
 42.1809 +            this.source = source;
 42.1810 +        }
 42.1811 +        
 42.1812 +        public void resultChanged(LookupEvent ev) {
 42.1813 +            if (changesIn != null) {
 42.1814 +                assertEquals("Changes in the same thread", changesIn, Thread.currentThread());
 42.1815 +            } else {
 42.1816 +                changesIn = Thread.currentThread();
 42.1817 +            }
 42.1818 +            ++count;
 42.1819 +            if (source != null) {
 42.1820 +                assertSame ("Source is the same", source, ev.getSource ());
 42.1821 +//                assertSame ("Result is the same", source, ev.getResult ());
 42.1822 +            }
 42.1823 +        }
 42.1824 +
 42.1825 +        public int getCount() {
 42.1826 +            int i = count;
 42.1827 +            count = 0;
 42.1828 +            return i;
 42.1829 +        }
 42.1830 +    };
 42.1831 +
 42.1832 +    /** A set of interfaces for testInterfaceInheritance
 42.1833 +     */
 42.1834 +    interface TestInterfaceInheritanceA {}
 42.1835 +    interface TestInterfaceInheritanceB extends TestInterfaceInheritanceA, java.rmi.Remote {}
 42.1836 +    interface TestInterfaceInheritanceBB extends TestInterfaceInheritanceB {}
 42.1837 +    interface TestInterfaceInheritanceC extends TestInterfaceInheritanceA, java.rmi.Remote {}
 42.1838 +    interface TestInterfaceInheritanceD extends TestInterfaceInheritanceA {}
 42.1839 +    
 42.1840 +    /** A special class for garbage test */
 42.1841 +    public static final class Garbage extends Object implements Serializable {
 42.1842 +        static final long serialVersionUID = 435340912534L;
 42.1843 +    }
 42.1844 +    
 42.1845 +
 42.1846 +    /* A classloader that can load one class in a special way */
 42.1847 +    private static class CL extends ClassLoader {
 42.1848 +        public CL () {
 42.1849 +            super (null);
 42.1850 +        }
 42.1851 +
 42.1852 +        public @Override Class findClass(String name) throws ClassNotFoundException {
 42.1853 +            if (name.equals (Garbage.class.getName ())) {
 42.1854 +                String n = name.replace ('.', '/');
 42.1855 +                java.io.InputStream is = getClass ().getResourceAsStream ("/" + n + ".class");
 42.1856 +                byte[] arr = new byte[8096];
 42.1857 +                try {
 42.1858 +                    int cnt = is.read (arr);
 42.1859 +                    if (cnt == arr.length) {
 42.1860 +                        fail ("Buffer to load the class is not big enough");
 42.1861 +                    }
 42.1862 +
 42.1863 +                    return defineClass (name, arr, 0, cnt);
 42.1864 +                } catch (java.io.IOException ex) {
 42.1865 +                        ex.printStackTrace();
 42.1866 +                        fail ("IO Exception");
 42.1867 +                        return null;
 42.1868 +                }
 42.1869 +            } else {
 42.1870 +                return null;
 42.1871 +            }
 42.1872 +        }
 42.1873 +
 42.1874 +        /** Convert obj to other object. There is no need to implement
 42.1875 +         * cache mechanism. It is provided by AbstractLookup.Item.getInstance().
 42.1876 +         * Method should be called more than once because Lookup holds
 42.1877 +         * just weak reference.
 42.1878 +         */
 42.1879 +        public Object convert(Object obj) {
 42.1880 +            return null;
 42.1881 +        }
 42.1882 +
 42.1883 +        /** Return type of converted object. */
 42.1884 +        public Class type(Object obj) {
 42.1885 +            try {
 42.1886 +                return loadClass (Garbage.class.getName ());
 42.1887 +            } catch (ClassNotFoundException ex) {
 42.1888 +                fail ("Class not found");
 42.1889 +                throw new InternalError ();
 42.1890 +            }
 42.1891 +        }
 42.1892 +    }
 42.1893 +    
 42.1894 +    private static final class CntPair extends AbstractLookup.Pair {
 42.1895 +        private static int instances;
 42.1896 +        private String txt;
 42.1897 +        
 42.1898 +        public CntPair(String txt) {
 42.1899 +            this.txt = txt;
 42.1900 +            instances++;
 42.1901 +        }
 42.1902 +
 42.1903 +        public static int hashCnt;
 42.1904 +        @Override
 42.1905 +        public int hashCode() {
 42.1906 +            hashCnt++;
 42.1907 +            return txt.hashCode() + 3777;
 42.1908 +        }
 42.1909 +
 42.1910 +        public static int cnt;
 42.1911 +        @Override
 42.1912 +        public boolean equals(Object obj) {
 42.1913 +            cnt++;
 42.1914 +            
 42.1915 +            if (obj == null) {
 42.1916 +                return false;
 42.1917 +            }
 42.1918 +            if (getClass() != obj.getClass()) {
 42.1919 +                return false;
 42.1920 +            }
 42.1921 +            final CntPair other = (CntPair) obj;
 42.1922 +            if (this.txt != other.txt && (this.txt == null || !this.txt.equals(other.txt))) {
 42.1923 +                return false;
 42.1924 +            }
 42.1925 +            return true;
 42.1926 +        }
 42.1927 +
 42.1928 +        protected boolean instanceOf(Class c) {
 42.1929 +            return c.isAssignableFrom(String.class);
 42.1930 +        }
 42.1931 +
 42.1932 +        protected boolean creatorOf(Object obj) {
 42.1933 +            return obj == txt;
 42.1934 +        }
 42.1935 +
 42.1936 +        public Object getInstance() {
 42.1937 +            return txt;
 42.1938 +        }
 42.1939 +
 42.1940 +        public Class getType() {
 42.1941 +            return String.class;
 42.1942 +        }
 42.1943 +
 42.1944 +        public String getId() {
 42.1945 +            return txt;
 42.1946 +        }
 42.1947 +
 42.1948 +        public String getDisplayName() {
 42.1949 +            return txt;
 42.1950 +        }
 42.1951 +        
 42.1952 +    }
 42.1953 +
 42.1954 +    public static final class SerialPair extends AbstractLookup.Pair
 42.1955 +    implements java.io.Serializable {
 42.1956 +        static final long serialVersionUID = 54305834L;
 42.1957 +        private Object value;
 42.1958 +        public transient int countInstanceOf;
 42.1959 +        
 42.1960 +        public SerialPair (Object value) {
 42.1961 +            this.value = value;
 42.1962 +        }
 42.1963 +        
 42.1964 +        protected boolean creatorOf(Object obj) {
 42.1965 +            return obj == value;
 42.1966 +        }
 42.1967 +        
 42.1968 +        public String getDisplayName() {
 42.1969 +            return getId ();
 42.1970 +        }
 42.1971 +        
 42.1972 +        public String getId() {
 42.1973 +            return value.toString();
 42.1974 +        }
 42.1975 +        
 42.1976 +        public Object getInstance() {
 42.1977 +            return value;
 42.1978 +        }
 42.1979 +        
 42.1980 +        public Class getType() {
 42.1981 +            return value.getClass ();
 42.1982 +        }
 42.1983 +        
 42.1984 +        protected boolean instanceOf(Class c) {
 42.1985 +            countInstanceOf++;
 42.1986 +            return c.isInstance(value);
 42.1987 +        }
 42.1988 +    } // end of SerialPair
 42.1989 +    
 42.1990 +    private static class BrokenPair extends AbstractLookup.Pair {
 42.1991 +        private transient ThreadLocal IN = new ThreadLocal ();
 42.1992 +        private boolean checkModify;
 42.1993 +        private boolean checkQuery;
 42.1994 +        
 42.1995 +        public BrokenPair (boolean checkModify, boolean checkQuery) {
 42.1996 +            this.checkModify = checkModify;
 42.1997 +            this.checkQuery = checkQuery;
 42.1998 +        }
 42.1999 +        
 42.2000 +        protected boolean creatorOf(Object obj) { return this == obj; }
 42.2001 +        public String getDisplayName() { return "Broken"; }
 42.2002 +        public String getId() { return "broken"; }
 42.2003 +        public Object getInstance() { return this; }
 42.2004 +        public Class getType() { return getClass (); }
 42.2005 +        protected boolean instanceOf(Class c) { 
 42.2006 +            
 42.2007 +            if (checkQuery) {
 42.2008 +                if (IN.get () == null) {
 42.2009 +                    try {
 42.2010 +                        IN.set (this);
 42.2011 +                        // broken behaviour, tries to modify the lookup
 42.2012 +                        // queries have to survive
 42.2013 +
 42.2014 +                        running.lookup.lookup (java.awt.List.class);
 42.2015 +
 42.2016 +                        // 
 42.2017 +                        // creation of new result has to survive as well
 42.2018 +                        Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.Button.class));
 42.2019 +                        Collection all = myQuery.allItems ();
 42.2020 +                    } finally {
 42.2021 +                        IN.set (null);
 42.2022 +                    }
 42.2023 +                }
 42.2024 +            }
 42.2025 +                
 42.2026 +
 42.2027 +            if (checkModify) {
 42.2028 +                //
 42.2029 +                // modifications should fail
 42.2030 +                //
 42.2031 +
 42.2032 +                try {
 42.2033 +                    running.ic.addPair (new SerialPair (""));
 42.2034 +                    fail ("Modification from a query should be prohibited");
 42.2035 +                } catch (IllegalStateException ex) {
 42.2036 +                }
 42.2037 +                
 42.2038 +                try {
 42.2039 +                    running.ic.removePair (this);
 42.2040 +                    fail ("This has to throw the exception");
 42.2041 +                } catch (IllegalStateException ex) {
 42.2042 +                }
 42.2043 +                try {
 42.2044 +                    running.ic.setPairs (Collections.EMPTY_SET);
 42.2045 +                    fail ("This has to throw the exception as well");
 42.2046 +                } catch (IllegalStateException ex) {
 42.2047 +                }
 42.2048 +            }
 42.2049 +            
 42.2050 +            return c.isAssignableFrom(getType ()); 
 42.2051 +        }
 42.2052 +    } // end of BrokenPair
 42.2053 +    
 42.2054 +    private static class Broken2Pair extends AbstractLookup.Pair {
 42.2055 +        static final long serialVersionUID = 4532587018501L;
 42.2056 +        public transient ThreadLocal IN;
 42.2057 +        
 42.2058 +        public Broken2Pair () {
 42.2059 +        }
 42.2060 +        
 42.2061 +        private void writeObject (java.io.ObjectOutputStream oos) throws java.io.IOException {
 42.2062 +        }
 42.2063 +        
 42.2064 +        private void readObject (java.io.ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException {
 42.2065 +            IN = new ThreadLocal ();
 42.2066 +        }
 42.2067 +        
 42.2068 +        protected boolean creatorOf(Object obj) { return this == obj; }
 42.2069 +        public String getDisplayName() { return "Broken"; }
 42.2070 +        public String getId() { return "broken"; }
 42.2071 +        public Object getInstance() { return this; }
 42.2072 +        public Class getType() { return getClass (); }
 42.2073 +        protected boolean instanceOf(Class c) { 
 42.2074 +            
 42.2075 +            // behaviour gets broken only after deserialization
 42.2076 +            if (IN != null && IN.get () == null) {
 42.2077 +                try {
 42.2078 +                    IN.set (this);
 42.2079 +
 42.2080 +                    // creation of new result has to survive as well
 42.2081 +                    Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.List.class));
 42.2082 +                    Collection all = myQuery.allItems ();
 42.2083 +                } finally {
 42.2084 +                    IN.set (null);
 42.2085 +                }
 42.2086 +            }
 42.2087 +            
 42.2088 +            return c.isAssignableFrom(getType ()); 
 42.2089 +        }
 42.2090 +    } // end of Broken2Pair    
 42.2091 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupExecutorTest.java	Sat Oct 31 15:28:13 2009 +0100
    43.3 @@ -0,0 +1,98 @@
    43.4 +/*
    43.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    43.6 + *
    43.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    43.8 + *
    43.9 + * The contents of this file are subject to the terms of either the GNU
   43.10 + * General Public License Version 2 only ("GPL") or the Common
   43.11 + * Development and Distribution License("CDDL") (collectively, the
   43.12 + * "License"). You may not use this file except in compliance with the
   43.13 + * License. You can obtain a copy of the License at
   43.14 + * http://www.netbeans.org/cddl-gplv2.html
   43.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   43.16 + * specific language governing permissions and limitations under the
   43.17 + * License.  When distributing the software, include this License Header
   43.18 + * Notice in each file and include the License file at
   43.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   43.20 + * particular file as subject to the "Classpath" exception as provided
   43.21 + * by Sun in the GPL Version 2 section of the License file that
   43.22 + * accompanied this code. If applicable, add the following below the
   43.23 + * License Header, with the fields enclosed by brackets [] replaced by
   43.24 + * your own identifying information:
   43.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   43.26 + *
   43.27 + * Contributor(s):
   43.28 + *
   43.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   43.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   43.31 + * Microsystems, Inc. All Rights Reserved.
   43.32 + *
   43.33 + * If you wish your version of this file to be governed by only the CDDL
   43.34 + * or only the GPL Version 2, indicate your decision by adding
   43.35 + * "[Contributor] elects to include this software in this distribution
   43.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   43.37 + * single choice of license, a recipient has the option to distribute
   43.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   43.39 + * to extend the choice of license to its licensees as provided above.
   43.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   43.41 + * Version 2 license, then the option applies only if the new code is
   43.42 + * made subject to such option by the copyright holder.
   43.43 + */
   43.44 +
   43.45 +package org.openide.util.lookup;
   43.46 +
   43.47 +import java.util.concurrent.Executor;
   43.48 +import org.openide.util.Lookup;
   43.49 +import org.openide.util.LookupEvent;
   43.50 +import org.openide.util.LookupListener;
   43.51 +
   43.52 +public class AbstractLookupExecutorTest extends AbstractLookupBaseHid 
   43.53 +implements AbstractLookupBaseHid.Impl, Executor, LookupListener {
   43.54 +    Lookup.Result<?> res;
   43.55 +    
   43.56 +    
   43.57 +    public AbstractLookupExecutorTest(java.lang.String testName) {
   43.58 +        super(testName, null);
   43.59 +    }
   43.60 +
   43.61 +    //
   43.62 +    // Impl of AbstractLookupBaseHid.Impl
   43.63 +    //
   43.64 +
   43.65 +    /** Creates the initial abstract lookup.
   43.66 +     */
   43.67 +    public Lookup createInstancesLookup (InstanceContent ic) {
   43.68 +        ic.attachExecutor(this);
   43.69 +        Lookup l = new AbstractLookup (ic, new InheritanceTree ());
   43.70 +        return l;
   43.71 +    }
   43.72 +    
   43.73 +    /** Creates an lookup for given lookup. This class just returns 
   43.74 +     * the object passed in, but subclasses can be different.
   43.75 +     * @param lookup in lookup
   43.76 +     * @return a lookup to use
   43.77 +     */
   43.78 +    public Lookup createLookup (Lookup lookup) {
   43.79 +        res = lookup.lookupResult(Object.class);
   43.80 +        res.addLookupListener(this);
   43.81 +        return lookup;
   43.82 +    }
   43.83 +
   43.84 +    public void clearCaches () {
   43.85 +    }    
   43.86 +
   43.87 +    ThreadLocal<Object> ME = new ThreadLocal<Object>();
   43.88 +    public void execute(Runnable command) {
   43.89 +        assertEquals("Not yet set", null, ME.get());
   43.90 +        ME.set(this);
   43.91 +        try {
   43.92 +            command.run();
   43.93 +        } finally {
   43.94 +            ME.set(null);
   43.95 +        }
   43.96 +    }
   43.97 +
   43.98 +    public void resultChanged(LookupEvent ev) {
   43.99 +        assertEquals("Changes delivered only from execute method", this, ME.get());
  43.100 +    }
  43.101 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupMemoryTest.java	Sat Oct 31 15:28:13 2009 +0100
    44.3 @@ -0,0 +1,158 @@
    44.4 +/*
    44.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    44.6 + *
    44.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    44.8 + *
    44.9 + * The contents of this file are subject to the terms of either the GNU
   44.10 + * General Public License Version 2 only ("GPL") or the Common
   44.11 + * Development and Distribution License("CDDL") (collectively, the
   44.12 + * "License"). You may not use this file except in compliance with the
   44.13 + * License. You can obtain a copy of the License at
   44.14 + * http://www.netbeans.org/cddl-gplv2.html
   44.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   44.16 + * specific language governing permissions and limitations under the
   44.17 + * License.  When distributing the software, include this License Header
   44.18 + * Notice in each file and include the License file at
   44.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   44.20 + * particular file as subject to the "Classpath" exception as provided
   44.21 + * by Sun in the GPL Version 2 section of the License file that
   44.22 + * accompanied this code. If applicable, add the following below the
   44.23 + * License Header, with the fields enclosed by brackets [] replaced by
   44.24 + * your own identifying information:
   44.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   44.26 + *
   44.27 + * Contributor(s):
   44.28 + *
   44.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   44.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   44.31 + * Microsystems, Inc. All Rights Reserved.
   44.32 + *
   44.33 + * If you wish your version of this file to be governed by only the CDDL
   44.34 + * or only the GPL Version 2, indicate your decision by adding
   44.35 + * "[Contributor] elects to include this software in this distribution
   44.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   44.37 + * single choice of license, a recipient has the option to distribute
   44.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   44.39 + * to extend the choice of license to its licensees as provided above.
   44.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   44.41 + * Version 2 license, then the option applies only if the new code is
   44.42 + * made subject to such option by the copyright holder.
   44.43 + */
   44.44 +
   44.45 +package org.openide.util.lookup;
   44.46 +
   44.47 +import java.util.*;
   44.48 +import org.netbeans.junit.*;
   44.49 +import org.netbeans.modules.openide.util.ActiveQueue;
   44.50 +import org.openide.util.Lookup;
   44.51 +
   44.52 +/** Testing memory consumption of various AbstractLookup aspects.
   44.53 + */
   44.54 +public class AbstractLookupMemoryTest extends NbTestCase {
   44.55 +    public AbstractLookupMemoryTest(java.lang.String testName) {
   44.56 +        super(testName);
   44.57 +    }
   44.58 +
   44.59 +    public static void main(java.lang.String[] args) {
   44.60 +        junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupMemoryTest.class));
   44.61 +    }
   44.62 +
   44.63 +    public void testEmptySize () {
   44.64 +        AbstractLookup instanceLookup = new AbstractLookup ();
   44.65 +        assertSize ("Empty lookup should be small", 16, instanceLookup);
   44.66 +        
   44.67 +        InstanceContent ic = new InstanceContent ();
   44.68 +        instanceLookup = new AbstractLookup (ic);
   44.69 +        assertSize ("Lookup with InstanceContent should be small as well", 16, instanceLookup);
   44.70 +    }
   44.71 +
   44.72 +    public void testPairSize () {
   44.73 +        AbstractLookup.Pair pair = new EmptyPair ();
   44.74 +        assertSize ("Pair occupies only 16 bytes", 16, pair);
   44.75 +    }
   44.76 +    
   44.77 +    public void testPairWithOnePointerSize () {
   44.78 +        AbstractLookup.Pair pair = new OneItemPair ();
   44.79 +        assertSize ("Pair occupies only 16 bytes", 16, pair);
   44.80 +    }
   44.81 +    
   44.82 +    public void testLookupWithPairs () {
   44.83 +        Lookup.Template<Object> t = new Lookup.Template<Object>(Object.class);
   44.84 +        class L implements org.openide.util.LookupListener {
   44.85 +            public int cnt;
   44.86 +            public void resultChanged (org.openide.util.LookupEvent ev) {
   44.87 +                cnt++;
   44.88 +            }
   44.89 +        }
   44.90 +        L listener = new L ();
   44.91 +        L listener2 = new L ();
   44.92 +
   44.93 +        EmptyPair[] pairs = {
   44.94 +            new EmptyPair(),
   44.95 +            new EmptyPair(),
   44.96 +            new EmptyPair(),
   44.97 +            new EmptyPair(),
   44.98 +        };
   44.99 +        Object[] ignore = {
  44.100 +            pairs[0],
  44.101 +            pairs[1],
  44.102 +            pairs[2],
  44.103 +            pairs[3],
  44.104 +            t,
  44.105 +            ActiveQueue.queue(),
  44.106 +            listener,
  44.107 +            listener2,
  44.108 +            new Integer (11) // trashhold is shared
  44.109 +        };
  44.110 +        
  44.111 +        AbstractLookup.Content c = new AbstractLookup.Content ();
  44.112 +        AbstractLookup l = new AbstractLookup (c, (Integer)ignore[ignore.length - 1]);
  44.113 +
  44.114 +        c.addPair ((EmptyPair)ignore[0]);
  44.115 +        assertSize ("Should be really small (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
  44.116 +        
  44.117 +        c.addPair ((EmptyPair)ignore[1]);
  44.118 +        assertSize ("Is bigger I guess (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
  44.119 +        
  44.120 +        c.setPairs(Arrays.asList(pairs).subList(0, 3));
  44.121 +        assertSize ("Even bigger (not counting the pair sizes)", Collections.singleton (l), 64, ignore);
  44.122 +        
  44.123 +        c.setPairs(Arrays.asList(pairs).subList(0, 4));
  44.124 +        assertSize ("Now not that much(not counting the pair sizes)", Collections.singleton (l), 64, ignore);
  44.125 +        
  44.126 +        Lookup.Result res = l.lookup (t);
  44.127 +        
  44.128 +        assertSize ("After creating a result", Collections.singleton (l), 120, ignore);
  44.129 +        
  44.130 +        res.addLookupListener (listener);
  44.131 +        
  44.132 +        assertSize ("And attaching one listener", Collections.singleton (l), 120, ignore);
  44.133 +
  44.134 +        res.addLookupListener (listener2);
  44.135 +        assertSize ("Second listener makes the situation much worse", Collections.singleton (l), 200, ignore);
  44.136 +        res.removeLookupListener(listener2);
  44.137 +        assertSize ("But removing it returns us back to original size", Collections.singleton (l), 120, ignore);
  44.138 +        
  44.139 +        
  44.140 +        assertEquals ("Current for pairs are in", res.allItems ().size (), 4); // also activates the listener
  44.141 +        assertSize ("and making the listener to work", Collections.singleton (l), 120, ignore);
  44.142 +        
  44.143 +        c.removePair ((EmptyPair)ignore[0]);
  44.144 +        assertEquals ("A changes has been delivered", 1, listener.cnt);
  44.145 +    }
  44.146 +
  44.147 +    /** Simple pair with no data */
  44.148 +    private static class EmptyPair extends AbstractLookup.Pair {
  44.149 +        protected boolean creatorOf(Object obj) { return false; }
  44.150 +        public String getDisplayName() { return ""; }
  44.151 +        public String getId() { return ""; }
  44.152 +        public Object getInstance() { return null; }
  44.153 +        public Class getType() { return Object.class; }
  44.154 +        protected boolean instanceOf(Class c) { return c == getType (); }
  44.155 +    } // end of EmptyPair
  44.156 +    
  44.157 +    /** Pair with one item (like InstanceContent.Pair) */
  44.158 +    private static class OneItemPair extends EmptyPair {
  44.159 +        private Object pointer;
  44.160 +    }
  44.161 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    45.3 @@ -0,0 +1,356 @@
    45.4 +/*
    45.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    45.6 + *
    45.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    45.8 + *
    45.9 + * The contents of this file are subject to the terms of either the GNU
   45.10 + * General Public License Version 2 only ("GPL") or the Common
   45.11 + * Development and Distribution License("CDDL") (collectively, the
   45.12 + * "License"). You may not use this file except in compliance with the
   45.13 + * License. You can obtain a copy of the License at
   45.14 + * http://www.netbeans.org/cddl-gplv2.html
   45.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   45.16 + * specific language governing permissions and limitations under the
   45.17 + * License.  When distributing the software, include this License Header
   45.18 + * Notice in each file and include the License file at
   45.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   45.20 + * particular file as subject to the "Classpath" exception as provided
   45.21 + * by Sun in the GPL Version 2 section of the License file that
   45.22 + * accompanied this code. If applicable, add the following below the
   45.23 + * License Header, with the fields enclosed by brackets [] replaced by
   45.24 + * your own identifying information:
   45.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   45.26 + *
   45.27 + * Contributor(s):
   45.28 + *
   45.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   45.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   45.31 + * Microsystems, Inc. All Rights Reserved.
   45.32 + *
   45.33 + * If you wish your version of this file to be governed by only the CDDL
   45.34 + * or only the GPL Version 2, indicate your decision by adding
   45.35 + * "[Contributor] elects to include this software in this distribution
   45.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   45.37 + * single choice of license, a recipient has the option to distribute
   45.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   45.39 + * to extend the choice of license to its licensees as provided above.
   45.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   45.41 + * Version 2 license, then the option applies only if the new code is
   45.42 + * made subject to such option by the copyright holder.
   45.43 + */
   45.44 +
   45.45 +package org.openide.util.lookup;
   45.46 +
   45.47 +import java.util.concurrent.ExecutionException;
   45.48 +
   45.49 +import java.lang.ref.WeakReference;
   45.50 +import java.util.*;
   45.51 +import java.util.concurrent.Executors;
   45.52 +import java.util.concurrent.TimeUnit;
   45.53 +import org.netbeans.junit.*;
   45.54 +import org.openide.util.Lookup;
   45.55 +import org.openide.util.lookup.AbstractLookup.Pair;
   45.56 +
   45.57 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   45.58 +public class AbstractLookupTest extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
   45.59 +    public AbstractLookupTest(java.lang.String testName) {
   45.60 +        super(testName, null);
   45.61 +    }
   45.62 +
   45.63 +    //
   45.64 +    // Impl of AbstractLookupBaseHid.Impl
   45.65 +    //
   45.66 +
   45.67 +    /** Creates the initial abstract lookup.
   45.68 +     */
   45.69 +    public Lookup createInstancesLookup (InstanceContent ic) {
   45.70 +        return new AbstractLookup (ic, new InheritanceTree ());
   45.71 +    }
   45.72 +    
   45.73 +    /** Creates an lookup for given lookup. This class just returns 
   45.74 +     * the object passed in, but subclasses can be different.
   45.75 +     * @param lookup in lookup
   45.76 +     * @return a lookup to use
   45.77 +     */
   45.78 +    public Lookup createLookup (Lookup lookup) {
   45.79 +        return lookup;
   45.80 +    }
   45.81 +
   45.82 +    public void clearCaches () {
   45.83 +    }    
   45.84 +    
   45.85 +    public static void main(java.lang.String[] args) {
   45.86 +        junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupTest.class));
   45.87 +    }
   45.88 +    
   45.89 +    static class LkpResultCanBeGargageCollectedAndClearsTheResult extends AbstractLookup {
   45.90 +        public int cleared;
   45.91 +        public int dirty;
   45.92 +
   45.93 +        synchronized @Override boolean cleanUpResult(Template t) {
   45.94 +            boolean res = super.cleanUpResult (t);
   45.95 +            if (res) {
   45.96 +                cleared++;
   45.97 +            } else {
   45.98 +                dirty++;
   45.99 +            }
  45.100 +
  45.101 +            notifyAll ();
  45.102 +
  45.103 +            return res;
  45.104 +        }
  45.105 +    }
  45.106 +    public void testResultCanBeGargageCollectedAndClearsTheResult () throws Exception {
  45.107 +        LkpResultCanBeGargageCollectedAndClearsTheResult lkp = new LkpResultCanBeGargageCollectedAndClearsTheResult ();
  45.108 +        assertSize ("24 for AbstractLookup, 8 for two ints", 32, lkp);
  45.109 +        synchronized (lkp) {
  45.110 +            Lookup.Result res = lkp.lookup (new Lookup.Template (getClass ()));
  45.111 +            res.allItems();
  45.112 +            
  45.113 +            WeakReference ref = new WeakReference (res);
  45.114 +            res = null;
  45.115 +            assertGC ("Reference can get cleared", ref);
  45.116 +         
  45.117 +            // wait till we 
  45.118 +            while (lkp.cleared == 0 && lkp.dirty == 0) {
  45.119 +                lkp.wait ();
  45.120 +            }
  45.121 +            
  45.122 +            assertEquals ("No dirty cleanups", 0, lkp.dirty);
  45.123 +            assertEquals ("One final cleanup", 1, lkp.cleared);
  45.124 +        }
  45.125 +        //assertSize ("Everything has been cleaned to original size", 32, lkp);
  45.126 +        
  45.127 +    }
  45.128 +    
  45.129 +    public void testPairCannotBeUsedInMoreThanOneLookupAtOnce () throws Exception {
  45.130 +        /** Simple pair with no data */
  45.131 +        class EmptyPair extends AbstractLookup.Pair {
  45.132 +            protected boolean creatorOf(Object obj) { return false; }
  45.133 +            public String getDisplayName() { return "Empty"; }
  45.134 +            public String getId() { return "empty"; }
  45.135 +            public Object getInstance() { return null; }
  45.136 +            public Class getType() { return Object.class; }
  45.137 +            protected boolean instanceOf(Class c) { return c == getType (); }
  45.138 +        } // end of EmptyPair
  45.139 +        
  45.140 +        AbstractLookup.Content c1 = new AbstractLookup.Content ();
  45.141 +        AbstractLookup.Content c2 = new AbstractLookup.Content ();
  45.142 +        AbstractLookup l1 = new AbstractLookup (c1);
  45.143 +        AbstractLookup l2 = new AbstractLookup (c2);
  45.144 +        
  45.145 +        EmptyPair empty = new EmptyPair ();
  45.146 +        c1.addPair (empty);
  45.147 +        Lookup.Result res = l1.lookup (new Lookup.Template (Object.class));
  45.148 +        assertEquals (
  45.149 +            "Pair is really found", empty, 
  45.150 +            res.allItems ().iterator().next ()
  45.151 +        );
  45.152 +        try {
  45.153 +            c2.addPair (empty);
  45.154 +            fail ("It should not be possible to add pair to two lookups");
  45.155 +        } catch (IllegalStateException ex) {
  45.156 +            // ok, exception is fine
  45.157 +        }
  45.158 +        assertEquals (
  45.159 +            "L2 is still empty", Collections.EMPTY_LIST, 
  45.160 +            new ArrayList (l2.lookup (new Lookup.Template (Object.class)).allItems ())
  45.161 +        );
  45.162 +    }
  45.163 +    
  45.164 +    public void testInitializationCanBeDoneFromAnotherThread () {
  45.165 +        class MyLkp extends AbstractLookup implements Runnable {
  45.166 +            private InstanceContent ic;
  45.167 +            private boolean direct;
  45.168 +            
  45.169 +            public MyLkp (boolean direct) {
  45.170 +                this (direct, new InstanceContent ());
  45.171 +            }
  45.172 +                
  45.173 +            private MyLkp (boolean direct, InstanceContent ic) {
  45.174 +                super (ic);
  45.175 +                this.direct = direct;
  45.176 +                this.ic = ic;
  45.177 +            }
  45.178 +            
  45.179 +            protected @Override void initialize() {
  45.180 +                if (direct) {
  45.181 +                    run ();
  45.182 +                } else {
  45.183 +                    try {
  45.184 +                        Executors.newSingleThreadScheduledExecutor().schedule(this, 0, TimeUnit.MICROSECONDS).get();
  45.185 +                    } catch (InterruptedException ex) {
  45.186 +                        ex.printStackTrace();
  45.187 +                    } catch (ExecutionException ex) {
  45.188 +                        ex.printStackTrace();
  45.189 +                    }
  45.190 +                }
  45.191 +            }
  45.192 +            
  45.193 +            public void run () {
  45.194 +                ic.add (this);
  45.195 +                ic.remove (this);
  45.196 +                ic.set (Collections.nCopies(10, this), null);
  45.197 +                ic.set (Collections.EMPTY_LIST, null);
  45.198 +                ic.add (AbstractLookupTest.this);
  45.199 +            }
  45.200 +        }
  45.201 +        
  45.202 +        assertEquals ("The test should be there", this, new MyLkp (true).lookup (Object.class));
  45.203 +        assertEquals ("and in async mode as well", this, new MyLkp (false).lookup (Object.class));
  45.204 +    }
  45.205 +    
  45.206 +    public void testBeforeLookupIsCalled () {
  45.207 +        class BeforeL extends AbstractLookup {
  45.208 +            public ArrayList list = new ArrayList ();
  45.209 +            public String toAdd;
  45.210 +            public InstanceContent ic;
  45.211 +            
  45.212 +            public BeforeL () {
  45.213 +                this (new InstanceContent ());
  45.214 +            }
  45.215 +            
  45.216 +            private BeforeL (InstanceContent c) {
  45.217 +                super (c);
  45.218 +                this.ic = c;
  45.219 +            }
  45.220 +        
  45.221 +            protected @Override void beforeLookup(Template t) {
  45.222 +                if (toAdd != null) {
  45.223 +                    list.add (0, new SerialPair (toAdd));
  45.224 +                    setPairs (list);
  45.225 +                } else {
  45.226 +                    ic.add (new Integer (1));
  45.227 +                }
  45.228 +            }
  45.229 +        }
  45.230 +        
  45.231 +        BeforeL lookup = new BeforeL ();
  45.232 +        
  45.233 +        lookup.toAdd = "First";
  45.234 +        assertEquals ("First if found", "First", lookup.lookup (String.class));
  45.235 +        
  45.236 +        lookup.toAdd = "2";
  45.237 +        assertEquals ("2 is not first", "2", lookup.lookup (String.class));
  45.238 +        
  45.239 +        Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
  45.240 +        for (int i = 3; i < 20; i++) {
  45.241 +            lookup.toAdd = String.valueOf (i);
  45.242 +            assertEquals (i + " items are now there", i, res.allInstances ().size ());
  45.243 +        }
  45.244 +        for (int i = 20; i < 35; i++) {
  45.245 +            lookup.toAdd = String.valueOf (i);
  45.246 +            assertEquals (i + " items are now there", i, res.allItems ().size ());
  45.247 +        }
  45.248 +        
  45.249 +        assertEquals ("Just strings are there now", 1, res.allClasses ().size ());
  45.250 +        lookup.toAdd = null; // this will add integer
  45.251 +        assertEquals ("Two classes now", 2, res.allClasses ().size ());
  45.252 +    }
  45.253 +
  45.254 +    public void testInconsistentAfterDeserIssue71744() throws Exception {
  45.255 +        InheritanceTree inhTree = new InheritanceTree();
  45.256 +
  45.257 +        AbstractLookup al = new AbstractLookup(new AbstractLookup.Content(), inhTree);
  45.258 +        {
  45.259 +
  45.260 +            Collection r = al.lookup(new Lookup.Template(Integer.class)).allInstances();
  45.261 +            assertEquals("None", 0, r.size());
  45.262 +        }
  45.263 +
  45.264 +        ICP item = new ICP(new Integer(10));
  45.265 +        al.addPair(item);
  45.266 +        al.removePair(item);
  45.267 +
  45.268 +        AbstractLookup newLookup = (AbstractLookup)reserialize(al);
  45.269 +
  45.270 +        newLookup.lookup(Number.class);
  45.271 +
  45.272 +
  45.273 +        newLookup.addPair(new ICP(new Long(20)));
  45.274 +
  45.275 +        {
  45.276 +
  45.277 +            Collection r = newLookup.lookup(new Lookup.Template(Number.class)).allInstances();
  45.278 +            assertEquals("one", 1, r.size());
  45.279 +/*
  45.280 +            Iterator it = r.iterator();
  45.281 +            assertEquals(new Integer(10), it.next());
  45.282 +            assertEquals(new Long(20), it.next());*/
  45.283 +        }
  45.284 +    }
  45.285 +
  45.286 +    public void testMatchesIssue130673() {
  45.287 +        class BrokenPairReturningNullID extends Pair<Object> {
  45.288 +            @Override
  45.289 +            protected boolean instanceOf(Class<?> c) {
  45.290 +                return false;
  45.291 +            }
  45.292 +
  45.293 +            @Override
  45.294 +            protected boolean creatorOf(Object obj) {
  45.295 +                return false;
  45.296 +            }
  45.297 +
  45.298 +            @Override
  45.299 +            public Object getInstance() {
  45.300 +                return null;
  45.301 +            }
  45.302 +
  45.303 +            @Override
  45.304 +            public Class<? extends Object> getType() {
  45.305 +                return null;
  45.306 +            }
  45.307 +
  45.308 +            @Override
  45.309 +            public String getId() {
  45.310 +                return null;
  45.311 +            }
  45.312 +
  45.313 +            @Override
  45.314 +            public String getDisplayName() {
  45.315 +                return null;
  45.316 +            }
  45.317 +        }
  45.318 +        BrokenPairReturningNullID broken = new BrokenPairReturningNullID();
  45.319 +        
  45.320 +        
  45.321 +        Lookup.Template<String> t = new Lookup.Template<String>(String.class, "ID", null);
  45.322 +        boolean not = AbstractLookup.matches(t, broken, true);
  45.323 +        assertFalse("Does not match the template, but throws no exception", not);
  45.324 +    }
  45.325 +    
  45.326 +    private static final class ICP extends AbstractLookup.Pair {
  45.327 +        private Number s;
  45.328 +
  45.329 +        public ICP (Number s) {
  45.330 +            this.s = s;
  45.331 +        }
  45.332 +
  45.333 +
  45.334 +        protected boolean instanceOf(Class c) {
  45.335 +            return c.isInstance(s);
  45.336 +        }
  45.337 +
  45.338 +        protected boolean creatorOf(Object obj) {
  45.339 +            return s == obj;
  45.340 +        }
  45.341 +
  45.342 +        public Object getInstance() {
  45.343 +            return s;
  45.344 +        }
  45.345 +
  45.346 +        public Class getType() {
  45.347 +            return s.getClass();
  45.348 +        }
  45.349 +
  45.350 +        public String getId() {
  45.351 +            return s.toString();
  45.352 +        }
  45.353 +
  45.354 +        public String getDisplayName() {
  45.355 +            return getId();
  45.356 +        }
  45.357 +
  45.358 +    }
  45.359 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    46.3 @@ -0,0 +1,228 @@
    46.4 +/*
    46.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    46.6 + *
    46.7 + * Copyright 1997-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 + * Contributor(s):
   46.28 + *
   46.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   46.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   46.31 + * Microsystems, Inc. All Rights Reserved.
   46.32 + *
   46.33 + * If you wish your version of this file to be governed by only the CDDL
   46.34 + * or only the GPL Version 2, indicate your decision by adding
   46.35 + * "[Contributor] elects to include this software in this distribution
   46.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   46.37 + * single choice of license, a recipient has the option to distribute
   46.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   46.39 + * to extend the choice of license to its licensees as provided above.
   46.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   46.41 + * Version 2 license, then the option applies only if the new code is
   46.42 + * made subject to such option by the copyright holder.
   46.43 + */
   46.44 +
   46.45 +package org.openide.util.lookup;
   46.46 +
   46.47 +import java.util.*;
   46.48 +import org.openide.util.Lookup;
   46.49 +
   46.50 +/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
   46.51 + */
   46.52 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   46.53 +public class ExcludingLookupTest extends AbstractLookupBaseHid
   46.54 +implements AbstractLookupBaseHid.Impl {
   46.55 +    public ExcludingLookupTest(java.lang.String testName) {
   46.56 +        super(testName, null);
   46.57 +    }
   46.58 +
   46.59 +    public Lookup createLookup (final Lookup lookup) {
   46.60 +        return Lookups.exclude (lookup, new Class[0]);
   46.61 +    }
   46.62 +    
   46.63 +    public Lookup createInstancesLookup (InstanceContent ic) {
   46.64 +        return new AbstractLookup (ic);
   46.65 +    }
   46.66 +
   46.67 +    public void clearCaches () {
   46.68 +    }    
   46.69 +    
   46.70 +    public void testWeCanRemoveInteger () throws Exception {
   46.71 +        doBasicFilteringTest (Integer.class, Integer.class, 0);
   46.72 +    }
   46.73 +    
   46.74 +    public void testWeCanRemoveIntegersEvenByAskingForRemoveOfAllNumbers () throws Exception {
   46.75 +        doBasicFilteringTest (Number.class, Integer.class, 0);
   46.76 +    }
   46.77 +    public void testFunWithInterfaces () throws Exception {
   46.78 +        doBasicFilteringTest (java.io.Serializable.class, Integer.class, 0);
   46.79 +    }
   46.80 +    
   46.81 +    public void testWeCanGetInstanceOfSerializableEvenItIsExcludedIfWeAskForClassNotExtendingIt () throws Exception {
   46.82 +        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { java.io.Serializable.class });
   46.83 +        Lookup.Template t = new Lookup.Template (Object.class);
   46.84 +        Lookup.Result res = lookup.lookup (t);
   46.85 +        
   46.86 +        LL ll = new LL ();
   46.87 +        res.addLookupListener (ll);
   46.88 +        assertEquals ("Nothing is there", 0, res.allItems ().size ());
   46.89 +        
   46.90 +        Object inst = new Integer (3);
   46.91 +        ic.add (inst);
   46.92 +        
   46.93 +        assertEquals ("Not Filtered out", inst, lookup.lookup (Object.class));
   46.94 +        assertEquals ("Not Filtered out2", inst, lookup.lookupItem (t).getInstance ());
   46.95 +        assertEquals ("One is there - 2", 1, res.allItems ().size ());
   46.96 +        assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
   46.97 +        assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
   46.98 +        assertEquals ("Right # of events", 1, ll.getCount ());
   46.99 +        
  46.100 +        ic.remove (inst);
  46.101 +        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
  46.102 +        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
  46.103 +        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
  46.104 +        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
  46.105 +        assertEquals ("Of course it is not there", null, lookup.lookup (Object.class));
  46.106 +        assertEquals ("Right # of events", 1, ll.getCount ());
  46.107 +    }
  46.108 +    
  46.109 +    public void testIntegersQueriedThruObject () throws Exception {
  46.110 +        doBasicFilteringTest (Number.class, Object.class, 1);
  46.111 +    }
  46.112 +    
  46.113 +    private void doBasicFilteringTest (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
  46.114 +        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
  46.115 +        Lookup.Template t = new Lookup.Template (theQuery);
  46.116 +        Lookup.Result res = lookup.lookup (t);
  46.117 +        
  46.118 +        LL ll = new LL ();
  46.119 +        res.addLookupListener (ll);
  46.120 +        assertEquals ("Nothing is there", 0, res.allItems ().size ());
  46.121 +        
  46.122 +        Object inst = new Integer (3);
  46.123 +        ic.add (inst);
  46.124 +        
  46.125 +        assertEquals ("Filtered out", null, lookup.lookup (theQuery));
  46.126 +        assertEquals ("Filtered out2", null, lookup.lookupItem (t));
  46.127 +        assertEquals ("Nothing is there - 2", 0, res.allItems ().size ());
  46.128 +        assertEquals ("Nothing is there - 2a", 0, res.allInstances ().size ());
  46.129 +        assertEquals ("Nothing is there - 2b", 0, res.allClasses ().size ());
  46.130 +        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
  46.131 +        
  46.132 +        ic.remove (inst);
  46.133 +        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
  46.134 +        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
  46.135 +        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
  46.136 +        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
  46.137 +        assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
  46.138 +        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
  46.139 +        
  46.140 +    }
  46.141 +    
  46.142 +    public void testSizeOfTheLookup () throws Exception {
  46.143 +        Class exclude = String.class;
  46.144 +        
  46.145 +        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { exclude });
  46.146 +
  46.147 +        assertSize ("Should be pretty lightweight", Collections.singleton (lookup), 16, 
  46.148 +                new Object[] { this.instanceLookup, exclude });
  46.149 +    }
  46.150 +    public void testSizeOfTheLookupForMultipleFiltersIsHigher () throws Exception {
  46.151 +        Class exclude = String.class;
  46.152 +        Class exclude2 = Integer.class;
  46.153 +        Class[] arr = new Class[] { exclude, exclude2 };
  46.154 +        
  46.155 +        Lookup lookup = Lookups.exclude (this.instanceLookup, arr);
  46.156 +
  46.157 +        assertSize ("Is fatter", Collections.singleton (lookup), 40, 
  46.158 +                new Object[] { this.instanceLookup, exclude, exclude2 });
  46.159 +        assertSize ("But only due to the array", Collections.singleton (lookup), 16, 
  46.160 +                new Object[] { this.instanceLookup, exclude, exclude2, arr });
  46.161 +    }
  46.162 +    
  46.163 +    public void testFilteringOfSomething () throws Exception {
  46.164 +        doFilteringOfSomething (Runnable.class, java.io.Serializable.class, 1);
  46.165 +    }
  46.166 +    
  46.167 +    private void doFilteringOfSomething (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
  46.168 +        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
  46.169 +        Lookup.Template t = new Lookup.Template (theQuery);
  46.170 +        Lookup.Result res = lookup.lookup (t);
  46.171 +        
  46.172 +        LL ll = new LL ();
  46.173 +        res.addLookupListener (ll);
  46.174 +        assertEquals ("Nothing is there", 0, res.allItems ().size ());
  46.175 +        
  46.176 +        Object inst = new Integer (3);
  46.177 +        ic.add (inst);
  46.178 +        
  46.179 +        assertEquals ("Accepted", inst, lookup.lookup (theQuery));
  46.180 +        assertNotNull ("Accepted too", lookup.lookupItem (t));
  46.181 +        assertEquals ("One is there - 2", 1, res.allItems ().size ());
  46.182 +        assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
  46.183 +        assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
  46.184 +        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
  46.185 +
  46.186 +        Object inst2 = new Thread (); // implements Runnable
  46.187 +        ic.add (inst2);
  46.188 +        assertEquals ("Accepted - 2", inst, lookup.lookup (theQuery));
  46.189 +        assertNotNull ("Accepted too -2", lookup.lookupItem (t));
  46.190 +        assertEquals ("One is there - 3", 1, res.allItems ().size ());
  46.191 +        assertEquals ("One is there - 3a", 1, res.allInstances ().size ());
  46.192 +        assertEquals ("One is there - 3b", 1, res.allClasses ().size ());
  46.193 +        assertEquals ("Right # of events", 0, ll.getCount ());
  46.194 +        
  46.195 +        
  46.196 +        ic.remove (inst);
  46.197 +        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
  46.198 +        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
  46.199 +        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
  46.200 +        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
  46.201 +        assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
  46.202 +        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
  46.203 +    }
  46.204 +
  46.205 +    public void testTheBehaviourAsRequestedByDavidAndDescribedByJesse () throws Exception {
  46.206 +        class C implements Runnable, java.io.Serializable {
  46.207 +            public void run () {}
  46.208 +        }
  46.209 +        Object c = new C();
  46.210 +        Lookup l1 = Lookups.singleton(c);
  46.211 +        Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
  46.212 +        assertNull(l2.lookup(Runnable.class));
  46.213 +        assertEquals(c, l2.lookup(java.io.Serializable.class));
  46.214 +    }
  46.215 +    
  46.216 +    public void testTheBehaviourAsRequestedByDavidAndDescribedByJesseWithUsageOfResult () throws Exception {
  46.217 +        class C implements Runnable, java.io.Serializable {
  46.218 +            public void run () {}
  46.219 +        }
  46.220 +        Object c = new C();
  46.221 +        Lookup l1 = Lookups.singleton(c);
  46.222 +        Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
  46.223 +        
  46.224 +        Lookup.Result run = l2.lookup (new Lookup.Template (Runnable.class));
  46.225 +        Lookup.Result ser = l2.lookup (new Lookup.Template (java.io.Serializable.class));
  46.226 +        
  46.227 +        assertEquals ("Runnables filtered out", 0, run.allItems ().size ());
  46.228 +        assertEquals ("One serialiazble", 1, ser.allItems ().size ());
  46.229 +        assertEquals ("And it is c", c, ser.allInstances ().iterator ().next ());
  46.230 +    }
  46.231 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/lookup/InheritanceTreeTest.java	Sat Oct 31 15:28:13 2009 +0100
    47.3 @@ -0,0 +1,77 @@
    47.4 +/*
    47.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    47.6 + *
    47.7 + * Copyright 1997-2009 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 + * Contributor(s):
   47.28 + *
   47.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   47.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   47.31 + * Microsystems, Inc. All Rights Reserved.
   47.32 + *
   47.33 + * If you wish your version of this file to be governed by only the CDDL
   47.34 + * or only the GPL Version 2, indicate your decision by adding
   47.35 + * "[Contributor] elects to include this software in this distribution
   47.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   47.37 + * single choice of license, a recipient has the option to distribute
   47.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   47.39 + * to extend the choice of license to its licensees as provided above.
   47.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   47.41 + * Version 2 license, then the option applies only if the new code is
   47.42 + * made subject to such option by the copyright holder.
   47.43 + */
   47.44 +package org.openide.util.lookup;
   47.45 +
   47.46 +import junit.framework.TestCase;
   47.47 +import junit.framework.*;
   47.48 +import org.openide.util.Lookup;
   47.49 +import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
   47.50 +import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
   47.51 +import java.io.*;
   47.52 +import java.lang.ref.WeakReference;
   47.53 +import java.util.*;
   47.54 +
   47.55 +/**
   47.56 + *
   47.57 + * @author Jaroslav Tulach
   47.58 + */
   47.59 +public class InheritanceTreeTest extends TestCase {
   47.60 +
   47.61 +    public InheritanceTreeTest(String testName) {
   47.62 +        super(testName);
   47.63 +    }
   47.64 +
   47.65 +    protected void setUp() throws Exception {
   47.66 +    }
   47.67 +
   47.68 +    protected void tearDown() throws Exception {
   47.69 +    }
   47.70 +
   47.71 +    public void testDeserOfNode() {
   47.72 +        InheritanceTree inh = new InheritanceTree();
   47.73 +        InheritanceTree.Node n = new InheritanceTree.Node(String.class);
   47.74 +        n.markDeserialized();
   47.75 +        n.markDeserialized();
   47.76 +
   47.77 +        n.assignItem(inh, new InstanceContent.SimpleItem("Ahoj"));
   47.78 +    }
   47.79 +    
   47.80 +}
    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/InitializationBug44134Test.java	Sat Oct 31 15:28:13 2009 +0100
    48.3 @@ -0,0 +1,126 @@
    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 java.util.*;
   48.48 +import org.netbeans.junit.*;
   48.49 +import org.openide.util.Lookup;
   48.50 +
   48.51 +public class InitializationBug44134Test extends NbTestCase {
   48.52 +    public InitializationBug44134Test (java.lang.String testName) {
   48.53 +        super(testName);
   48.54 +    }
   48.55 +
   48.56 +    public static void main(java.lang.String[] args) {
   48.57 +        junit.textui.TestRunner.run(new NbTestSuite(InitializationBug44134Test.class));
   48.58 +    }
   48.59 +
   48.60 +    public void testThereShouldBe18Integers () throws Exception {
   48.61 +        FooManifestLookup foo = new FooManifestLookup ();
   48.62 +        
   48.63 +        Collection items = foo.lookup (new Lookup.Template (Integer.class)).allItems ();
   48.64 +        
   48.65 +        assertEquals ("18 of them", 18, items.size ());
   48.66 +        
   48.67 +        Iterator it = items.iterator ();
   48.68 +        while (it.hasNext()) {
   48.69 +            Lookup.Item t = (Lookup.Item)it.next ();
   48.70 +            assertEquals ("Is Integer", Integer.class, t.getInstance ().getClass ());
   48.71 +        }
   48.72 +    }
   48.73 +
   48.74 +    
   48.75 +    public class FooManifestLookup extends AbstractLookup {
   48.76 +        public FooManifestLookup() {
   48.77 +            super();
   48.78 +        }
   48.79 +        
   48.80 +        @Override
   48.81 +        protected void initialize() {
   48.82 +            for (int i=0; i<18; i++) {
   48.83 +                try {
   48.84 +                    String id= "__" + i;
   48.85 +                    
   48.86 +                    addPair(new FooLookupItem(new Integer(i),id));
   48.87 +                }
   48.88 +                catch (Exception e) {
   48.89 +                }
   48.90 +            }
   48.91 +        }
   48.92 +        
   48.93 +        public class FooLookupItem extends AbstractLookup.Pair {
   48.94 +            public FooLookupItem(Integer data, String id) {
   48.95 +                super();
   48.96 +                this.data=data;
   48.97 +                this.id=id;
   48.98 +            }
   48.99 +            
  48.100 +            protected boolean creatorOf(Object obj) {
  48.101 +                return obj == data;
  48.102 +            }
  48.103 +            
  48.104 +            public String getDisplayName() {
  48.105 +                return data.toString();
  48.106 +            }
  48.107 +            
  48.108 +            public Class getType () {
  48.109 +                return Integer.class;
  48.110 +            }
  48.111 +            
  48.112 +            protected boolean instanceOf (Class c) {
  48.113 +                return c.isInstance(data);
  48.114 +            }
  48.115 +            
  48.116 +            public Object getInstance() {
  48.117 +                return data;
  48.118 +            }
  48.119 +            
  48.120 +            public String getId() {
  48.121 +                return id;
  48.122 +            }
  48.123 +            
  48.124 +            private Integer data;
  48.125 +            private String id;
  48.126 +        }
  48.127 +    }
  48.128 +    
  48.129 +}
    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/KomrskaLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    49.3 @@ -0,0 +1,177 @@
    49.4 +/*
    49.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    49.6 + *
    49.7 + * Copyright 2008 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 + * If you wish your version of this file to be governed by only the CDDL
   49.28 + * or only the GPL Version 2, indicate your decision by adding
   49.29 + * "[Contributor] elects to include this software in this distribution
   49.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   49.31 + * single choice of license, a recipient has the option to distribute
   49.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   49.33 + * to extend the choice of license to its licensees as provided above.
   49.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   49.35 + * Version 2 license, then the option applies only if the new code is
   49.36 + * made subject to such option by the copyright holder.
   49.37 + *
   49.38 + * Contributor(s):
   49.39 + *
   49.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   49.41 + */
   49.42 +package org.openide.util.lookup;
   49.43 +
   49.44 +import org.junit.After;
   49.45 +import org.junit.Before;
   49.46 +import org.junit.Test;
   49.47 +import org.openide.util.Lookup;
   49.48 +import org.openide.util.LookupEvent;
   49.49 +import org.openide.util.LookupListener;
   49.50 +import static org.junit.Assert.*;
   49.51 +
   49.52 +/**
   49.53 + * Test donated by Mr. Komrska. Seems to pass with 6.5.
   49.54 + * @author komrska
   49.55 + */
   49.56 +public final class KomrskaLookupTest {
   49.57 +    private TestLookupManager lookupManager=null;
   49.58 +    private StringBuffer result=null;
   49.59 +    
   49.60 +    //
   49.61 +    
   49.62 +    private void addToLookup(final TestLookupItemA object) {
   49.63 +        result.append('A');
   49.64 +        lookupManager.add(object);
   49.65 +    }
   49.66 +    private void removeFromLookup(final TestLookupItemA object) {
   49.67 +        result.append('A');
   49.68 +        lookupManager.remove(object);
   49.69 +    }
   49.70 +
   49.71 +    private void addToLookup(final TestLookupItemB object) {
   49.72 +        result.append('B');
   49.73 +        lookupManager.add(object);
   49.74 +    }
   49.75 +    private void removeFromLookup(final TestLookupItemB object) {
   49.76 +        result.append('B');
   49.77 +        lookupManager.remove(object);
   49.78 +    }
   49.79 +    
   49.80 +    public String getResult() {
   49.81 +        return result.toString();
   49.82 +    }
   49.83 +    
   49.84 +    //
   49.85 +
   49.86 +    @Before
   49.87 +    public void setUp() {
   49.88 +        lookupManager=new TestLookupManager();
   49.89 +        result=new StringBuffer();
   49.90 +    }
   49.91 +    
   49.92 +    @After
   49.93 +    public void tearDown() {
   49.94 +        lookupManager=null;
   49.95 +        result=null;
   49.96 +    }
   49.97 +    
   49.98 +    @Test
   49.99 +    public void testLookupBug() {
  49.100 +        TestLookupItemA itemA1=new TestLookupItemA();
  49.101 +        TestLookupItemB itemB1=new TestLookupItemB();
  49.102 +        //
  49.103 +        addToLookup(itemA1);
  49.104 +        addToLookup(itemB1);
  49.105 +        removeFromLookup(itemA1);
  49.106 +        removeFromLookup(itemB1);
  49.107 +        addToLookup(itemB1);
  49.108 +        removeFromLookup(itemB1);
  49.109 +        //
  49.110 +        addToLookup(itemA1);
  49.111 +        addToLookup(itemB1);
  49.112 +        removeFromLookup(itemA1);
  49.113 +        removeFromLookup(itemB1);
  49.114 +        addToLookup(itemB1);
  49.115 +        removeFromLookup(itemB1);
  49.116 +        //
  49.117 +        addToLookup(itemA1);
  49.118 +        addToLookup(itemB1);
  49.119 +        removeFromLookup(itemA1);
  49.120 +        removeFromLookup(itemB1);
  49.121 +        addToLookup(itemB1);
  49.122 +        removeFromLookup(itemB1);
  49.123 +        //
  49.124 +        assertEquals(getResult(),lookupManager.getResult());
  49.125 +    }
  49.126 +
  49.127 +    public static final class TestLookupItemA {}
  49.128 +    public static final class TestLookupItemB {}
  49.129 +    public static final class TestLookupManager {
  49.130 +        private InstanceContent instanceContent=new InstanceContent();
  49.131 +        private AbstractLookup abstractLookup=new AbstractLookup(instanceContent);
  49.132 +
  49.133 +        private Lookup.Result<TestLookupItemA> resultA=null;
  49.134 +        private Lookup.Result<TestLookupItemB> resultB=null;
  49.135 +
  49.136 +        private LookupListener listenerA=new LookupListener() {
  49.137 +            public void resultChanged(LookupEvent event) {
  49.138 +                result.append('A');
  49.139 +            }
  49.140 +        };
  49.141 +        private LookupListener listenerB=new LookupListener() {
  49.142 +            public void resultChanged(LookupEvent event) {
  49.143 +                result.append('B');
  49.144 +            }
  49.145 +        };
  49.146 +
  49.147 +        private StringBuffer result=new StringBuffer();
  49.148 +
  49.149 +        //
  49.150 +
  49.151 +        public TestLookupManager() {
  49.152 +            Lookup.Template<TestLookupItemA> templateA=
  49.153 +                new Lookup.Template<TestLookupItemA>(TestLookupItemA.class);
  49.154 +            resultA=abstractLookup.lookup(templateA);
  49.155 +            resultA.addLookupListener(listenerA);
  49.156 +            resultA.allInstances().size();
  49.157 +            //
  49.158 +            Lookup.Template<TestLookupItemB> templateB=
  49.159 +                new Lookup.Template<TestLookupItemB>(TestLookupItemB.class);
  49.160 +            resultB=abstractLookup.lookup(templateB);
  49.161 +            resultB.addLookupListener(listenerB);
  49.162 +            resultB.allInstances().size();
  49.163 +            // WORKAROUND
  49.164 +            // instanceContent.add(Boolean.TRUE);
  49.165 +        }
  49.166 +
  49.167 +        //
  49.168 +
  49.169 +        public void add(Object item) {
  49.170 +            instanceContent.add(item);
  49.171 +        }
  49.172 +        public void remove(Object item) {
  49.173 +            instanceContent.remove(item);
  49.174 +        }
  49.175 +        public String getResult() {
  49.176 +            return result.toString();
  49.177 +        }
  49.178 +    }
  49.179 +
  49.180 +}
    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/LookupBugTest.java	Sat Oct 31 15:28:13 2009 +0100
    50.3 @@ -0,0 +1,79 @@
    50.4 +package org.openide.util.lookup;
    50.5 +
    50.6 +import java.util.logging.Logger;
    50.7 +import org.junit.Before;
    50.8 +import org.junit.Test;
    50.9 +import org.openide.util.Lookup;
   50.10 +import org.openide.util.LookupEvent;
   50.11 +import org.openide.util.LookupListener;
   50.12 +import static org.junit.Assert.*;
   50.13 +
   50.14 +/**
   50.15 + * Test of a Lookup bug seen in NetBeans platforms 6.0-6.5M1.
   50.16 + * @author rlee
   50.17 + */
   50.18 +public class LookupBugTest implements LookupListener
   50.19 +{
   50.20 +    private static final int MAX_LOOPS = 1000;
   50.21 +    
   50.22 +    private AbstractLookup lookup;
   50.23 +    private InstanceContent content;
   50.24 +    private Lookup.Result<String> wordResult;
   50.25 +    private Lookup.Result<Integer> numberResult;
   50.26 +    private String word;
   50.27 +    private Integer number;
   50.28 +    private Logger LOG;
   50.29 +    
   50.30 +    private boolean fired;
   50.31 +    private int i;
   50.32 +
   50.33 +    @Before
   50.34 +    public void setUp()
   50.35 +    {
   50.36 +        LOG = Logger.getLogger("test.LookupBugTest");
   50.37 +        content = new InstanceContent();
   50.38 +        lookup = new AbstractLookup(content);
   50.39 +        wordResult = lookup.lookupResult(java.lang.String.class);
   50.40 +        wordResult.addLookupListener(this);
   50.41 +        numberResult = lookup.lookupResult(java.lang.Integer.class);
   50.42 +        numberResult.addLookupListener(this);
   50.43 +        
   50.44 +        fired = false;
   50.45 +    }
   50.46 +    
   50.47 +    @Test
   50.48 +    public void lookupTest()
   50.49 +    {
   50.50 +        for(i = 0; i < MAX_LOOPS; i++ )
   50.51 +        {
   50.52 +            word = String.valueOf(i);
   50.53 +            number = new Integer(i);
   50.54 +            content.add(word);
   50.55 +            assertTrue( "word on loop " + i, checkLookupEventFired() );
   50.56 +            content.add(number);
   50.57 +            assertTrue( "number on loop " + i, checkLookupEventFired() );
   50.58 +            content.remove(word);
   50.59 +            assertTrue( "remove word on loop " + i, checkLookupEventFired() );
   50.60 +            content.remove(number);
   50.61 +            assertTrue( "remove number on loop " + i, checkLookupEventFired() );
   50.62 +
   50.63 +            assertTrue("The lookup still needs to stay simple", AbstractLookup.isSimple(lookup));
   50.64 +        }
   50.65 +    }
   50.66 +
   50.67 +    public void resultChanged(LookupEvent ev)
   50.68 +    {
   50.69 +        fired = true;
   50.70 +    }
   50.71 +    
   50.72 +    public boolean checkLookupEventFired()
   50.73 +    {
   50.74 +        LOG.fine("  round: " + i + " word = " + word + " number = " + number);
   50.75 +        if( fired )
   50.76 +        {
   50.77 +            fired = false;
   50.78 +            return true;
   50.79 +        }
   50.80 +        else return false;
   50.81 +    }
   50.82 +}
    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/LookupsProxyTest.java	Sat Oct 31 15:28:13 2009 +0100
    51.3 @@ -0,0 +1,282 @@
    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.io.Serializable;
   51.48 +
   51.49 +import java.util.*;
   51.50 +import org.netbeans.junit.*;
   51.51 +import org.openide.util.Lookup;
   51.52 +import org.openide.util.LookupEvent;
   51.53 +import org.openide.util.LookupListener;
   51.54 +
   51.55 +/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
   51.56 + */
   51.57 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   51.58 +public class LookupsProxyTest extends AbstractLookupBaseHid
   51.59 +implements AbstractLookupBaseHid.Impl {
   51.60 +    public LookupsProxyTest(java.lang.String testName) {
   51.61 +        super(testName, null);
   51.62 +    }
   51.63 +
   51.64 +    public static void main(java.lang.String[] args) {
   51.65 +        junit.textui.TestRunner.run(new NbTestSuite (LookupsProxyTest.class));
   51.66 +    }
   51.67 +    
   51.68 +    /** Creates an lookup for given lookup. This class just returns 
   51.69 +     * the object passed in, but subclasses can be different.
   51.70 +     * @param lookup in lookup
   51.71 +     * @return a lookup to use
   51.72 +     */
   51.73 +    public Lookup createLookup (final Lookup lookup) {
   51.74 +        return org.openide.util.lookup.Lookups.proxy (
   51.75 +            new Lookup.Provider () {
   51.76 +                public Lookup getLookup () {
   51.77 +                    return lookup;
   51.78 +                }
   51.79 +            }
   51.80 +        );
   51.81 +    }
   51.82 +    
   51.83 +    public Lookup createInstancesLookup (InstanceContent ic) {
   51.84 +        return new AbstractLookup (ic);
   51.85 +    }
   51.86 +
   51.87 +    public void clearCaches () {
   51.88 +    }    
   51.89 +    
   51.90 +    
   51.91 +   
   51.92 +    /** Check whether setLookups method does not fire when there is no
   51.93 +     * change in the lookups.
   51.94 +     */
   51.95 +    public void testProxyListener () {
   51.96 +        Changer ch = new Changer (Lookup.EMPTY);
   51.97 +        
   51.98 +        Lookup lookup = Lookups.proxy(ch);
   51.99 +        Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
  51.100 +        
  51.101 +        LL ll = new LL ();
  51.102 +        res.addLookupListener (ll);
  51.103 +        Collection allRes = res.allInstances ();
  51.104 +
  51.105 +        ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
  51.106 +        lookup.lookup (Object.class); // does the refresh
  51.107 +        
  51.108 +        assertEquals("Replacing an empty by empty does not generate an event", 0, ll.getCount());
  51.109 +        
  51.110 +        InstanceContent content = new InstanceContent ();
  51.111 +        AbstractLookup del = new AbstractLookup (content);
  51.112 +        content.add (this);
  51.113 +        ch.setLookup (del);
  51.114 +        lookup.lookup (Object.class);
  51.115 +        
  51.116 +        if (ll.getCount () != 1) {
  51.117 +            fail ("Changing lookups with different content generates an event");
  51.118 +        }
  51.119 +        
  51.120 +        ch.setLookup (del);
  51.121 +        lookup.lookup (Object.class);
  51.122 +        
  51.123 +        if (ll.getCount () != 0) {
  51.124 +           fail ("Not changing the lookups does not generate any event");
  51.125 +        }
  51.126 +    }
  51.127 +
  51.128 +    
  51.129 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
  51.130 +        doListeningAndQueryingByTwoListenersSetLookups(0, 1, false);
  51.131 +    }
  51.132 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
  51.133 +        doListeningAndQueryingByTwoListenersSetLookups(1, 1, false);        
  51.134 +    }
  51.135 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
  51.136 +        doListeningAndQueryingByTwoListenersSetLookups(2, 1, false);
  51.137 +    }
  51.138 +    
  51.139 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
  51.140 +        doListeningAndQueryingByTwoListenersSetLookups(0, 2, false);
  51.141 +    }
  51.142 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
  51.143 +        doListeningAndQueryingByTwoListenersSetLookups(1, 2, false);        
  51.144 +    }
  51.145 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
  51.146 +        doListeningAndQueryingByTwoListenersSetLookups(2, 2, false);
  51.147 +    }
  51.148 +
  51.149 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookupsWithProxy() {
  51.150 +        doListeningAndQueryingByTwoListenersSetLookups(0, 1, true);
  51.151 +    }
  51.152 +    public void testListeningAndQueryingByTwoListenersClassesSetLookupsWithProxy() {
  51.153 +        doListeningAndQueryingByTwoListenersSetLookups(1, 1, true);        
  51.154 +    }
  51.155 +    public void testListeningAndQueryingByTwoListenersItemsSetLookupsWithProxy() {
  51.156 +        doListeningAndQueryingByTwoListenersSetLookups(2, 1, true);
  51.157 +    }
  51.158 +    
  51.159 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2WithProxy() {
  51.160 +        doListeningAndQueryingByTwoListenersSetLookups(0, 2, true);
  51.161 +    }
  51.162 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups2WithProxy() {
  51.163 +        doListeningAndQueryingByTwoListenersSetLookups(1, 2, true);        
  51.164 +    }
  51.165 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups2WithProxy() {
  51.166 +        doListeningAndQueryingByTwoListenersSetLookups(2, 2, true);
  51.167 +    }
  51.168 +    
  51.169 +    /* XXX: these are pretty slow, seems there is a performance problem 2^22
  51.170 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
  51.171 +        doListeningAndQueryingByTwoListenersSetLookups(0, 22);
  51.172 +    }
  51.173 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
  51.174 +        doListeningAndQueryingByTwoListenersSetLookups(1, 22);        
  51.175 +    }
  51.176 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
  51.177 +        doListeningAndQueryingByTwoListenersSetLookups(2, 22);
  51.178 +    }
  51.179 +     */
  51.180 +    
  51.181 +    private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth, boolean cacheOnTop) {
  51.182 +        Changer orig = new Changer(Lookup.EMPTY);
  51.183 +        Lookup on = Lookups.proxy(orig);
  51.184 +        Lookup first = on;
  51.185 +        
  51.186 +        while (--depth > 0) {
  51.187 +            Changer next = new Changer(on);
  51.188 +            on = Lookups.proxy(next);
  51.189 +        }
  51.190 +        
  51.191 +        
  51.192 +        final Lookup lookup = cacheOnTop ? new ProxyLookup(new Lookup[] { on }) : on;
  51.193 +        
  51.194 +        class L implements LookupListener {
  51.195 +            Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
  51.196 +            Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
  51.197 +            Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
  51.198 +            
  51.199 +            {
  51.200 +                integer.addLookupListener(this);
  51.201 +                number.addLookupListener(this);
  51.202 +                serial.addLookupListener(this);
  51.203 +            }
  51.204 +            
  51.205 +            int round;
  51.206 +            
  51.207 +            public void resultChanged(LookupEvent ev) {
  51.208 +                Collection c1 = get(type, integer);
  51.209 +                Collection c2 = get(type, number);
  51.210 +                Collection c3 = get(type, serial);
  51.211 +                
  51.212 +                assertEquals("round " + round + " c1 vs. c2", c1, c2);
  51.213 +                assertEquals("round " + round + " c1 vs. c3", c1, c3);
  51.214 +                assertEquals("round " + round + " c2 vs. c3", c2, c3);
  51.215 +                
  51.216 +                round++;
  51.217 +            }            
  51.218 +
  51.219 +            private Collection get(int type, Lookup.Result res) {
  51.220 +                Collection c;
  51.221 +                switch(type) {
  51.222 +                    case 0: c = res.allInstances(); break;
  51.223 +                    case 1: c = res.allClasses(); break;
  51.224 +                    case 2: c = res.allItems(); break;
  51.225 +                    default: c = null; fail("Type: " + type); break;
  51.226 +                }
  51.227 +                
  51.228 +                assertNotNull(c);
  51.229 +                return new ArrayList(c);
  51.230 +            }
  51.231 +        }
  51.232 +        
  51.233 +        L listener = new L();
  51.234 +        listener.resultChanged(null);
  51.235 +        ArrayList arr = new ArrayList();
  51.236 +        for(int i = 0; i < 100; i++) {
  51.237 +            arr.add(new Integer(i));
  51.238 +            
  51.239 +            orig.lookup = Lookups.fixed(arr.toArray());
  51.240 +            // do the refresh
  51.241 +            first.lookup((Class)null);
  51.242 +        }
  51.243 +        
  51.244 +        assertEquals("3x100+1 checks", 301, listener.round);
  51.245 +    }
  51.246 +    
  51.247 +    
  51.248 +    public void testRefreshWithoutAllInstances103300 () {
  51.249 +        Changer ch = new Changer (Lookup.EMPTY);
  51.250 +        
  51.251 +        Lookup lookup = Lookups.proxy(ch);
  51.252 +
  51.253 +        ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
  51.254 +        assertNull("Nothing there", lookup.lookup (Object.class)); // does the refresh
  51.255 +        
  51.256 +        InstanceContent content = new InstanceContent ();
  51.257 +        AbstractLookup del = new AbstractLookup (content);
  51.258 +        content.add (this);
  51.259 +        ch.setLookup (del);
  51.260 +        assertEquals("Can see me", this, lookup.lookup (Object.class));
  51.261 +        
  51.262 +        ch.setLookup (del);
  51.263 +        assertEquals("Still can see me", this, lookup.lookup (Object.class));
  51.264 +
  51.265 +        assertEquals("I am visible", this, lookup.lookup(LookupsProxyTest.class));
  51.266 +    }
  51.267 +
  51.268 +
  51.269 +    private static final class Changer implements Lookup.Provider {
  51.270 +        private Lookup lookup;
  51.271 +        
  51.272 +        public Changer (Lookup lookup) {
  51.273 +            setLookup (lookup);
  51.274 +        }
  51.275 +        
  51.276 +        public void setLookup (Lookup lookup) {
  51.277 +            this.lookup = lookup;
  51.278 +        }
  51.279 +        
  51.280 +        public Lookup getLookup() {
  51.281 +            return lookup;
  51.282 +        }
  51.283 +    }
  51.284 +
  51.285 +}
    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/MetaInfServicesLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    52.3 @@ -0,0 +1,550 @@
    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.io.ByteArrayInputStream;
   52.48 +import java.io.File;
   52.49 +import java.io.FileOutputStream;
   52.50 +import java.io.IOException;
   52.51 +import java.io.InputStream;
   52.52 +import java.io.InputStreamReader;
   52.53 +import java.lang.ref.Reference;
   52.54 +import java.lang.ref.WeakReference;
   52.55 +import java.net.URL;
   52.56 +import java.net.URLClassLoader;
   52.57 +import java.net.URLConnection;
   52.58 +import java.net.URLStreamHandler;
   52.59 +import java.util.ArrayList;
   52.60 +import java.util.Collection;
   52.61 +import java.util.Collections;
   52.62 +import java.util.Comparator;
   52.63 +import java.util.Enumeration;
   52.64 +import java.util.HashSet;
   52.65 +import java.util.Iterator;
   52.66 +import java.util.List;
   52.67 +import java.util.Map;
   52.68 +import java.util.Set;
   52.69 +import java.util.TreeSet;
   52.70 +import java.util.WeakHashMap;
   52.71 +import java.util.concurrent.atomic.AtomicBoolean;
   52.72 +import java.util.jar.JarEntry;
   52.73 +import java.util.jar.JarOutputStream;
   52.74 +import java.util.logging.Level;
   52.75 +import java.util.logging.Logger;
   52.76 +import java.util.regex.Matcher;
   52.77 +import java.util.regex.Pattern;
   52.78 +import org.bar.Comparator2;
   52.79 +import org.netbeans.junit.MockServices;
   52.80 +import org.netbeans.junit.NbTestCase;
   52.81 +import org.openide.util.Enumerations;
   52.82 +import org.openide.util.Exceptions;
   52.83 +import org.openide.util.Lookup;
   52.84 +import org.openide.util.LookupEvent;
   52.85 +import org.openide.util.LookupListener;
   52.86 +import org.openide.util.test.MockLookup;
   52.87 +
   52.88 +/** Test finding services from manifest.
   52.89 + * @author Jesse Glick
   52.90 + */
   52.91 +public class MetaInfServicesLookupTest extends NbTestCase {
   52.92 +    private Logger LOG;
   52.93 +    private Map<ClassLoader,Lookup> lookups = new WeakHashMap<ClassLoader,Lookup>();
   52.94 +    
   52.95 +    public MetaInfServicesLookupTest(String name) {
   52.96 +        super(name);
   52.97 +        LOG = Logger.getLogger("Test." + name);
   52.98 +    }
   52.99 +
  52.100 +    protected String prefix() {
  52.101 +        return "META-INF/services/";
  52.102 +    }
  52.103 +    
  52.104 +    protected Lookup createLookup(ClassLoader c) {
  52.105 +        return Lookups.metaInfServices(c);
  52.106 +    }
  52.107 +    
  52.108 +    @Override
  52.109 +    protected Level logLevel() {
  52.110 +        return Level.INFO;
  52.111 +    }
  52.112 +
  52.113 +    private Lookup getTestedLookup(ClassLoader c) {
  52.114 +        MockServices.setServices();
  52.115 +        Lookup l = lookups.get(c);
  52.116 +        if (l == null) {
  52.117 +            l = createLookup(c);
  52.118 +            lookups.put(c, l);
  52.119 +        }
  52.120 +        return l;
  52.121 +    }
  52.122 +
  52.123 +    private URL findJar(String n) throws IOException {
  52.124 +        LOG.info("Looking for " + n);
  52.125 +        File jarDir = new File(getWorkDir(), "jars");
  52.126 +        jarDir.mkdirs();
  52.127 +        File jar = new File(jarDir, n);
  52.128 +        if (jar.exists()) {
  52.129 +            return jar.toURI().toURL();
  52.130 +        }
  52.131 +        
  52.132 +        LOG.info("generating " + jar);
  52.133 +        
  52.134 +        URL data = MetaInfServicesLookupTest.class.getResource(n.replaceAll("\\.jar", "\\.txt"));
  52.135 +        assertNotNull("Data found", data);
  52.136 +        StringBuffer sb = new StringBuffer();
  52.137 +        InputStreamReader r = new InputStreamReader(data.openStream());
  52.138 +        for(;;) {
  52.139 +            int ch = r.read();
  52.140 +            if (ch == -1) {
  52.141 +                break;
  52.142 +            }
  52.143 +            sb.append((char)ch);
  52.144 +        }
  52.145 +        
  52.146 +        JarOutputStream os = new JarOutputStream(new FileOutputStream(jar));
  52.147 +        
  52.148 +        Pattern p = Pattern.compile(":([^:]+):([^:]*)", Pattern.MULTILINE | Pattern.DOTALL);
  52.149 +        Matcher m = p.matcher(sb);
  52.150 +        Pattern foobar = Pattern.compile("^(org\\.(foo|bar)\\..*)$", Pattern.MULTILINE);
  52.151 +        Set<String> names = new TreeSet<String>();
  52.152 +        while (m.find()) {
  52.153 +            assert m.groupCount() == 2;
  52.154 +            String entryName = prefix() + m.group(1);
  52.155 +            LOG.info("putting there entry: " + entryName);
  52.156 +            os.putNextEntry(new JarEntry(entryName));
  52.157 +            os.write(m.group(2).getBytes());
  52.158 +            os.closeEntry();
  52.159 +            
  52.160 +            Matcher fb = foobar.matcher(m.group(2));
  52.161 +            while (fb.find()) {
  52.162 +                String clazz = fb.group(1).replace('.', '/') + ".class";
  52.163 +                LOG.info("will copy " + clazz);
  52.164 +                names.add(clazz);
  52.165 +            }
  52.166 +        }
  52.167 +        
  52.168 +        for (String copy : names) {
  52.169 +            os.putNextEntry(new JarEntry(copy));
  52.170 +            LOG.info("copying " + copy);
  52.171 +            InputStream from = MetaInfServicesLookupTest.class.getResourceAsStream("/" + copy);
  52.172 +            assertNotNull(copy, from);
  52.173 +            for (;;) {
  52.174 +                int ch = from.read();
  52.175 +                if (ch == -1) {
  52.176 +                    break;
  52.177 +                }
  52.178 +                os.write(ch);
  52.179 +            }
  52.180 +            from.close();
  52.181 +            os.closeEntry();
  52.182 +        }
  52.183 +        os.close();
  52.184 +        LOG.info("done " + jar);
  52.185 +        return jar.toURI().toURL();
  52.186 +    }
  52.187 +
  52.188 +    ClassLoader c1, c2, c2a, c3, c4;
  52.189 +
  52.190 +    @Override
  52.191 +    protected void setUp() throws Exception {
  52.192 +        clearWorkDir();
  52.193 +        ClassLoader app = getClass().getClassLoader().getParent();
  52.194 +        ClassLoader c0 = app;
  52.195 +        
  52.196 +        c1 = new URLClassLoader(new URL[] {
  52.197 +            findJar("services-jar-1.jar"),
  52.198 +        }, c0);
  52.199 +        c2 = new URLClassLoader(new URL[] {
  52.200 +            findJar("services-jar-2.jar"),
  52.201 +        }, c1);
  52.202 +        c2a = new URLClassLoader(new URL[] {
  52.203 +            findJar("services-jar-2.jar"),
  52.204 +        }, c1);
  52.205 +        c3 = new URLClassLoader(new URL[] { findJar("services-jar-2.jar") },
  52.206 +            c0
  52.207 +        );
  52.208 +        c4 = new URLClassLoader(new URL[] {
  52.209 +            findJar("services-jar-1.jar"),
  52.210 +            findJar("services-jar-2.jar"),
  52.211 +        }, c0);
  52.212 +    }
  52.213 +
  52.214 +    @Override
  52.215 +    protected void tearDown() throws Exception {
  52.216 +        Set<Reference<Lookup>> weak = new HashSet<Reference<Lookup>>();
  52.217 +        for (Lookup l : lookups.values()) {
  52.218 +            weak.add(new WeakReference<Lookup>(l));
  52.219 +        }
  52.220 +        
  52.221 +        lookups = null;
  52.222 +        
  52.223 +        for(Reference<Lookup> ref : weak) {
  52.224 +            assertGC("Lookup can disappear", ref);
  52.225 +        }
  52.226 +    }
  52.227 +
  52.228 +    public void testBasicUsage() throws Exception {
  52.229 +        Lookup l = getTestedLookup(c2);
  52.230 +        Class<?> xface = c1.loadClass("org.foo.Interface");
  52.231 +        List<?> results = new ArrayList<Object>(l.lookupAll(xface));
  52.232 +        assertEquals("Two items in result: " + results, 2, results.size());
  52.233 +        // Note that they have to be in order:
  52.234 +        assertEquals("org.foo.impl.Implementation1", results.get(0).getClass().getName());
  52.235 +        assertEquals("org.bar.Implementation2", results.get(1).getClass().getName());
  52.236 +        // Make sure it does not gratuitously replace items:
  52.237 +        List<?> results2 = new ArrayList<Object>(l.lookupAll(xface));
  52.238 +        assertEquals(results, results2);
  52.239 +    }
  52.240 +
  52.241 +    public void testLoaderSkew() throws Exception {
  52.242 +        Class<?> xface1 = c1.loadClass("org.foo.Interface");
  52.243 +        Lookup l3 = getTestedLookup(c3);
  52.244 +        // If we cannot load Interface, there should be no impls of course... quietly!
  52.245 +        assertEquals(Collections.emptyList(),
  52.246 +                new ArrayList<Object>(l3.lookupAll(xface1)));
  52.247 +        Lookup l4 = getTestedLookup(c4);
  52.248 +        // If we can load Interface but it is the wrong one, ignore it.
  52.249 +        assertEquals(Collections.emptyList(),
  52.250 +                new ArrayList<Object>(l4.lookupAll(xface1)));
  52.251 +        // Make sure l4 is really OK - it can load from its own JARs.
  52.252 +        Class<?> xface4 = c4.loadClass("org.foo.Interface");
  52.253 +        assertEquals(2, l4.lookupAll(xface4).size());
  52.254 +    }
  52.255 +
  52.256 +    public void testStability() throws Exception {
  52.257 +        Lookup l = getTestedLookup(c2);
  52.258 +        Class<?> xface = c1.loadClass("org.foo.Interface");
  52.259 +        Object first = l.lookup(xface);
  52.260 +        assertEquals(first, l.lookupAll(xface).iterator().next());
  52.261 +        l = getTestedLookup(c2a);
  52.262 +        Object second = l.lookup(xface);
  52.263 +        assertEquals(first, second);
  52.264 +    }
  52.265 +
  52.266 +    public void testMaskingOfResources() throws Exception {
  52.267 +        Lookup l1 = getTestedLookup(c1);
  52.268 +        Lookup l2 = getTestedLookup(c2);
  52.269 +        Lookup l4 = getTestedLookup(c4);
  52.270 +
  52.271 +        assertNotNull("services1.jar defines a class that implements runnable", l1.lookup(Runnable.class));
  52.272 +        assertNull("services2.jar does not defines a class that implements runnable", l2.lookup(Runnable.class));
  52.273 +        assertNull("services1.jar defines Runnable, but services2.jar masks it out", l4.lookup(Runnable.class));
  52.274 +    }
  52.275 +
  52.276 +    public void testOrdering() throws Exception {
  52.277 +        Lookup l = getTestedLookup(c1);
  52.278 +        Class<?> xface = c1.loadClass("java.util.Comparator");
  52.279 +        List<?> results = new ArrayList<Object>(l.lookupAll(xface));
  52.280 +        assertEquals(1, results.size());
  52.281 +
  52.282 +        l = getTestedLookup(c2);
  52.283 +        xface = c2.loadClass("java.util.Comparator");
  52.284 +        results = new ArrayList<Object>(l.lookupAll(xface));
  52.285 +        assertEquals(2, results.size());
  52.286 +        // Test order:
  52.287 +        assertEquals("org.bar.Comparator2", results.get(0).getClass().getName());
  52.288 +        assertEquals("org.foo.impl.Comparator1", results.get(1).getClass().getName());
  52.289 +
  52.290 +        // test that items without position are always at the end
  52.291 +        l = getTestedLookup(c2);
  52.292 +        xface = c2.loadClass("java.util.Iterator");
  52.293 +        results = new ArrayList<Object>(l.lookupAll(xface));
  52.294 +        assertEquals(2, results.size());
  52.295 +        // Test order:
  52.296 +        assertEquals("org.bar.Iterator2", results.get(0).getClass().getName());
  52.297 +        assertEquals("org.foo.impl.Iterator1", results.get(1).getClass().getName());
  52.298 +    }
  52.299 +
  52.300 +    public void testNoCallToGetResourceForObjectIssue65124() throws Exception {
  52.301 +        class Loader extends ClassLoader {
  52.302 +            private int counter;
  52.303 +
  52.304 +            @Override
  52.305 +            protected URL findResource(String name) {
  52.306 +                if (name.equals(prefix() + "java.lang.Object")) {
  52.307 +                    counter++;
  52.308 +                }
  52.309 +
  52.310 +                URL retValue;
  52.311 +
  52.312 +                retValue = super.findResource(name);
  52.313 +                return retValue;
  52.314 +            }
  52.315 +
  52.316 +            @Override
  52.317 +            protected Enumeration<URL> findResources(String name) throws IOException {
  52.318 +                if (name.equals(prefix() + "java.lang.Object")) {
  52.319 +                    counter++;
  52.320 +                }
  52.321 +                return super.findResources(name);
  52.322 +            }
  52.323 +        }
  52.324 +        Loader loader = new Loader();
  52.325 +        Lookup l = getTestedLookup(loader);
  52.326 +
  52.327 +        Object no = l.lookup(String.class);
  52.328 +        assertNull("Not found of course", no);
  52.329 +        assertEquals("No lookup of Object", 0, loader.counter);
  52.330 +    }
  52.331 +
  52.332 +    public void testCanGarbageCollectClasses() throws Exception {
  52.333 +        class Loader extends ClassLoader {
  52.334 +            public Loader() {
  52.335 +                super(Loader.class.getClassLoader().getParent());
  52.336 +            }
  52.337 +
  52.338 +            @Override
  52.339 +            protected URL findResource(String name) {
  52.340 +                if (name.equals(prefix() + "java.lang.Runnable")) {
  52.341 +                    return Loader.class.getResource("MetaInfServicesLookupTestRunnable.txt");
  52.342 +                }
  52.343 +
  52.344 +                URL retValue;
  52.345 +
  52.346 +                retValue = super.findResource(name);
  52.347 +                return retValue;
  52.348 +            }
  52.349 +
  52.350 +            @Override
  52.351 +            protected Class<?> findClass(String name) throws ClassNotFoundException {
  52.352 +                if (name.equals("org.openide.util.lookup.MetaInfServicesLookupTestRunnable")) {
  52.353 +                    try {
  52.354 +                        InputStream is = getClass().getResourceAsStream("MetaInfServicesLookupTestRunnable.class");
  52.355 +                        byte[] arr = new byte[is.available()];
  52.356 +                        int read = is.read(arr);
  52.357 +                        assertEquals("Fully read", arr.length, read);
  52.358 +                        return defineClass(name, arr, 0, arr.length);
  52.359 +                    } catch (IOException ex) {
  52.360 +                        throw new ClassNotFoundException("Cannot load", ex);
  52.361 +                    }
  52.362 +                }
  52.363 +                throw new ClassNotFoundException();
  52.364 +            }
  52.365 +
  52.366 +
  52.367 +
  52.368 +            @Override
  52.369 +            protected Enumeration<URL> findResources(String name) throws IOException {
  52.370 +                if (name.equals(prefix() + "java.lang.Runnable")) {
  52.371 +                    return Collections.enumeration(Collections.singleton(findResource(name)));
  52.372 +                }
  52.373 +                return super.findResources(name);
  52.374 +            }
  52.375 +        }
  52.376 +        Loader loader = new Loader();
  52.377 +        Lookup l = getTestedLookup(loader);
  52.378 +
  52.379 +
  52.380 +        Object no = l.lookup(Runnable.class);
  52.381 +        assertNotNull("Found of course", no);
  52.382 +        assertEquals("The right name", "MetaInfServicesLookupTestRunnable", no.getClass().getSimpleName());
  52.383 +        if (no.getClass().getClassLoader() != loader) {
  52.384 +            fail("Wrong classloader: " + no.getClass().getClassLoader());
  52.385 +        }
  52.386 +
  52.387 +        WeakReference<Object> ref = new WeakReference<Object>(no.getClass());
  52.388 +        loader = null;
  52.389 +        no = null;
  52.390 +        l = null;
  52.391 +        lookups.clear();
  52.392 +        MockLookup.setInstances();
  52.393 +        Thread.currentThread().setContextClassLoader(null);
  52.394 +        assertGC("Class can be garbage collected", ref);
  52.395 +    }
  52.396 +
  52.397 +    public void testSuperTypes() throws Exception {
  52.398 +        doTestSuperTypes(createLookup(c2));
  52.399 +        doTestSuperTypes(new ProxyLookup(createLookup(c2)));
  52.400 +    }
  52.401 +    private void doTestSuperTypes(Lookup l) throws Exception {
  52.402 +        final Class<?> xface = c1.loadClass("org.foo.Interface");
  52.403 +        final Lookup.Result<Object> res = l.lookupResult(Object.class);
  52.404 +        assertEquals("Nothing yet", 0, res.allInstances().size());
  52.405 +        final AtomicBoolean event = new AtomicBoolean();
  52.406 +        final Thread here = Thread.currentThread();
  52.407 +        res.addLookupListener(new LookupListener() {
  52.408 +            public void resultChanged(LookupEvent ev) {
  52.409 +                if (Thread.currentThread() == here) {
  52.410 +                    event.set(true);
  52.411 +                }
  52.412 +            }
  52.413 +        });
  52.414 +        assertNotNull("Interface found", l.lookup(xface));
  52.415 +        assertFalse(event.get());
  52.416 +        class W implements Runnable {
  52.417 +            boolean ok;
  52.418 +            public synchronized void run() {
  52.419 +                ok = true;
  52.420 +                notifyAll();
  52.421 +            }
  52.422 +
  52.423 +            public synchronized void await() throws Exception {
  52.424 +                while (!ok) {
  52.425 +                    wait();
  52.426 +                }
  52.427 +            }
  52.428 +        }
  52.429 +        W w = new W();
  52.430 +        MetaInfServicesLookup.RP.execute(w);
  52.431 +        w.await();
  52.432 +        assertEquals("Now two", 2, res.allInstances().size());
  52.433 +    }
  52.434 +    
  52.435 +    public void testWrongOrderAsInIssue100320() throws Exception {
  52.436 +        ClassLoader app = getClass().getClassLoader().getParent();
  52.437 +        ClassLoader c0 = app;
  52.438 +        ClassLoader ctmp = new URLClassLoader(new URL[] {
  52.439 +            findJar("problem100320.jar"),
  52.440 +        }, c0);
  52.441 +        Lookup lookup = Lookups.metaInfServices(ctmp, prefix());
  52.442 +
  52.443 +        Collection<?> colAWT = lookup.lookupAll(IOException.class);
  52.444 +        assertEquals("There is enough objects to switch to InheritanceTree", 12, colAWT.size());
  52.445 +        
  52.446 +        
  52.447 +        List<?> col1 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
  52.448 +        assertEquals("Two", 2, col1.size());
  52.449 +        Collection<?> col2 = lookup.lookupAll(ctmp.loadClass(Comparator2.class.getName()));
  52.450 +        assertEquals("One", 1, col2.size());
  52.451 +        List<?> col3 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
  52.452 +        assertEquals("Two2", 2, col3.size());
  52.453 +        
  52.454 +        Iterator<?> it1 = col1.iterator();
  52.455 +        Iterator<?> it3 = col3.iterator();
  52.456 +        if (
  52.457 +            it1.next() != it3.next() || 
  52.458 +            it1.next() != it3.next() 
  52.459 +        ) {
  52.460 +            fail("Collections are different:\nFirst: " + col1 + "\nLast:  " + col3);
  52.461 +        }
  52.462 +    }
  52.463 +
  52.464 +    public void testContentionWhenLoadingMetainfServices() throws Exception {
  52.465 +        class My extends ClassLoader implements Runnable {
  52.466 +            Lookup query;
  52.467 +            Integer value;
  52.468 +
  52.469 +            public void run() {
  52.470 +                value = query.lookup(Integer.class);
  52.471 +            }
  52.472 +
  52.473 +
  52.474 +            @Override
  52.475 +            protected URL findResource(String name) {
  52.476 +                waitForTask(name);
  52.477 +                return super.findResource(name);
  52.478 +            }
  52.479 +
  52.480 +            @Override
  52.481 +            protected Enumeration<URL> findResources(String name) throws IOException {
  52.482 +                waitForTask(name);
  52.483 +                return super.findResources(name);
  52.484 +            }
  52.485 +
  52.486 +            private synchronized void waitForTask(String name) {
  52.487 +                if (name.startsWith(prefix()) && Thread.currentThread().getName().contains("block")) {
  52.488 +                    try {
  52.489 +                        wait();
  52.490 +                    } catch (InterruptedException ex) {
  52.491 +                        Exceptions.printStackTrace(ex);
  52.492 +                    }
  52.493 +                }
  52.494 +            }
  52.495 +        }
  52.496 +
  52.497 +        My loader = new My();
  52.498 +        loader.query = createLookup(loader);
  52.499 +        Thread t = new Thread(loader, "block when querying");
  52.500 +        t.start();
  52.501 +        t.join(1000);
  52.502 +
  52.503 +        // this blocks waiting for the waitForTask to finish
  52.504 +        // right now
  52.505 +        Float f = loader.query.lookup(Float.class);
  52.506 +        assertNull("Nothing found", f);
  52.507 +
  52.508 +        synchronized (loader) {
  52.509 +            loader.notifyAll();
  52.510 +        }
  52.511 +        t.join();
  52.512 +
  52.513 +        assertNull("Nothing found", loader.value);
  52.514 +    }
  52.515 +
  52.516 +    public void testInitializerRobustness() throws Exception { // #174055
  52.517 +        check(Broken1.class.getName());
  52.518 +        check(Broken2.class.getName());
  52.519 +    }
  52.520 +    private void check(final String n) {
  52.521 +        assertNull(Lookups.metaInfServices(new ClassLoader() {
  52.522 +            protected @Override Enumeration<URL> findResources(String name) throws IOException {
  52.523 +                if (name.equals("META-INF/services/java.lang.Object")) {
  52.524 +                    return Enumerations.singleton(new URL(null, "dummy:stuff", new URLStreamHandler() {
  52.525 +                        protected URLConnection openConnection(URL u) throws IOException {
  52.526 +                            return new URLConnection(u) {
  52.527 +                                public void connect() throws IOException {}
  52.528 +                                public @Override InputStream getInputStream() throws IOException {
  52.529 +                                    return new ByteArrayInputStream(n.getBytes("UTF-8"));
  52.530 +                                }
  52.531 +                            };
  52.532 +                        }
  52.533 +                    }));
  52.534 +                } else {
  52.535 +                    return Enumerations.empty();
  52.536 +                }
  52.537 +            }
  52.538 +        }).lookup(Object.class));
  52.539 +    }
  52.540 +    public static class Broken1 {
  52.541 +        public Broken1() {
  52.542 +            throw new NullPointerException("broken1");
  52.543 +        }
  52.544 +    }
  52.545 +    public static class Broken2 {
  52.546 +        static {
  52.547 +            if (true) { // otherwise javac complains
  52.548 +                throw new NullPointerException("broken2");
  52.549 +            }
  52.550 +        }
  52.551 +    }
  52.552 +
  52.553 +}
    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/MetaInfServicesLookupTestRunnable.java	Sat Oct 31 15:28:13 2009 +0100
    53.3 @@ -0,0 +1,50 @@
    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 +
   53.48 +/**
   53.49 + */
   53.50 +public final class MetaInfServicesLookupTestRunnable implements Runnable {
   53.51 +    public void run() {
   53.52 +    }
   53.53 +}
    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/MetaInfServicesLookupTestRunnable.txt	Sat Oct 31 15:28:13 2009 +0100
    54.3 @@ -0,0 +1,1 @@
    54.4 +org.openide.util.lookup.MetaInfServicesLookupTestRunnable
    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/NamedServicesLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    55.3 @@ -0,0 +1,85 @@
    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 +
   55.45 +package org.openide.util.lookup;
   55.46 +
   55.47 +import org.openide.util.Lookup;
   55.48 +import org.openide.util.test.MockLookup;
   55.49 +
   55.50 +
   55.51 +/** Test finding services from manifest.
   55.52 + * @author Jaroslav Tulach
   55.53 + */
   55.54 +public class NamedServicesLookupTest extends MetaInfServicesLookupTest {
   55.55 +    static {
   55.56 +        MockLookup.init();
   55.57 +    }
   55.58 +    public NamedServicesLookupTest(String name) {
   55.59 +        super(name);
   55.60 +    }
   55.61 +
   55.62 +    @Override
   55.63 +    protected String prefix() {
   55.64 +        return "META-INF/namedservices/sub/path/";
   55.65 +    }
   55.66 +    
   55.67 +    @Override
   55.68 +    protected Lookup createLookup(ClassLoader c) {
   55.69 +        MockLookup.setInstances(c);
   55.70 +        Thread.currentThread().setContextClassLoader(c);
   55.71 +        Lookup l = Lookups.forPath("sub/path");
   55.72 +        return l;
   55.73 +    }
   55.74 +    
   55.75 +    //
   55.76 +    // this is not much inheriting test, as we mask most of the tested methods
   55.77 +    // anyway, but the infrastructure to generate the JAR files is useful
   55.78 +    //
   55.79 +    
   55.80 +    public @Override void testLoaderSkew() {}
   55.81 +    public @Override void testStability() throws Exception {}
   55.82 +    public @Override void testMaskingOfResources() throws Exception {}
   55.83 +    public @Override void testOrdering() throws Exception {}
   55.84 +    public @Override void testNoCallToGetResourceForObjectIssue65124() throws Exception {}
   55.85 +    public @Override void testSuperTypes() throws Exception {}
   55.86 +    public @Override void testWrongOrderAsInIssue100320() throws Exception {}
   55.87 +    
   55.88 +}
    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/PathInLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    56.3 @@ -0,0 +1,112 @@
    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.logging.Level;
   56.48 +import org.netbeans.junit.MockServices;
   56.49 +import org.netbeans.junit.NbTestCase;
   56.50 +import org.netbeans.modules.openide.util.NamedServicesProvider;
   56.51 +import org.openide.util.Lookup;
   56.52 +
   56.53 +/** 
   56.54 + * @author Jaroslav Tulach
   56.55 + */
   56.56 +public class PathInLookupTest extends NbTestCase {
   56.57 +    static {
   56.58 +        System.setProperty("org.openide.util.Lookup.paths", "MyServices:YourServices");
   56.59 +        MockServices.setServices(P.class);
   56.60 +        Lookup.getDefault();
   56.61 +    }
   56.62 +
   56.63 +    public PathInLookupTest(String name) {
   56.64 +        super(name);
   56.65 +    }
   56.66 +
   56.67 +    @Override
   56.68 +    protected Level logLevel() {
   56.69 +        return Level.FINE;
   56.70 +    }
   56.71 +    
   56.72 +    public void testInterfaceFoundInMyServices() throws Exception {
   56.73 +        assertNull("not found", Lookup.getDefault().lookup(Shared.class));
   56.74 +        Shared v = new Shared();
   56.75 +        P.ic1.add(v);
   56.76 +        assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
   56.77 +        P.ic1.remove(v);
   56.78 +        assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
   56.79 +    }
   56.80 +    public void testInterfaceFoundInMyServices2() throws Exception {
   56.81 +        assertNull("not found", Lookup.getDefault().lookup(Shared.class));
   56.82 +        Shared v = new Shared();
   56.83 +        P.ic2.add(v);
   56.84 +        assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
   56.85 +        P.ic2.remove(v);
   56.86 +        assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
   56.87 +    }
   56.88 +
   56.89 +    static final class Shared extends Object {}
   56.90 +
   56.91 +    public static final class P extends NamedServicesProvider {
   56.92 +        static InstanceContent ic1 = new InstanceContent();
   56.93 +        static InstanceContent ic2 = new InstanceContent();
   56.94 +        static AbstractLookup[] arr = {
   56.95 +            new AbstractLookup(ic1), new AbstractLookup(ic2)
   56.96 +        };
   56.97 +
   56.98 +
   56.99 +        @Override
  56.100 +        public Lookup create(String path) {
  56.101 +            int indx = -1;
  56.102 +            if (path.equals("MyServices/")) {
  56.103 +                indx = 0;
  56.104 +            }
  56.105 +            if (path.equals("YourServices/")) {
  56.106 +                indx = 1;
  56.107 +            }
  56.108 +            if (indx == -1) {
  56.109 +                fail("Unexpected lookup query: " + path);
  56.110 +            }
  56.111 +            return arr[indx];
  56.112 +        }
  56.113 +    }
  56.114 +
  56.115 +}
    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/PrefixServicesLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    57.3 @@ -0,0 +1,63 @@
    57.4 +/*
    57.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    57.6 + *
    57.7 + * Copyright 1997-2009 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 + * Contributor(s):
   57.28 + *
   57.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   57.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   57.31 + * Microsystems, Inc. All Rights Reserved.
   57.32 + *
   57.33 + * If you wish your version of this file to be governed by only the CDDL
   57.34 + * or only the GPL Version 2, indicate your decision by adding
   57.35 + * "[Contributor] elects to include this software in this distribution
   57.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   57.37 + * single choice of license, a recipient has the option to distribute
   57.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   57.39 + * to extend the choice of license to its licensees as provided above.
   57.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   57.41 + * Version 2 license, then the option applies only if the new code is
   57.42 + * made subject to such option by the copyright holder.
   57.43 + */
   57.44 +
   57.45 +package org.openide.util.lookup;
   57.46 +
   57.47 +import org.openide.util.Lookup;
   57.48 +
   57.49 +
   57.50 +/** Test finding services from manifest.
   57.51 + * @author Jaroslav Tulach
   57.52 + */
   57.53 +public class PrefixServicesLookupTest extends MetaInfServicesLookupTest {
   57.54 +    public PrefixServicesLookupTest(String name) {
   57.55 +        super(name);
   57.56 +    }
   57.57 +    
   57.58 +    protected String prefix() {
   57.59 +        return "META-INF/netbeans/prefix/services/test/";
   57.60 +    }
   57.61 +    
   57.62 +    protected Lookup createLookup(ClassLoader c) {
   57.63 +        return Lookups.metaInfServices(c, prefix());
   57.64 +    }
   57.65 +    
   57.66 +}
    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/ProxyLookupEventIssue136866Test.java	Sat Oct 31 15:28:13 2009 +0100
    58.3 @@ -0,0 +1,56 @@
    58.4 +package org.openide.util.lookup;
    58.5 +
    58.6 +import junit.framework.TestCase;
    58.7 +import org.openide.util.Lookup;
    58.8 +import org.openide.util.LookupEvent;
    58.9 +import org.openide.util.LookupListener;
   58.10 +
   58.11 +/**
   58.12 + * Test case which demonstrates that ProxyLookup does not fire
   58.13 + * an event when it should.
   58.14 + */
   58.15 +public class ProxyLookupEventIssue136866Test extends TestCase {
   58.16 +
   58.17 +    public ProxyLookupEventIssue136866Test(String testName) {
   58.18 +        super(testName);
   58.19 +    }
   58.20 +
   58.21 +    public void testAbstractLookupFiresEventWhenContentChanged() {
   58.22 +        InstanceContent ic = new InstanceContent();
   58.23 +        AbstractLookup al = new AbstractLookup(ic);
   58.24 +
   58.25 +        final int[] counts = {0}; // Number of items observed upon a LookupEvent
   58.26 +        final Lookup.Result<String> result = al.lookupResult(String.class);
   58.27 +
   58.28 +        result.addLookupListener(new LookupListener() {
   58.29 +            public void resultChanged(LookupEvent ev) {
   58.30 +                // this gets called as expected
   58.31 +                assertSame(result, ev.getSource());
   58.32 +                counts[0] = result.allInstances().size();
   58.33 +            }
   58.34 +        });
   58.35 +        
   58.36 +        ic.add("hello1");
   58.37 +        assertEquals(1, counts[0]);
   58.38 +    }
   58.39 +    
   58.40 +    public void testProxyLookupFailsToFireEventWhenProxiedLookupChanged() {
   58.41 +        InstanceContent ic = new InstanceContent();
   58.42 +//        AbstractLookup al = new AbstractLookup(ic);
   58.43 +        Lookup proxy = new AbstractLookup(ic);
   58.44 +
   58.45 +        final int[] counts = {0}; // Number of items observed upon a LookupEvent
   58.46 +        final Lookup.Result<String> result = proxy.lookupResult(String.class);
   58.47 +
   58.48 +        result.addLookupListener(new LookupListener() {
   58.49 +            public void resultChanged(LookupEvent ev) {
   58.50 +                // this should be called but never is
   58.51 +                assertSame(result, ev.getSource());
   58.52 +                counts[0] = result.allInstances().size();
   58.53 +            }
   58.54 +        });
   58.55 +        
   58.56 +        ic.add("hello1");
   58.57 +        assertEquals(1, counts[0]);
   58.58 +    }
   58.59 +}
    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/ProxyLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    59.3 @@ -0,0 +1,655 @@
    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.lang.ref.Reference;
   59.50 +import java.lang.ref.WeakReference;
   59.51 +import java.util.*;
   59.52 +import java.util.concurrent.Executor;
   59.53 +import junit.framework.*;
   59.54 +import org.netbeans.junit.*;
   59.55 +import org.netbeans.modules.openide.util.ActiveQueue;
   59.56 +import org.openide.util.Lookup;
   59.57 +import org.openide.util.Lookup.Result;
   59.58 +import org.openide.util.LookupEvent;
   59.59 +import org.openide.util.LookupListener;
   59.60 +
   59.61 +/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
   59.62 + */
   59.63 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   59.64 +public class ProxyLookupTest extends AbstractLookupBaseHid
   59.65 +implements AbstractLookupBaseHid.Impl {
   59.66 +    public ProxyLookupTest(java.lang.String testName) {
   59.67 +        super(testName, null);
   59.68 +    }
   59.69 +
   59.70 +    public static Test suite() {
   59.71 +        return new NbTestSuite (ProxyLookupTest.class);
   59.72 +//        return new ProxyLookupTest("testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679");
   59.73 +    }
   59.74 +    
   59.75 +    /** Creates an lookup for given lookup. This class just returns 
   59.76 +     * the object passed in, but subclasses can be different.
   59.77 +     * @param lookup in lookup
   59.78 +     * @return a lookup to use
   59.79 +     */
   59.80 +    public Lookup createLookup (Lookup lookup) {
   59.81 +        return new ProxyLookup (new Lookup[] { lookup });
   59.82 +    }
   59.83 +    
   59.84 +    public Lookup createInstancesLookup (InstanceContent ic) {
   59.85 +        return new AbstractLookup (ic);
   59.86 +    }
   59.87 +    
   59.88 +
   59.89 +    public void clearCaches () {
   59.90 +    }    
   59.91 +    
   59.92 +    
   59.93 +    /** Check whether setLookups method does not fire when there is no
   59.94 +     * change in the lookups.
   59.95 +     */
   59.96 +    public void testProxyListener () {
   59.97 +        ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
   59.98 +
   59.99 +        final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
  59.100 +        final Object[] IGNORE = {
  59.101 +            ProxyLookup.ImmutableInternalData.EMPTY,
  59.102 +            ProxyLookup.ImmutableInternalData.EMPTY_ARR,
  59.103 +            ActiveQueue.queue(),
  59.104 +            Collections.emptyMap(),
  59.105 +            Collections.emptyList(),
  59.106 +            Collections.emptySet()
  59.107 +        };
  59.108 +        
  59.109 +        assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
  59.110 +        
  59.111 +        Lookup.Result<Object> res = lookup.lookup (template);
  59.112 +
  59.113 +        assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
  59.114 +        
  59.115 +        LL ll = new LL ();
  59.116 +        res.addLookupListener (ll);
  59.117 +        Collection allRes = res.allInstances ();
  59.118 +        
  59.119 +        lookup.setLookups (new Lookup[0]);
  59.120 +        
  59.121 +        if (ll.getCount () != 0) {
  59.122 +           fail ("Calling setLookups (emptyarray) fired a change");
  59.123 +        }
  59.124 +        
  59.125 +        InstanceContent t = new InstanceContent();
  59.126 +        Lookup del = new AbstractLookup (t);
  59.127 +        t.add("Ahoj");
  59.128 +        lookup.setLookups (new Lookup[] { del });
  59.129 +        
  59.130 +        if (ll.getCount () != 1) {
  59.131 +            fail ("Changing lookups did not generate an event");
  59.132 +        }
  59.133 +        
  59.134 +        lookup.setLookups (new Lookup[] { del });
  59.135 +        
  59.136 +        if (ll.getCount () != 0) {
  59.137 +           fail ("Calling setLookups (thesamearray) fired a change");
  59.138 +        }
  59.139 +    }
  59.140 +    
  59.141 +    public void testNoListenersProxyListener () {
  59.142 +        ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
  59.143 +        class E implements Executor {
  59.144 +            Runnable r;
  59.145 +            public void execute(Runnable command) {
  59.146 +                assertNull("NO previous", r);
  59.147 +                r = command;
  59.148 +            }
  59.149 +            public void perform() {
  59.150 +                assertNotNull("We shall have a runnable", r);
  59.151 +                r.run();
  59.152 +                r = null;
  59.153 +            }
  59.154 +        }
  59.155 +        E executor = new E();
  59.156 +                
  59.157 +
  59.158 +        final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
  59.159 +        final Object[] IGNORE = {
  59.160 +            ProxyLookup.ImmutableInternalData.EMPTY,
  59.161 +            ProxyLookup.ImmutableInternalData.EMPTY_ARR,
  59.162 +            ActiveQueue.queue(),
  59.163 +            Collections.emptyMap(),
  59.164 +            Collections.emptyList(),
  59.165 +            Collections.emptySet()
  59.166 +        };
  59.167 +        
  59.168 +        assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
  59.169 +        
  59.170 +        Lookup.Result<Object> res = lookup.lookup (template);
  59.171 +
  59.172 +        assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
  59.173 +        
  59.174 +        LL ll = new LL ();
  59.175 +        res.addLookupListener (ll);
  59.176 +        Collection allRes = res.allInstances ();
  59.177 +        
  59.178 +        lookup.setLookups (executor, new Lookup[0]);
  59.179 +        if (ll.getCount () != 0) {
  59.180 +           fail ("Calling setLookups (emptyarray) fired a change");
  59.181 +        }
  59.182 +        
  59.183 +        InstanceContent t = new InstanceContent();
  59.184 +        Lookup del = new AbstractLookup (t);
  59.185 +        t.add("Ahoj");
  59.186 +        lookup.setLookups (executor, new Lookup[] { del });
  59.187 +        assertEquals("No change yet", 0, ll.getCount());
  59.188 +        executor.perform();
  59.189 +        if (ll.getCount () != 1) {
  59.190 +            fail ("Changing lookups did not generate an event");
  59.191 +        }
  59.192 +        
  59.193 +        lookup.setLookups (executor, new Lookup[] { del });
  59.194 +        if (ll.getCount () != 0) {
  59.195 +           fail ("Calling setLookups (thesamearray) fired a change");
  59.196 +        }
  59.197 +    }
  59.198 +
  59.199 +    public void testSetLookups () throws Exception {
  59.200 +        AbstractLookup a1 = new AbstractLookup (new InstanceContent ());
  59.201 +        AbstractLookup a2 = new AbstractLookup (new InstanceContent ());
  59.202 +        
  59.203 +        InstanceContent i3 = new InstanceContent ();
  59.204 +        i3.add (i3);
  59.205 +        AbstractLookup a3 = new AbstractLookup (i3);
  59.206 +
  59.207 +        final ProxyLookup p = new ProxyLookup (new Lookup[] { a1, a2 });
  59.208 +        final Lookup.Result res1 = p.lookup (new Lookup.Template (Object.class));
  59.209 +        Collection c1 = res1.allInstances();
  59.210 +        
  59.211 +        Lookup.Result res2 = p.lookup (new Lookup.Template (String.class));
  59.212 +        Collection c2 = res2.allInstances ();
  59.213 +        
  59.214 +        
  59.215 +        assertTrue ("We need two results", res1 != res2);
  59.216 +
  59.217 +        final Object blocked = new Object ();
  59.218 +
  59.219 +        class L extends Object implements LookupListener {
  59.220 +            public void resultChanged (LookupEvent ev) {
  59.221 +                try {
  59.222 +                    res1.removeLookupListener(this);
  59.223 +                    
  59.224 +                    // waiting for second thread to start #111#
  59.225 +                    blocked.wait ();
  59.226 +
  59.227 +                } catch (Exception ex) {
  59.228 +                    ex.printStackTrace();
  59.229 +                    fail ("An exception occured ");
  59.230 +                }
  59.231 +            }
  59.232 +        }
  59.233 +        
  59.234 +        final L listener1 = new L ();
  59.235 +        res1.addLookupListener (listener1);
  59.236 +        
  59.237 +
  59.238 +        Runnable newLookupSetter = new Runnable() {
  59.239 +            public void run () {
  59.240 +                synchronized (blocked) {
  59.241 +                    try {
  59.242 +                        p.setLookups (new Lookup[0]);
  59.243 +                    } catch (Exception ex) {
  59.244 +                        ex.printStackTrace();
  59.245 +                        fail ("setLookups failed.");
  59.246 +                    } finally {
  59.247 +                        // starts the main thread #111#
  59.248 +                        blocked.notify ();
  59.249 +                    }
  59.250 +                }
  59.251 +            }
  59.252 +        };
  59.253 +        
  59.254 +        synchronized (blocked) {
  59.255 +            new Thread (newLookupSetter).start ();
  59.256 +            
  59.257 +            p.setLookups (new Lookup[] { a1, a2, a3 });
  59.258 +        }
  59.259 +    }
  59.260 +    
  59.261 +    public void testProxyLookupTemplateCaching(){
  59.262 +        Lookup lookups[] = new Lookup[1];
  59.263 +        doProxyLookupTemplateCaching(lookups, false);
  59.264 +    }
  59.265 +    
  59.266 +    public void testProxyLookupTemplateCachingOnSizeTwoArray() {
  59.267 +        Lookup lookups[] = new Lookup[2];
  59.268 +        lookups[1] = Lookup.EMPTY;
  59.269 +        doProxyLookupTemplateCaching(lookups, false);
  59.270 +    }
  59.271 +    public void testProxyLookupShallNotAllowModificationOfGetLookups(){
  59.272 +        Lookup lookups[] = new Lookup[1];
  59.273 +        doProxyLookupTemplateCaching(lookups, true);
  59.274 +    }
  59.275 +    
  59.276 +    public void testProxyLookupShallNotAllowModificationOfGetLookupsOnSizeTwoArray() {
  59.277 +        Lookup lookups[] = new Lookup[2];
  59.278 +        lookups[1] = Lookup.EMPTY;
  59.279 +        doProxyLookupTemplateCaching(lookups, true);
  59.280 +    }
  59.281 +    
  59.282 +    /** Index 0 of lookups will be modified, the rest is up to the 
  59.283 +     * setup code.
  59.284 +     */
  59.285 +    private void doProxyLookupTemplateCaching(Lookup[] lookups, boolean reget) {
  59.286 +        // Create MyProxyLookup with one lookup containing the String object
  59.287 +        InstanceContent inst = new InstanceContent();
  59.288 +        inst.add(new String("Hello World")); //NOI18N
  59.289 +        lookups[0] = new AbstractLookup(inst);
  59.290 +        ProxyLookup proxy = new ProxyLookup(lookups);
  59.291 +        if (reget) {
  59.292 +            lookups = proxy.getLookups();
  59.293 +        }
  59.294 +        
  59.295 +        // Performing template lookup for String object
  59.296 +        Lookup.Result result = proxy.lookup(new Lookup.Template(String.class, null, null));
  59.297 +        int stringTemplateResultSize = result.allInstances().size();
  59.298 +        assertEquals ("Ensure, there is only one instance of String.class in proxyLookup:", //NOI18N
  59.299 +                1, stringTemplateResultSize);
  59.300 +        
  59.301 +        // Changing lookup in proxy lookup, now it will contain 
  59.302 +        // StringBuffer Object instead of String
  59.303 +        InstanceContent ic2 = new InstanceContent();
  59.304 +        ic2.add(new Integer(1234567890));
  59.305 +        lookups[0] = new AbstractLookup(ic2);
  59.306 +        proxy.setLookups(lookups);
  59.307 +        
  59.308 +        assertEquals ("the old result is updated", 0, result.allInstances().size());
  59.309 +
  59.310 +        // Instance of String.class should not appear in proxyLookup
  59.311 +        Lookup.Result r2 = proxy.lookup(new Lookup.Template(String.class, null, null));
  59.312 +        assertEquals ("Instance of String.class should not appear in proxyLookup:", //NOI18N
  59.313 +                0, r2.allInstances().size());
  59.314 +
  59.315 +        Lookup.Result r3 = proxy.lookup(new Lookup.Template(Integer.class, null, null));
  59.316 +        assertEquals ("There is only one instance of Integer.class in proxyLookup:", //NOI18N
  59.317 +                1, r3.allInstances().size());
  59.318 +    }
  59.319 +    
  59.320 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
  59.321 +        doListeningAndQueryingByTwoListenersSetLookups(0, 1);
  59.322 +    }
  59.323 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
  59.324 +        doListeningAndQueryingByTwoListenersSetLookups(1, 1);        
  59.325 +    }
  59.326 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
  59.327 +        doListeningAndQueryingByTwoListenersSetLookups(2, 1);
  59.328 +    }
  59.329 +    
  59.330 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
  59.331 +        doListeningAndQueryingByTwoListenersSetLookups(0, 2);
  59.332 +    }
  59.333 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
  59.334 +        doListeningAndQueryingByTwoListenersSetLookups(1, 2);        
  59.335 +    }
  59.336 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
  59.337 +        doListeningAndQueryingByTwoListenersSetLookups(2, 2);
  59.338 +    }
  59.339 +    public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
  59.340 +        doListeningAndQueryingByTwoListenersSetLookups(0, 22);
  59.341 +    }
  59.342 +    public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
  59.343 +        doListeningAndQueryingByTwoListenersSetLookups(1, 22);        
  59.344 +    }
  59.345 +    public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
  59.346 +        doListeningAndQueryingByTwoListenersSetLookups(2, 22);
  59.347 +    }
  59.348 +    
  59.349 +    private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth) {
  59.350 +        ProxyLookup orig = new ProxyLookup();
  59.351 +        ProxyLookup on = orig;
  59.352 +        
  59.353 +        while (--depth > 0) {
  59.354 +            on = new ProxyLookup(new Lookup[] { on });
  59.355 +        }
  59.356 +        
  59.357 +        
  59.358 +        final ProxyLookup lookup = on;
  59.359 +        
  59.360 +        class L implements LookupListener {
  59.361 +            Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
  59.362 +            Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
  59.363 +            Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
  59.364 +            
  59.365 +            {
  59.366 +                integer.addLookupListener(this);
  59.367 +                number.addLookupListener(this);
  59.368 +                serial.addLookupListener(this);
  59.369 +            }
  59.370 +            
  59.371 +            int round;
  59.372 +            
  59.373 +            public void resultChanged(LookupEvent ev) {
  59.374 +                Collection c1 = get(type, integer);
  59.375 +                Collection c2 = get(type, number);
  59.376 +                Collection c3 = get(type, serial);
  59.377 +                
  59.378 +                assertEquals("round " + round + " c1 vs. c2", c1, c2);
  59.379 +                assertEquals("round " + round + " c1 vs. c3", c1, c3);
  59.380 +                assertEquals("round " + round + " c2 vs. c3", c2, c3);
  59.381 +                
  59.382 +                round++;
  59.383 +            }            
  59.384 +
  59.385 +            private Collection get(int type, Lookup.Result res) {
  59.386 +                Collection c;
  59.387 +                switch(type) {
  59.388 +                    case 0: c = res.allInstances(); break;
  59.389 +                    case 1: c = res.allClasses(); break;
  59.390 +                    case 2: c = res.allItems(); break;
  59.391 +                    default: c = null; fail("Type: " + type); break;
  59.392 +                }
  59.393 +                
  59.394 +                assertNotNull(c);
  59.395 +                return new ArrayList(c);
  59.396 +            }
  59.397 +        }
  59.398 +        
  59.399 +        L listener = new L();
  59.400 +        listener.resultChanged(null);
  59.401 +        ArrayList arr = new ArrayList();
  59.402 +        for(int i = 0; i < 100; i++) {
  59.403 +            arr.add(new Integer(i));
  59.404 +            
  59.405 +            orig.setLookups(new Lookup[] { Lookups.fixed(arr.toArray()) });
  59.406 +        }
  59.407 +        
  59.408 +        assertEquals("3x100+1 checks", 301, listener.round);
  59.409 +    }
  59.410 +
  59.411 +    static Object holder;
  59.412 +    
  59.413 +    public void testProxyWithLiveResultCanBeCollected() {
  59.414 +        Lookup layer0 = Lookups.singleton("Hello");
  59.415 +        Lookup layer1 = new ProxyLookup(new Lookup[] { layer0 });
  59.416 +        Lookup layer2 = new ProxyLookup(new Lookup[] { layer1 });
  59.417 +        Lookup.Result result1 = layer1.lookup(new Lookup.Template(String.class));
  59.418 +
  59.419 +        assertEquals("One instance", 1, result1.allInstances().size());
  59.420 +
  59.421 +        // this will create ProxyLookup$R which listens on origResult
  59.422 +        Lookup.Result result2 = layer2.lookup(new Lookup.Template(String.class));
  59.423 +        
  59.424 +        // this line is necessary. W/o actually querying the result,
  59.425 +        // it will nether compute it nor attach the listener.
  59.426 +        assertEquals("One instance", 1, result2.allInstances().size());
  59.427 +        
  59.428 +        result2.addLookupListener(new LookupListener() {
  59.429 +            public void resultChanged(LookupEvent ev) {}
  59.430 +        });
  59.431 +        
  59.432 +        Reference ref = new WeakReference(layer2);
  59.433 +        layer2 = null;
  59.434 +        result2 = null;
  59.435 +        try {
  59.436 +            holder = result1;
  59.437 +            assertGC ("The proxy lookup not been garbage collected!", ref);
  59.438 +        } finally {
  59.439 +            holder = null;
  59.440 +        }
  59.441 +    }
  59.442 +    
  59.443 +    public void testArrayIndexAsInIssue119292() throws Exception {
  59.444 +        final ProxyLookup pl = new ProxyLookup();
  59.445 +        final int[] cnt = { 0 };
  59.446 +        
  59.447 +        class L extends Lookup {
  59.448 +            L[] set;
  59.449 +            Lookup l;
  59.450 +            
  59.451 +            public L(String s) {
  59.452 +                l = Lookups.singleton(s);
  59.453 +            }
  59.454 +            
  59.455 +            @Override
  59.456 +            public <T> T lookup(Class<T> clazz) {
  59.457 +                return l.lookup(clazz);
  59.458 +            }
  59.459 +
  59.460 +            @Override
  59.461 +            public <T> Result<T> lookup(Template<T> template) {
  59.462 +                return l.lookup(template);
  59.463 +            }
  59.464 +
  59.465 +            @Override
  59.466 +            @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
  59.467 +            public boolean equals(Object obj) {
  59.468 +                if (set != null) {
  59.469 +                    cnt[0]++;
  59.470 +                    pl.setLookups(set);
  59.471 +                }
  59.472 +                return super.equals(obj);
  59.473 +            }
  59.474 +
  59.475 +            @Override
  59.476 +            public int hashCode() {
  59.477 +                int hash = 3;
  59.478 +                return hash;
  59.479 +            }
  59.480 +        }
  59.481 +
  59.482 +        Result<String> res = pl.lookupResult(String.class);
  59.483 +        assertEquals(Collections.EMPTY_LIST, res.allItems());
  59.484 +        
  59.485 +        L[] old = { new L("A"), new L("B") };
  59.486 +        L[] now = { new L("C") };
  59.487 +        
  59.488 +        pl.setLookups(old);
  59.489 +        cnt[0] = 0;
  59.490 +        
  59.491 +        old[0].set = new L[0];
  59.492 +        pl.setLookups(now);
  59.493 +
  59.494 +        assertEquals("No call to equals", 0, cnt[0]);
  59.495 +        
  59.496 +        assertEquals("Still assigned to C", Collections.singletonList("C"), res.allInstances());
  59.497 +    }
  59.498 +    
  59.499 +    public void testArrayIndexWithAddRemoveListenerAsInIssue119292() throws Exception {
  59.500 +        final ProxyLookup pl = new ProxyLookup();
  59.501 +        final int[] cnt = { 0 };
  59.502 +        
  59.503 +        class L extends Lookup {
  59.504 +            L[] set;
  59.505 +            Lookup l;
  59.506 +            
  59.507 +            public L(String s) {
  59.508 +                l = Lookups.singleton(s);
  59.509 +            }
  59.510 +            
  59.511 +            @Override
  59.512 +            public <T> T lookup(Class<T> clazz) {
  59.513 +                return l.lookup(clazz);
  59.514 +            }
  59.515 +
  59.516 +            @Override
  59.517 +            public <T> Result<T> lookup(Template<T> template) {
  59.518 +                Result<T> r = l.lookup(template);
  59.519 +                return new R<T>(r);
  59.520 +            }
  59.521 +
  59.522 +            final class R<T> extends Result<T> {
  59.523 +                private Result<T> delegate;
  59.524 +
  59.525 +                public R(Result<T> delegate) {
  59.526 +                    this.delegate = delegate;
  59.527 +                }
  59.528 +                
  59.529 +                @Override
  59.530 +                public void addLookupListener(LookupListener l) {
  59.531 +                    cnt[0]++;
  59.532 +                    if (set != null) {
  59.533 +                        pl.setLookups(set);
  59.534 +                    }
  59.535 +                    delegate.addLookupListener(l);
  59.536 +                }
  59.537 +
  59.538 +                @Override
  59.539 +                public void removeLookupListener(LookupListener l) {
  59.540 +                    cnt[0]++;
  59.541 +                    if (set != null) {
  59.542 +                        pl.setLookups(set);
  59.543 +                    }
  59.544 +                    delegate.removeLookupListener(l);
  59.545 +                }
  59.546 +
  59.547 +                @Override
  59.548 +                public Collection<? extends T> allInstances() {
  59.549 +                    return delegate.allInstances();
  59.550 +                }
  59.551 +            }
  59.552 +        }
  59.553 +
  59.554 +        Result<String> res = pl.lookupResult(String.class);
  59.555 +        assertEquals(Collections.EMPTY_LIST, res.allItems());
  59.556 +        
  59.557 +        L[] old = { new L("A"), new L("B") };
  59.558 +        L[] now = { new L("C") };
  59.559 +        
  59.560 +        pl.setLookups(old);
  59.561 +        cnt[0] = 0;
  59.562 +        
  59.563 +        old[0].set = new L[0];
  59.564 +        pl.setLookups(now);
  59.565 +
  59.566 +        if (cnt[0] == 0) {
  59.567 +            fail("There should be calls to listeners");
  59.568 +        }
  59.569 +        
  59.570 +        assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances());
  59.571 +    }
  59.572 +    
  59.573 +    
  59.574 +    public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception {
  59.575 +        final ProxyLookup pl = new ProxyLookup();
  59.576 +        final int[] cnt = { 0 };
  59.577 +        
  59.578 +        class L extends Lookup {
  59.579 +            L[] set;
  59.580 +            Lookup l;
  59.581 +            Collection<? extends Serializable> res;
  59.582 +            
  59.583 +            public L(String s) {
  59.584 +                l = Lookups.singleton(s);
  59.585 +            }
  59.586 +            
  59.587 +            @Override
  59.588 +            public <T> T lookup(Class<T> clazz) {
  59.589 +                return l.lookup(clazz);
  59.590 +            }
  59.591 +
  59.592 +            @Override
  59.593 +            public <T> Result<T> lookup(Template<T> template) {
  59.594 +                cnt[0]++;
  59.595 +                if (set != null) {
  59.596 +                    pl.setLookups(set);
  59.597 +                    res = pl.lookupAll(Serializable.class);
  59.598 +                }
  59.599 +                Result<T> r = l.lookup(template);
  59.600 +                return r;
  59.601 +            }
  59.602 +        }
  59.603 +
  59.604 +        L[] now = { new L("A"), new L("B") };
  59.605 +        L[] old = { new L("C") };
  59.606 +        pl.setLookups(old);
  59.607 +        old[0].set = now;
  59.608 +        
  59.609 +        Result<String> res = pl.lookupResult(String.class);
  59.610 +        assertEquals("New items visible", 2, res.allItems().size());
  59.611 +        
  59.612 +        
  59.613 +        pl.setLookups(new L("X"), new L("Y"), new L("Z"));
  59.614 +    }
  59.615 +    
  59.616 +    public void testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679() throws Exception {
  59.617 +        final ProxyLookup pl = new ProxyLookup();
  59.618 +        final int[] cnt = { 0 };
  59.619 +        
  59.620 +        class L extends Lookup {
  59.621 +            L[] set;
  59.622 +            Lookup l;
  59.623 +            Collection<? extends Serializable> res;
  59.624 +            
  59.625 +            public L(String s) {
  59.626 +                l = Lookups.singleton(s);
  59.627 +            }
  59.628 +            
  59.629 +            @Override
  59.630 +            public <T> T lookup(Class<T> clazz) {
  59.631 +                return l.lookup(clazz);
  59.632 +            }
  59.633 +
  59.634 +            @Override
  59.635 +            public <T> Result<T> lookup(Template<T> template) {
  59.636 +                cnt[0]++;
  59.637 +                if (set != null) {
  59.638 +                    pl.setLookups(set);
  59.639 +                    res = pl.lookupAll(Serializable.class);
  59.640 +                }
  59.641 +                Result<T> r = l.lookup(template);
  59.642 +                return r;
  59.643 +            }
  59.644 +        }
  59.645 +
  59.646 +        L dupl = new L("A");
  59.647 +        L[] now = { dupl };
  59.648 +        L[] old = { new L("C") };
  59.649 +        pl.setLookups(old);
  59.650 +        old[0].set = now;
  59.651 +        
  59.652 +        Result<String> res = pl.lookupResult(String.class);
  59.653 +        assertEquals("New items visible", 1, res.allItems().size());
  59.654 +        
  59.655 +        
  59.656 +        pl.setLookups(old);
  59.657 +    }
  59.658 +}
    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/SimpleLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    60.3 @@ -0,0 +1,351 @@
    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-2009 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.util.ArrayList;
   60.48 +import java.util.Arrays;
   60.49 +import java.util.Collection;
   60.50 +import java.util.List;
   60.51 +import java.util.Set;
   60.52 +import org.netbeans.junit.NbTestCase;
   60.53 +import org.openide.util.Lookup;
   60.54 +
   60.55 +/**
   60.56 + * Tests for class SimpleLookup.
   60.57 + * @author David Strupl
   60.58 + */
   60.59 +public class SimpleLookupTest extends NbTestCase {
   60.60 +
   60.61 +    public SimpleLookupTest(String testName) {
   60.62 +        super(testName);
   60.63 +    }
   60.64 +
   60.65 +    public void testEmptyLookup() {
   60.66 +        assertSize("Lookup.EMPTY should be small", 8, Lookup.EMPTY);
   60.67 +    }
   60.68 +
   60.69 +    /**
   60.70 +     * Simple tests testing singleton lookup.
   60.71 +     */
   60.72 +    public void testSingleton() {
   60.73 +        //
   60.74 +        Object orig = new Object();
   60.75 +        Lookup p1 = Lookups.singleton(orig);
   60.76 +        Object obj = p1.lookup(Object.class);
   60.77 +        assertTrue(obj == orig);
   60.78 +        assertNull(p1.lookup(String.class)); 
   60.79 +        assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
   60.80 +        //
   60.81 +        Lookup p2 = Lookups.singleton("test");
   60.82 +        assertNotNull(p2.lookup(Object.class));
   60.83 +        assertNotNull(p2.lookup(String.class));
   60.84 +        assertNotNull(p2.lookup(java.io.Serializable.class));
   60.85 +    }
   60.86 +    
   60.87 +    public void testEmptyFixed() {
   60.88 +        Lookup l = Lookups.fixed();
   60.89 +        assertSize("Lookups.fixed() for empty list of items should be small", 8, l);
   60.90 +        assertSame(Lookup.EMPTY, l);
   60.91 +    }
   60.92 +
   60.93 +    public void testSingleItemFixed() {
   60.94 +        Object o = new Object();
   60.95 +        Lookup l = Lookups.fixed(o);
   60.96 +        assertSize("Lookups.fixed(o) for a single item should be small", 24, l);
   60.97 +    }
   60.98 +
   60.99 +    /**
  60.100 +     * Simple tests testing fixed lookup.
  60.101 +     */
  60.102 +    public void testFixed() {
  60.103 +        //
  60.104 +        Object[] orig = new Object[] { new Object(), new Object() };
  60.105 +        Lookup p1 = Lookups.fixed(orig);
  60.106 +        Object obj = p1.lookup(Object.class);
  60.107 +        assertTrue(obj == orig[0] || obj == orig[1]);
  60.108 +        assertNull(p1.lookup(String.class)); 
  60.109 +        //
  60.110 +        String[] s = new String[] { "test1", "test2" };
  60.111 +        Lookup p2 = Lookups.fixed((Object[]) s);
  60.112 +        Object obj2 = p2.lookup(Object.class);
  60.113 +        assertNotNull(obj2);
  60.114 +        if (obj2 != s[0] && obj2 != s[1]) {
  60.115 +            fail("Returned objects are not the originals");
  60.116 +        }
  60.117 +        assertNotNull(p2.lookup(String.class));
  60.118 +        assertNotNull(p2.lookup(java.io.Serializable.class));
  60.119 +        Lookup.Template<String> t = new Lookup.Template<String>(String.class);
  60.120 +        Lookup.Result<String> r = p2.lookup(t);
  60.121 +        Collection<? extends String> all = r.allInstances();
  60.122 +        assertTrue(all.size() == 2);
  60.123 +        for (String o : all) {
  60.124 +            assertTrue("allInstances contains wrong objects", o.equals(s[0]) || o.equals(s[1]));
  60.125 +        }
  60.126 +        
  60.127 +        try {
  60.128 +            Lookups.fixed(new Object[] {null});
  60.129 +            fail("No nulls are allowed");
  60.130 +        } catch (NullPointerException ex) {
  60.131 +            // ok, NPE is what we want
  60.132 +        }        
  60.133 +    }
  60.134 +
  60.135 +    public void testFixedSubtypes() {
  60.136 +        class A {}
  60.137 +        class B extends A {}
  60.138 +        Lookup l = Lookups.fixed(new A(), new B());
  60.139 +        assertEquals(1, l.lookupAll(B.class).size());
  60.140 +        assertEquals(2, l.lookupAll(A.class).size());
  60.141 +    }
  60.142 +
  60.143 +    /**
  60.144 +     * Simple tests testing converting lookup.
  60.145 +     */
  60.146 +    public void testConverting() {
  60.147 +        //
  60.148 +        String[] orig = new String[] { TestConvertor.TEST1, TestConvertor.TEST2 };
  60.149 +        TestConvertor convertor = new TestConvertor();
  60.150 +        Lookup p1 = Lookups.fixed(orig, convertor);
  60.151 +        assertNull("Converting from String to Integer - it should not find String in result", p1.lookup(String.class));
  60.152 +        assertNotNull(p1.lookup(Integer.class));
  60.153 +        assertNotNull(p1.lookup(Integer.class));
  60.154 +        assertTrue("Convertor should be called only once.", convertor.getNumberOfConvertCalls() == 1); 
  60.155 +        Lookup.Template<Integer> t = new Lookup.Template<Integer>(Integer.class);
  60.156 +        Lookup.Result<Integer> r = p1.lookup(t);
  60.157 +        Collection<? extends Integer> all = r.allInstances();
  60.158 +        assertTrue(all.size() == 2);
  60.159 +        for (int i : all) {
  60.160 +            assertTrue("allInstances contains wrong objects", i == TestConvertor.t1 || i == TestConvertor.t2);
  60.161 +        }
  60.162 +    }
  60.163 +    
  60.164 +    private static class TestConvertor implements InstanceContent.Convertor<String,Integer> {
  60.165 +        static final String TEST1 = "test1";
  60.166 +        static final int t1 = 1;
  60.167 +        static final String TEST2 = "test2";
  60.168 +        static final int t2 = 2;
  60.169 +        
  60.170 +        private int numberOfConvertCalls = 0;
  60.171 +        
  60.172 +        public Integer convert(String obj) {
  60.173 +            numberOfConvertCalls++;
  60.174 +            if (obj.equals(TEST1)) {
  60.175 +                return t1;
  60.176 +            }
  60.177 +            if (obj.equals(TEST2)) {
  60.178 +                return t2;
  60.179 +            }
  60.180 +            throw new IllegalArgumentException();
  60.181 +        }
  60.182 +        
  60.183 +        public String displayName(String obj) {
  60.184 +            return obj;
  60.185 +        }
  60.186 +        
  60.187 +        public String id(String obj) {
  60.188 +            if (obj.equals(TEST1)) {
  60.189 +                return TEST1;
  60.190 +            }
  60.191 +            if (obj.equals(TEST2)) {
  60.192 +                return TEST2;
  60.193 +            }
  60.194 +            return null;
  60.195 +        }
  60.196 +        
  60.197 +        public Class<? extends Integer> type(String obj) {
  60.198 +            return Integer.class;
  60.199 +        }
  60.200 +        
  60.201 +        int getNumberOfConvertCalls() { 
  60.202 +            return numberOfConvertCalls;
  60.203 +        }
  60.204 +    }
  60.205 +    
  60.206 +    public void testLookupItem() {
  60.207 +        SomeInst inst = new SomeInst();
  60.208 +        Lookup.Item item = Lookups.lookupItem(inst, "XYZ");
  60.209 +        
  60.210 +        assertTrue("Wrong instance", item.getInstance() == inst);
  60.211 +        assertTrue("Wrong instance class", item.getType() == inst.getClass());
  60.212 +        assertEquals("Wrong id", "XYZ", item.getId());
  60.213 +
  60.214 +        item = Lookups.lookupItem(inst, null);
  60.215 +        assertNotNull("Id must never be null", item.getId());
  60.216 +    }
  60.217 +
  60.218 +    public void testLookupItemEquals() {
  60.219 +        SomeInst instA = new SomeInst();
  60.220 +        SomeInst instB = new SomeInst();
  60.221 +        Lookup.Item itemA = Lookups.lookupItem(instA, null);
  60.222 +        Lookup.Item itemB = Lookups.lookupItem(instB, null);
  60.223 +        
  60.224 +        assertTrue("Lookup items shouldn't be equal", !itemA.equals(itemB) && !itemB.equals(itemA));
  60.225 +
  60.226 +        itemA = Lookups.lookupItem(instA, null);
  60.227 +        itemB = Lookups.lookupItem(instA, null); // same instance
  60.228 +
  60.229 +        assertTrue("Lookup items should be equal", itemA.equals(itemB) && itemB.equals(itemA));
  60.230 +        assertTrue("Lookup items hashcode should be same", itemA.hashCode() == itemB.hashCode());
  60.231 +
  60.232 +        itemA = Lookups.lookupItem(new String("VOKURKA"), null);
  60.233 +        itemB = Lookups.lookupItem(new String("VOKURKA"), null);
  60.234 +
  60.235 +        assertTrue("Lookup items shouldn't be equal (2)", !itemA.equals(itemB) && !itemB.equals(itemA));
  60.236 +    }
  60.237 +    
  60.238 +    public void testAllClassesIssue42399 () throws Exception {
  60.239 +        Object[] arr = { "Ahoj", new Object () };
  60.240 +        
  60.241 +        Lookup l = Lookups.fixed (arr);
  60.242 +        
  60.243 +        Set<Class<? extends Object>> s = l.lookup(new Lookup.Template<Object>(Object.class)).allClasses();
  60.244 +        
  60.245 +        assertEquals ("Two there", 2, s.size ());
  60.246 +        assertTrue ("Contains Object.class", s.contains (Object.class));
  60.247 +        assertTrue ("Contains string", s.contains (String.class));
  60.248 +        
  60.249 +    }
  60.250 +
  60.251 +    public void testLookupItemEarlyInitializationProblem() {
  60.252 +        InstanceContent ic = new InstanceContent();
  60.253 +        AbstractLookup al = new AbstractLookup(ic);
  60.254 +        LI item = new LI();
  60.255 +        List<AbstractLookup.Pair> pairs1 = new ArrayList<AbstractLookup.Pair>();
  60.256 +        List<AbstractLookup.Pair> pairs2 = new ArrayList<AbstractLookup.Pair>();
  60.257 +        
  60.258 +        assertEquals("Item's instance shouldn't be requested", 0, item.cnt);
  60.259 +
  60.260 +        pairs1.add(new ItemPair<Object>(Lookups.<Object>lookupItem(new SomeInst(), null)));
  60.261 +        pairs1.add(new ItemPair<Object>(item));
  60.262 +        pairs1.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
  60.263 +
  60.264 +        pairs2.add(new ItemPair<Object>(item));
  60.265 +        pairs2.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
  60.266 +
  60.267 +        ic.setPairs(pairs1);
  60.268 +        ic.setPairs(pairs2);
  60.269 +
  60.270 +        assertEquals("Item's instance shouldn't be requested when added to lookup", 0, item.cnt);
  60.271 +        
  60.272 +        LI item2 = al.lookup(LI.class);
  60.273 +        assertEquals("Item's instance should be requested", 1, item.cnt);
  60.274 +    }
  60.275 +
  60.276 +    public void testConvenienceMethods() throws Exception {
  60.277 +        // Just check signatures and basic behavior of #73848.
  60.278 +        Lookup l = Lookups.fixed(new Object[] {1, "hello", 2, "goodbye"});
  60.279 +        Collection<? extends Integer> ints = l.lookupAll(Integer.class);
  60.280 +        assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
  60.281 +        Lookup.Result<Integer> r = l.lookupResult(Integer.class);
  60.282 +        ints = r.allInstances();
  60.283 +        assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
  60.284 +    }
  60.285 +    
  60.286 +    private static class SomeInst { }
  60.287 +    
  60.288 +    private static class LI extends Lookup.Item<Object> {
  60.289 +
  60.290 +        public long cnt = 0;
  60.291 +        
  60.292 +        public String getDisplayName() {
  60.293 +            return getId();
  60.294 +        }
  60.295 +
  60.296 +        public String getId() {
  60.297 +            return getClass() + "@" + hashCode();
  60.298 +        }
  60.299 +
  60.300 +        public Object getInstance() {
  60.301 +            cnt++;
  60.302 +            return this;
  60.303 +        }
  60.304 +
  60.305 +        public Class<? extends Object> getType() {
  60.306 +            return getClass();
  60.307 +        }
  60.308 +    } // End of LI class
  60.309 +
  60.310 +    private static class ItemPair<T> extends AbstractLookup.Pair<T> {
  60.311 +        
  60.312 +        private AbstractLookup.Item<T> item;
  60.313 +        
  60.314 +        public ItemPair(Lookup.Item<T> i) {
  60.315 +            this.item = i;
  60.316 +        }
  60.317 +
  60.318 +        protected boolean creatorOf(Object obj) {
  60.319 +            return item.getInstance() == obj;
  60.320 +        }
  60.321 +
  60.322 +        public String getDisplayName() {
  60.323 +            return item.getDisplayName ();
  60.324 +        }
  60.325 +
  60.326 +        public String getId() {
  60.327 +            return item.getId ();
  60.328 +        }
  60.329 +
  60.330 +        public T getInstance() {
  60.331 +            return item.getInstance ();
  60.332 +        }
  60.333 +
  60.334 +        public Class<? extends T> getType() {
  60.335 +            return item.getType ();
  60.336 +        }
  60.337 +
  60.338 +        protected boolean instanceOf(Class<?> c) {
  60.339 +            return c.isAssignableFrom(getType());
  60.340 +        }
  60.341 +
  60.342 +        public @Override boolean equals(Object o) {
  60.343 +            if (o instanceof ItemPair) {
  60.344 +                ItemPair p = (ItemPair)o;
  60.345 +                return item.equals (p.item);
  60.346 +            }
  60.347 +            return false;
  60.348 +        }
  60.349 +
  60.350 +        public @Override int hashCode() {
  60.351 +            return item.hashCode ();
  60.352 +        }
  60.353 +    } // end of ItemPair
  60.354 +}
    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/SimpleProxyLookupIssue42244Test.java	Sat Oct 31 15:28:13 2009 +0100
    61.3 @@ -0,0 +1,120 @@
    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 +import java.lang.ref.WeakReference;
   61.48 +import java.util.*;
   61.49 +import junit.framework.*;
   61.50 +import org.netbeans.junit.*;
   61.51 +import org.openide.util.Lookup;
   61.52 +
   61.53 +/** To simulate issue 42244.
   61.54 + */
   61.55 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   61.56 +public class SimpleProxyLookupIssue42244Test extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
   61.57 +    public SimpleProxyLookupIssue42244Test (java.lang.String testName) {
   61.58 +        super(testName, null);
   61.59 +    }
   61.60 +
   61.61 +    public static Test suite() {
   61.62 +        // return new SimpleProxyLookupIssue42244Test("testGarbageCollect");
   61.63 +        return new NbTestSuite(SimpleProxyLookupIssue42244Test.class);
   61.64 +    }
   61.65 +    
   61.66 +    /** Creates an lookup for given lookup. This class just returns 
   61.67 +     * the object passed in, but subclasses can be different.
   61.68 +     * @param lookup in lookup
   61.69 +     * @return a lookup to use
   61.70 +     */
   61.71 +    public Lookup createLookup (final Lookup lookup) {
   61.72 +        class C implements Lookup.Provider {
   61.73 +            public Lookup getLookup () {
   61.74 +                return lookup;
   61.75 +            }
   61.76 +        }
   61.77 +        return Lookups.proxy (new C ());
   61.78 +    }
   61.79 +    
   61.80 +    public Lookup createInstancesLookup (InstanceContent ic) {
   61.81 +        return new KeepResultsProxyLookup (new AbstractLookup (ic));
   61.82 +    }
   61.83 +    
   61.84 +    public void clearCaches () {
   61.85 +        KeepResultsProxyLookup k = (KeepResultsProxyLookup)this.instanceLookup;
   61.86 +        
   61.87 +        ArrayList toGC = new ArrayList ();
   61.88 +        Iterator it = k.allQueries.iterator ();
   61.89 +        while (it.hasNext ()) {
   61.90 +            Lookup.Result r = (Lookup.Result)it.next ();
   61.91 +            toGC.add (new WeakReference (r));
   61.92 +        }
   61.93 +        
   61.94 +        k.allQueries = null;
   61.95 +        
   61.96 +        it = toGC.iterator ();
   61.97 +        while (it.hasNext ()) {
   61.98 +            WeakReference r = (WeakReference)it.next ();
   61.99 +            assertGC ("Trying to release all results from memory", r);
  61.100 +        }
  61.101 +    }
  61.102 +    
  61.103 +    class KeepResultsProxyLookup extends ProxyLookup {
  61.104 +        private ArrayList allQueries = new ArrayList ();
  61.105 +        private ThreadLocal in = new ThreadLocal ();
  61.106 +        
  61.107 +        public KeepResultsProxyLookup (Lookup delegate) {
  61.108 +            super (new Lookup[] { delegate });
  61.109 +        }
  61.110 +        
  61.111 +        @Override
  61.112 +        protected void beforeLookup (org.openide.util.Lookup.Template template) {
  61.113 +            super.beforeLookup (template);
  61.114 +            if (allQueries != null && in.get () == null) {
  61.115 +                in.set (this);
  61.116 +                Lookup.Result res = lookup (template);
  61.117 +                allQueries.add (res);
  61.118 +                in.set (null);
  61.119 +            }
  61.120 +        }
  61.121 +        
  61.122 +    }
  61.123 +}
    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/SimpleProxyLookupSpeedIssue42244Test.java	Sat Oct 31 15:28:13 2009 +0100
    62.3 @@ -0,0 +1,118 @@
    62.4 +/*
    62.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    62.6 + *
    62.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    62.8 + *
    62.9 + * The contents of this file are subject to the terms of either the GNU
   62.10 + * General Public License Version 2 only ("GPL") or the Common
   62.11 + * Development and Distribution License("CDDL") (collectively, the
   62.12 + * "License"). You may not use this file except in compliance with the
   62.13 + * License. You can obtain a copy of the License at
   62.14 + * http://www.netbeans.org/cddl-gplv2.html
   62.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   62.16 + * specific language governing permissions and limitations under the
   62.17 + * License.  When distributing the software, include this License Header
   62.18 + * Notice in each file and include the License file at
   62.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   62.20 + * particular file as subject to the "Classpath" exception as provided
   62.21 + * by Sun in the GPL Version 2 section of the License file that
   62.22 + * accompanied this code. If applicable, add the following below the
   62.23 + * License Header, with the fields enclosed by brackets [] replaced by
   62.24 + * your own identifying information:
   62.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   62.26 + *
   62.27 + * Contributor(s):
   62.28 + *
   62.29 + * The Original Software is NetBeans. The Initial Developer of the Original
   62.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   62.31 + * Microsystems, Inc. All Rights Reserved.
   62.32 + *
   62.33 + * If you wish your version of this file to be governed by only the CDDL
   62.34 + * or only the GPL Version 2, indicate your decision by adding
   62.35 + * "[Contributor] elects to include this software in this distribution
   62.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   62.37 + * single choice of license, a recipient has the option to distribute
   62.38 + * your version of this file under either the CDDL, the GPL Version 2 or
   62.39 + * to extend the choice of license to its licensees as provided above.
   62.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   62.41 + * Version 2 license, then the option applies only if the new code is
   62.42 + * made subject to such option by the copyright holder.
   62.43 + */
   62.44 +
   62.45 +package org.openide.util.lookup;
   62.46 +
   62.47 +import java.util.HashSet;
   62.48 +import java.util.Set;
   62.49 +import org.netbeans.junit.NbTestCase;
   62.50 +
   62.51 +import org.netbeans.junit.RandomlyFails;
   62.52 +import org.openide.util.Lookup;
   62.53 +
   62.54 +/**
   62.55 + * @author  Petr Nejedly, adapted to test by Jaroslav Tulach
   62.56 + */
   62.57 +@RandomlyFails // NB-Core-Build #1847
   62.58 +public class SimpleProxyLookupSpeedIssue42244Test extends NbTestCase {
   62.59 +
   62.60 +    public SimpleProxyLookupSpeedIssue42244Test (String name) {
   62.61 +        super (name);
   62.62 +    }
   62.63 +
   62.64 +    public void testCompareTheSpeed () {
   62.65 +        String content1 = "String1";
   62.66 +        String content2 = "String2";
   62.67 +        
   62.68 +        Lookup fixed1 = Lookups.singleton(content1);
   62.69 +        Lookup fixed2 = Lookups.singleton(content2);
   62.70 +        
   62.71 +        MyProvider provider = new MyProvider();
   62.72 +        provider.setLookup(fixed1);
   62.73 +        
   62.74 +        Lookup top = Lookups.proxy(provider);
   62.75 +
   62.76 +        Lookup.Result<String> r0 = top.lookupResult(String.class);
   62.77 +        r0.allInstances();
   62.78 +
   62.79 +        long time = System.currentTimeMillis();
   62.80 +        top.lookupAll(String.class);
   62.81 +        long withOneResult = System.currentTimeMillis() - time;
   62.82 +
   62.83 +     
   62.84 +        Set<Object> results = new HashSet<Object>();
   62.85 +        for (int i=0; i<10000; i++) {
   62.86 +            Lookup.Result<String> res = top.lookupResult(String.class);
   62.87 +            results.add (res);
   62.88 +            res.allInstances();
   62.89 +        }
   62.90 +        
   62.91 +        provider.setLookup(fixed2);
   62.92 +
   62.93 +        time = System.currentTimeMillis();
   62.94 +        top.lookupAll(String.class);
   62.95 +        long withManyResults = System.currentTimeMillis() - time;
   62.96 +        
   62.97 +        // if the measurement takes less then 10ms, pretend 10ms
   62.98 +        if (withManyResults < 10) {
   62.99 +            withManyResults = 10;
  62.100 +        }
  62.101 +        if (withOneResult < 10) {
  62.102 +            withOneResult = 10;
  62.103 +        }
  62.104 +
  62.105 +        if (withManyResults >= 10 * withOneResult) {
  62.106 +            fail ("With many results the test runs too long.\n With many: " + withManyResults + "\n With one : " + withOneResult);
  62.107 +        }
  62.108 +    }
  62.109 +    
  62.110 +    private static class MyProvider implements Lookup.Provider {
  62.111 +        private Lookup lookup;
  62.112 +        public Lookup getLookup() {
  62.113 +            return lookup;
  62.114 +        }
  62.115 +        
  62.116 +        void setLookup(Lookup lookup) {
  62.117 +            this.lookup = lookup;
  62.118 +        }
  62.119 +    }
  62.120 +    
  62.121 +}
    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/SimpleProxyLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    63.3 @@ -0,0 +1,73 @@
    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 java.lang.ref.WeakReference;
   63.48 +import org.netbeans.junit.NbTestCase;
   63.49 +import org.openide.util.Lookup;
   63.50 +import org.openide.util.Lookup.Provider;
   63.51 +
   63.52 +/**
   63.53 + *
   63.54 + * @author Jan Lahoda
   63.55 + */
   63.56 +@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
   63.57 +public class SimpleProxyLookupTest extends NbTestCase {
   63.58 +
   63.59 +    public SimpleProxyLookupTest(String testName) {
   63.60 +        super(testName);
   63.61 +    }
   63.62 +
   63.63 +    public void test69810() throws Exception {
   63.64 +        Lookup.Template t = new Lookup.Template(String.class);
   63.65 +        SimpleProxyLookup spl = new SimpleProxyLookup(new Provider() {
   63.66 +            public Lookup getLookup() {
   63.67 +                return Lookups.fixed(new Object[] {"test1", "test2"});
   63.68 +            }
   63.69 +        });
   63.70 +        
   63.71 +        assertGC("", new WeakReference(spl.lookup(t)));
   63.72 +        
   63.73 +        spl.lookup(new Lookup.Template(Object.class)).allInstances();
   63.74 +    }
   63.75 +    
   63.76 +}
    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/SingletonLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    64.3 @@ -0,0 +1,113 @@
    64.4 +/*
    64.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    64.6 + * 
    64.7 + * Copyright 2008 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 + * If you wish your version of this file to be governed by only the CDDL
   64.28 + * or only the GPL Version 2, indicate your decision by adding
   64.29 + * "[Contributor] elects to include this software in this distribution
   64.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   64.31 + * single choice of license, a recipient has the option to distribute
   64.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   64.33 + * to extend the choice of license to its licensees as provided above.
   64.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   64.35 + * Version 2 license, then the option applies only if the new code is
   64.36 + * made subject to such option by the copyright holder.
   64.37 + * 
   64.38 + * Contributor(s):
   64.39 + * 
   64.40 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
   64.41 + */
   64.42 +
   64.43 +package org.openide.util.lookup;
   64.44 +
   64.45 +import java.util.Collection;
   64.46 +import org.netbeans.junit.NbTestCase;
   64.47 +import org.openide.util.Lookup;
   64.48 +
   64.49 +/**
   64.50 + * Contains tests of class {@code SingletonLookup}.
   64.51 + *
   64.52 + * @author  Marian Petras
   64.53 + */
   64.54 +public class SingletonLookupTest extends NbTestCase {
   64.55 +    
   64.56 +    public SingletonLookupTest(String testName) {
   64.57 +        super(testName);
   64.58 +    }
   64.59 +
   64.60 +    public void testBasics() {
   64.61 +        Object orig = new Object();
   64.62 +        Lookup p1 = new SingletonLookup(orig);
   64.63 +        Object obj = p1.lookup(Object.class);
   64.64 +        assertTrue(obj == orig);
   64.65 +        assertNull(p1.lookup(String.class)); 
   64.66 +        assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
   64.67 +        //
   64.68 +        Lookup p2 = new SingletonLookup("test");
   64.69 +        assertNotNull(p2.lookup(Object.class));
   64.70 +        assertNotNull(p2.lookup(String.class));
   64.71 +        assertNotNull(p2.lookup(java.io.Serializable.class));
   64.72 +    }
   64.73 +
   64.74 +    public void testId() {
   64.75 +        Object orig = new Object();
   64.76 +        Collection allInstances;
   64.77 +
   64.78 +        Lookup l = new SingletonLookup(orig, "id");
   64.79 +
   64.80 +        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, null, null)).allInstances();
   64.81 +        assertNotNull(allInstances);
   64.82 +        assertFalse(allInstances.isEmpty());
   64.83 +        assertEquals(1, allInstances.size());
   64.84 +        assertTrue(allInstances.iterator().next() == orig);
   64.85 +
   64.86 +        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "id", null)).allInstances();
   64.87 +        assertNotNull(allInstances);
   64.88 +        assertFalse(allInstances.isEmpty());
   64.89 +        assertEquals(1, allInstances.size());
   64.90 +        assertTrue(allInstances.iterator().next() == orig);
   64.91 +
   64.92 +        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "not", null)).allInstances();
   64.93 +        assertNotNull(allInstances);
   64.94 +        assertTrue(allInstances.isEmpty());
   64.95 +
   64.96 +        allInstances = l.lookup(new Lookup.Template<String>(String.class, null, null)).allInstances();
   64.97 +        assertNotNull(allInstances);
   64.98 +        assertTrue(allInstances.isEmpty());
   64.99 +
  64.100 +        allInstances = l.lookup(new Lookup.Template<String>(String.class, "id", null)).allInstances();
  64.101 +        assertNotNull(allInstances);
  64.102 +        assertTrue(allInstances.isEmpty());
  64.103 +
  64.104 +        allInstances = l.lookup(new Lookup.Template<String>(String.class, "not", null)).allInstances();
  64.105 +        assertNotNull(allInstances);
  64.106 +        assertTrue(allInstances.isEmpty());
  64.107 +    }
  64.108 +
  64.109 +    public void testSize() {
  64.110 +        final Object obj = new Object();
  64.111 +        assertSize("The singleton lookup instance should be small",
  64.112 +                   24,
  64.113 +                   new SingletonLookup(obj));
  64.114 +    }
  64.115 +
  64.116 +}
    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/problem100320.txt	Sat Oct 31 15:28:13 2009 +0100
    65.3 @@ -0,0 +1,17 @@
    65.4 +:java.io.IOException:
    65.5 +java.nio.charset.CharacterCodingException
    65.6 +java.io.EOFException
    65.7 +java.io.FileNotFoundException
    65.8 +java.io.InterruptedIOException
    65.9 +java.net.MalformedURLException
   65.10 +java.io.IOException
   65.11 +java.io.UnsupportedEncodingException
   65.12 +java.io.NotActiveException
   65.13 +java.io.StreamCorruptedException
   65.14 +java.io.UTFDataFormatException
   65.15 +java.util.zip.ZipException
   65.16 +java.util.jar.JarException
   65.17 +:java.util.Comparator:
   65.18 +org.bar.Comparator3
   65.19 +org.bar.Comparator2
   65.20 +#position=5
    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/services-jar-1.txt	Sat Oct 31 15:28:13 2009 +0100
    66.3 @@ -0,0 +1,17 @@
    66.4 +:somedummyfile:
    66.5 +org.foo.Interface
    66.6 +:java.lang.Runnable:
    66.7 +org.foo.impl.Runnable1
    66.8 +:java.util.Comparator:
    66.9 +#some comment
   66.10 +org.foo.impl.Comparator1
   66.11 +#position=10
   66.12 +#som comment2
   66.13 +:java.util.Iterator:
   66.14 +org.foo.impl.Iterator1
   66.15 +:org.foo.Interface:
   66.16 +# Some header info, maybe.
   66.17 +
   66.18 +# Our first impl here
   66.19 +org.foo.impl.Implementation1
   66.20 +
    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/services-jar-2.txt	Sat Oct 31 15:28:13 2009 +0100
    67.3 @@ -0,0 +1,10 @@
    67.4 +:java.lang.Runnable:
    67.5 +#-org.foo.impl.Runnable1
    67.6 +:java.util.Comparator:
    67.7 +org.bar.Comparator2
    67.8 +#position=5
    67.9 +:java.util.Iterator:
   67.10 +org.bar.Iterator2
   67.11 +#position=100
   67.12 +:org.foo.Interface:
   67.13 +org.bar.Implementation2
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/test/MockLookup.java	Sat Oct 31 15:28:13 2009 +0100
    68.3 @@ -0,0 +1,135 @@
    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-2007 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.test;
   68.46 +
   68.47 +import java.lang.reflect.Field;
   68.48 +import java.util.Collection;
   68.49 +import static junit.framework.Assert.*;
   68.50 +import org.openide.util.Lookup;
   68.51 +import org.openide.util.lookup.Lookups;
   68.52 +import org.openide.util.lookup.ProxyLookup;
   68.53 +
   68.54 +/**
   68.55 + * Mock implementation of system default lookup suitable for use in unit tests.
   68.56 + * The initial value just contains classpath services.
   68.57 + */
   68.58 +public class MockLookup extends ProxyLookup {
   68.59 +
   68.60 +    private static MockLookup DEFAULT;
   68.61 +    private static boolean making = false;
   68.62 +    private static volatile boolean ready;
   68.63 +
   68.64 +    static {
   68.65 +        making = true;
   68.66 +        try {
   68.67 +            System.setProperty("org.openide.util.Lookup", MockLookup.class.getName());
   68.68 +            if (Lookup.getDefault().getClass() != MockLookup.class) {
   68.69 +                // Someone else initialized lookup first. Try to force our way.
   68.70 +                Field defaultLookup = Lookup.class.getDeclaredField("defaultLookup");
   68.71 +                defaultLookup.setAccessible(true);
   68.72 +                defaultLookup.set(null, null);
   68.73 +            }
   68.74 +            assertEquals(MockLookup.class, Lookup.getDefault().getClass());
   68.75 +        } catch (Exception x) {
   68.76 +            throw new ExceptionInInitializerError(x);
   68.77 +        } finally {
   68.78 +            making = false;
   68.79 +        }
   68.80 +    }
   68.81 +
   68.82 +    /** Do not call this directly! */
   68.83 +    public MockLookup() {
   68.84 +        assertTrue(making);
   68.85 +        assertNull(DEFAULT);
   68.86 +        DEFAULT = this;
   68.87 +    }
   68.88 +
   68.89 +    /**
   68.90 +     * Just ensures that this lookup is default lookup, but does not actually change its content.
   68.91 +     * Useful mainly if you have some test utility method which calls foreign code which might use default lookup,
   68.92 +     * and you want to ensure that any users of mock lookup will see the correct default lookup right away,
   68.93 +     * even if they have not yet called {@link #setLookup} or {@link #setInstances}.
   68.94 +     */
   68.95 +    public static void init() {
   68.96 +        if (!ready) {
   68.97 +            setInstances();
   68.98 +        }
   68.99 +    }
  68.100 +
  68.101 +    /**
  68.102 +     * Sets the global default lookup with zero or more delegate lookups.
  68.103 +     * Caution: if you don't include Lookups.metaInfServices, you may have trouble,
  68.104 +     * e.g. {@link #makeScratchDir} will not work.
  68.105 +     * Most of the time you should use {@link #setInstances} instead.
  68.106 +     */
  68.107 +    public static void setLookup(Lookup... lookups) {
  68.108 +        ready = true;
  68.109 +        DEFAULT.setLookups(lookups);
  68.110 +    }
  68.111 +
  68.112 +    /**
  68.113 +     * Sets the global default lookup with some fixed instances.
  68.114 +     * Will also include (at a lower priority) a {@link ClassLoader},
  68.115 +     * and services found from <code>META-INF/services/*</code> in the classpath.
  68.116 +     */
  68.117 +    public static void setInstances(Object... instances) {
  68.118 +        ClassLoader l = MockLookup.class.getClassLoader();
  68.119 +        setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
  68.120 +    }
  68.121 +    /**
  68.122 +     * Sets the global default lookup with some fixed instances and
  68.123 +     * content read from Services folder from system file system.
  68.124 +     * Will also include (at a lower priority) a {@link ClassLoader},
  68.125 +     * and services found from <code>META-INF/services/*</code> in the classpath.
  68.126 +     */
  68.127 +    public static void setLayersAndInstances(Object... instances) {
  68.128 +        ClassLoader l = MockLookup.class.getClassLoader();
  68.129 +        if (l != Lookup.getDefault().lookup(ClassLoader.class)) {
  68.130 +            setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
  68.131 +        }
  68.132 +        Lookup projects = Lookups.forPath("Services");
  68.133 +        Collection<?> initialize = projects.lookupAll(Object.class);
  68.134 +        //System.err.println("all: " + initialize);
  68.135 +        setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l), projects);
  68.136 +    }
  68.137 +
  68.138 +}
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/openide.util.lookup/test/unit/src/org/openide/util/test/MockLookupTest.java	Sat Oct 31 15:28:13 2009 +0100
    69.3 @@ -0,0 +1,66 @@
    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-2007 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.test;
   69.46 +
   69.47 +import junit.framework.TestCase;
   69.48 +import org.openide.util.Lookup;
   69.49 +
   69.50 +public class MockLookupTest extends TestCase {
   69.51 +
   69.52 +    // XXX test:
   69.53 +    // setLookup with one or more lookup args does not use M-I/s
   69.54 +    // still works if another Lookup.getDefault was set before
   69.55 +
   69.56 +    public MockLookupTest(String n) {
   69.57 +        super(n);
   69.58 +    }
   69.59 +
   69.60 +    public void testSetLookup() throws Exception {
   69.61 +        MockLookup.setInstances("hello");
   69.62 +        assertEquals("initial lookup works", "hello", Lookup.getDefault().lookup(String.class));
   69.63 +        MockLookup.setInstances("goodbye");
   69.64 +        assertEquals("modified lookup works", "goodbye", Lookup.getDefault().lookup(String.class));
   69.65 +        MockLookup.setInstances();
   69.66 +        assertEquals("cleared lookup works", null, Lookup.getDefault().lookup(String.class));
   69.67 +    }
   69.68 +
   69.69 +}
    70.1 --- a/openide.util/src/org/netbeans/modules/openide/util/ActiveQueue.java	Sat Oct 31 15:06:58 2009 +0100
    70.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.3 @@ -1,108 +0,0 @@
    70.4 -package org.netbeans.modules.openide.util;
    70.5 -
    70.6 -import java.lang.ref.Reference;
    70.7 -import java.lang.ref.ReferenceQueue;
    70.8 -import java.util.logging.Level;
    70.9 -import java.util.logging.Logger;
   70.10 -
   70.11 -/**
   70.12 - * Implementation of the active reference queue.
   70.13 - */
   70.14 -public final class ActiveQueue extends ReferenceQueue<Object> implements Runnable {
   70.15 -
   70.16 -    private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
   70.17 -    private static ActiveQueue activeReferenceQueue;
   70.18 -    
   70.19 -    /** number of known outstanding references */
   70.20 -    private int count;
   70.21 -    private boolean deprecated;
   70.22 -
   70.23 -    ActiveQueue(boolean deprecated) {
   70.24 -        super();
   70.25 -        this.deprecated = deprecated;
   70.26 -    }
   70.27 -
   70.28 -    public static synchronized ReferenceQueue<Object> queue() {
   70.29 -        if (activeReferenceQueue == null) {
   70.30 -            activeReferenceQueue = new ActiveQueue(false);
   70.31 -        }
   70.32 -
   70.33 -        activeReferenceQueue.ping();
   70.34 -
   70.35 -        return activeReferenceQueue;
   70.36 -    }
   70.37 -
   70.38 -    @Override
   70.39 -    public Reference<Object> poll() {
   70.40 -        throw new UnsupportedOperationException();
   70.41 -    }
   70.42 -
   70.43 -    @Override
   70.44 -    public Reference<Object> remove(long timeout) throws IllegalArgumentException, InterruptedException {
   70.45 -        throw new InterruptedException();
   70.46 -    }
   70.47 -
   70.48 -    @Override
   70.49 -    public Reference<Object> remove() throws InterruptedException {
   70.50 -        throw new InterruptedException();
   70.51 -    }
   70.52 -
   70.53 -    public void run() {
   70.54 -        while (true) {
   70.55 -            try {
   70.56 -                Reference<?> ref = super.remove(0);
   70.57 -                LOGGER.finer("dequeued reference");
   70.58 -                if (!(ref instanceof Runnable)) {
   70.59 -                    LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass());
   70.60 -                    continue;
   70.61 -                }
   70.62 -                if (deprecated) {
   70.63 -                    LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue");
   70.64 -                }
   70.65 -                // do the cleanup
   70.66 -                try {
   70.67 -                    ((Runnable) ref).run();
   70.68 -                } catch (ThreadDeath td) {
   70.69 -                    throw td;
   70.70 -                } catch (Throwable t) {
   70.71 -                    // Should not happen.
   70.72 -                    // If it happens, it is a bug in client code, notify!
   70.73 -                    LOGGER.log(Level.WARNING, null, t);
   70.74 -                } finally {
   70.75 -                    // to allow GC
   70.76 -                    ref = null;
   70.77 -                }
   70.78 -            } catch (InterruptedException ex) {
   70.79 -                // Can happen during VM shutdown, it seems. Ignore.
   70.80 -                continue;
   70.81 -            }
   70.82 -            synchronized (this) {
   70.83 -                assert count > 0;
   70.84 -                count--;
   70.85 -                if (count == 0) {
   70.86 -                    // We have processed all we have to process (for now at least).
   70.87 -                    // Could be restarted later if ping() called again.
   70.88 -                    // This could also happen in case someone called queue() once and tried
   70.89 -                    // to use it for several references; in that case run() might never be called on
   70.90 -                    // the later ones to be collected. Can't really protect against that situation.
   70.91 -                    // See issue #86625 for details.
   70.92 -                    LOGGER.fine("stopping thread");
   70.93 -                    break;
   70.94 -                }
   70.95 -            }
   70.96 -        }
   70.97 -    }
   70.98 -
   70.99 -    synchronized void ping() {
  70.100 -        if (count == 0) {
  70.101 -            Thread t = new Thread(this, "Active Reference Queue Daemon");
  70.102 -            t.setPriority(Thread.MIN_PRIORITY);
  70.103 -            t.setDaemon(true);
  70.104 -            t.start();
  70.105 -            LOGGER.fine("starting thread");
  70.106 -        } else {
  70.107 -            LOGGER.finer("enqueuing reference");
  70.108 -        }
  70.109 -        count++;
  70.110 -    }
  70.111 -}
    71.1 --- a/openide.util/src/org/netbeans/modules/openide/util/NamedServicesProvider.java	Sat Oct 31 15:06:58 2009 +0100
    71.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.3 @@ -1,81 +0,0 @@
    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.
   71.31 - *
   71.32 - * Portions Copyrighted 2006 Sun Microsystems, Inc.
   71.33 - */
   71.34 -
   71.35 -package org.netbeans.modules.openide.util;
   71.36 -
   71.37 -import java.lang.ref.Reference;
   71.38 -import java.lang.ref.WeakReference;
   71.39 -import java.util.Collections;
   71.40 -import java.util.HashMap;
   71.41 -import java.util.Map;
   71.42 -import org.openide.util.Lookup;
   71.43 -import org.openide.util.lookup.Lookups;
   71.44 -
   71.45 -/** Interface for core/startup and core/settings
   71.46 - * to provide lookup over system filesystem.
   71.47 - *
   71.48 - * @author Jaroslav Tulach
   71.49 - */
   71.50 -public abstract class NamedServicesProvider {
   71.51 -
   71.52 -    private static final Map<String,Reference<Lookup>> map = Collections.synchronizedMap(new HashMap<String,Reference<Lookup>>());
   71.53 -    
   71.54 -    public abstract Lookup create(String path);
   71.55 -    
   71.56 -    public static Lookup find(String path) {
   71.57 -        if (!path.endsWith("/")) {
   71.58 -            path = path + "/";
   71.59 -        }
   71.60 -        
   71.61 -        Reference<Lookup> ref = map.get(path);
   71.62 -        Lookup lkp = ref == null ? null : ref.get();
   71.63 -        if (lkp != null) {
   71.64 -            return lkp;
   71.65 -        }
   71.66 -        NamedServicesProvider prov = Lookup.getDefault().lookup(NamedServicesProvider.class);
   71.67 -        if (prov != null) {
   71.68 -            lkp = prov.create(path);
   71.69 -        } else {
   71.70 -            ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
   71.71 -            if (l == null) {
   71.72 -                l = Thread.currentThread().getContextClassLoader();
   71.73 -                if (l == null) {
   71.74 -                    l = NamedServicesProvider.class.getClassLoader();
   71.75 -                }
   71.76 -            }
   71.77 -            lkp = Lookups.metaInfServices(l, "META-INF/namedservices/" + path);
   71.78 -        }
   71.79 -        
   71.80 -        map.put(path, new WeakReference<Lookup>(lkp));
   71.81 -        return lkp;
   71.82 -    }
   71.83 -    
   71.84 -}
    72.1 --- a/openide.util/src/org/openide/util/Lookup.java	Sat Oct 31 15:06:58 2009 +0100
    72.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.3 @@ -1,544 +0,0 @@
    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;
   72.46 -
   72.47 -import java.util.ArrayList;
   72.48 -import java.util.Collection;
   72.49 -import java.util.Collections;
   72.50 -import java.util.Iterator;
   72.51 -import java.util.List;
   72.52 -import java.util.Set;
   72.53 -import org.openide.util.lookup.Lookups;
   72.54 -import org.openide.util.lookup.ProxyLookup;
   72.55 -import org.openide.util.lookup.ServiceProvider;
   72.56 -
   72.57 -/**
   72.58 - * A general registry permitting clients to find instances of services
   72.59 - * (implementation of a given interface).
   72.60 - * This class is inspired by the
   72.61 - * <a href="http://www.jini.org/">Jini</a>
   72.62 - * registration and lookup mechanism. The difference is that the methods do
   72.63 - * not throw checked exceptions (as they usually work only locally and not over the network)
   72.64 - * and that the Lookup API concentrates on the lookup, not on the registration
   72.65 - * (although {@link Lookup#getDefault} is strongly encouraged to support
   72.66 - * {@link Lookups#metaInfServices} for registration in addition to whatever
   72.67 - * else it decides to support).
   72.68 - * <p>
   72.69 - * For a general talk about the idea behind the lookup pattern please see
   72.70 - * <UL>
   72.71 - *      <LI><a href="lookup/doc-files/index.html">The Solution to Communication Between Components</a>
   72.72 - *      page
   72.73 - *      <LI>the introduction to the <a href="lookup/doc-files/lookup-api.html">lookup API via
   72.74 - *      use cases</a>
   72.75 - *      <LI>the examples of <a href="lookup/doc-files/lookup-spi.html">how to write your own lookup</a>
   72.76 - * </UL>
   72.77 - *
   72.78 - * @see org.openide.util.lookup.AbstractLookup
   72.79 - * @see Lookups
   72.80 - * @see LookupListener
   72.81 - * @see LookupEvent
   72.82 - * @author  Jaroslav Tulach
   72.83 - */
   72.84 -public abstract class Lookup {
   72.85 -    /** A dummy lookup that never returns any results.
   72.86 -     */
   72.87 -    public static final Lookup EMPTY = new Empty();
   72.88 -
   72.89 -    /** default instance */
   72.90 -    private static Lookup defaultLookup;
   72.91 -
   72.92 -    /** Empty constructor for use by subclasses. */
   72.93 -    public Lookup() {
   72.94 -    }
   72.95 -
   72.96 -    /** Static method to obtain the global lookup in the whole system.
   72.97 -     * The actual returned implementation can be different in different
   72.98 -     * systems, but the default one is based on
   72.99 -     * {@link org.openide.util.lookup.Lookups#metaInfServices}
  72.100 -     * with the context classloader of the first caller. Each system is
  72.101 -     * adviced to honor this and include some form of <code>metaInfServices</code>
  72.102 -     * implementation in the returned lookup as usage of <code>META-INF/services</code>
  72.103 -     * is a JDK standard.
  72.104 -     *
  72.105 -     * @return the global lookup in the system
  72.106 -     * @see ServiceProvider
  72.107 -     */
  72.108 -    public static synchronized Lookup getDefault() {
  72.109 -        if (defaultLookup != null) {
  72.110 -            return defaultLookup;
  72.111 -        }
  72.112 -
  72.113 -        // You can specify a Lookup impl using a system property if you like.
  72.114 -        String className = System.getProperty("org.openide.util.Lookup" // NOI18N
  72.115 -            );
  72.116 -
  72.117 -        if ("-".equals(className)) { // NOI18N
  72.118 -
  72.119 -            // Suppress even MetaInfServicesLookup.
  72.120 -            return EMPTY;
  72.121 -        }
  72.122 -
  72.123 -        ClassLoader l = Thread.currentThread().getContextClassLoader();
  72.124 -
  72.125 -        try {
  72.126 -            if (className != null) {
  72.127 -                defaultLookup = (Lookup) Class.forName(className, true, l).newInstance();
  72.128 -
  72.129 -                return defaultLookup;
  72.130 -            }
  72.131 -        } catch (Exception e) {
  72.132 -            // do not use ErrorManager because we are in the startup code
  72.133 -            // and ErrorManager might not be ready
  72.134 -            e.printStackTrace();
  72.135 -        }
  72.136 -
  72.137 -        // OK, none specified (successfully) in a system property.
  72.138 -        // Try MetaInfServicesLookup as a default, which may also
  72.139 -        // have a org.openide.util.Lookup line specifying the lookup.
  72.140 -        Lookup misl = Lookups.metaInfServices(l);
  72.141 -        defaultLookup = misl.lookup(Lookup.class);
  72.142 -
  72.143 -        if (defaultLookup != null) {
  72.144 -            return defaultLookup;
  72.145 -        }
  72.146 -
  72.147 -        // You may also specify a Lookup.Provider.
  72.148 -        Lookup.Provider prov = misl.lookup(Lookup.Provider.class);
  72.149 -
  72.150 -        if (prov != null) {
  72.151 -            defaultLookup = Lookups.proxy(prov);
  72.152 -
  72.153 -            return defaultLookup;
  72.154 -        }
  72.155 -
  72.156 -        DefLookup def = new DefLookup();
  72.157 -        def.init(l, misl, false);
  72.158 -        defaultLookup = def;
  72.159 -        def.init(l, misl, true);
  72.160 -        return defaultLookup;
  72.161 -    }
  72.162 -    
  72.163 -    private static final class DefLookup extends ProxyLookup {
  72.164 -        public DefLookup() {
  72.165 -            super(new Lookup[0]);
  72.166 -        }
  72.167 -        
  72.168 -        public void init(ClassLoader loader, Lookup metaInfLookup, boolean addPath) {
  72.169 -            // Had no such line, use simple impl.
  72.170 -            // It does however need to have ClassLoader available or many things will break.
  72.171 -            // Use the thread context classloader in effect now.
  72.172 -            Lookup clLookup = Lookups.singleton(loader);
  72.173 -            List<Lookup> arr = new ArrayList<Lookup>();
  72.174 -            arr.add(metaInfLookup);
  72.175 -            arr.add(clLookup);
  72.176 -            String paths = System.getProperty("org.openide.util.Lookup.paths"); // NOI18N
  72.177 -            if (addPath && paths != null) {
  72.178 -                for (String p : paths.split(":")) { // NOI18N
  72.179 -                    arr.add(Lookups.forPath(p));
  72.180 -                }
  72.181 -            }
  72.182 -            setLookups(arr.toArray(new Lookup[0]));
  72.183 -        }
  72.184 -    }
  72.185 -    
  72.186 -    /** Called from MockServices to reset default lookup in case services change
  72.187 -     */
  72.188 -    private static void resetDefaultLookup() {
  72.189 -        if (defaultLookup instanceof DefLookup) {
  72.190 -            DefLookup def = (DefLookup)defaultLookup;
  72.191 -            ClassLoader l = Thread.currentThread().getContextClassLoader();
  72.192 -            def.init(l, Lookups.metaInfServices(l), true);
  72.193 -        }
  72.194 -    }
  72.195 -
  72.196 -    /** Look up an object matching a given interface.
  72.197 -     * This is the simplest method to use.
  72.198 -     * If more than one object matches, the first will be returned.
  72.199 -     * The template class may be a class or interface; the instance is
  72.200 -     * guaranteed to be assignable to it.
  72.201 -     *
  72.202 -     * @param clazz class of the object we are searching for
  72.203 -     * @return an object implementing the given class or <code>null</code> if no such
  72.204 -     *         implementation is found
  72.205 -     */
  72.206 -    public abstract <T> T lookup(Class<T> clazz);
  72.207 -
  72.208 -    /** The general lookup method. Callers can get list of all instances and classes
  72.209 -     * that match the given <code>template</code>, request more info about
  72.210 -     * them in form of {@link Lookup.Item} and attach a listener to
  72.211 -     * this be notified about changes. The general interface does not
  72.212 -     * specify whether subsequent calls with the same template produce new
  72.213 -     * instance of the {@link Lookup.Result} or return shared instance. The
  72.214 -     * prefered behaviour however is to return shared one.
  72.215 -     *
  72.216 -     * @param template a template describing the services to look for
  72.217 -     * @return an object containing the results
  72.218 -     */
  72.219 -    public abstract <T> Result<T> lookup(Template<T> template);
  72.220 -
  72.221 -    /** Look up the first item matching a given template.
  72.222 -     * Includes not only the instance but other associated information.
  72.223 -     * @param template the template to check
  72.224 -     * @return a matching item or <code>null</code>
  72.225 -     *
  72.226 -     * @since 1.8
  72.227 -     */
  72.228 -    public <T> Item<T> lookupItem(Template<T> template) {
  72.229 -        Result<T> res = lookup(template);
  72.230 -        Iterator<? extends Item<T>> it = res.allItems().iterator();
  72.231 -        return it.hasNext() ? it.next() : null;
  72.232 -    }
  72.233 -
  72.234 -    /**
  72.235 -     * Find a result corresponding to a given class.
  72.236 -     * Equivalent to calling {@link #lookup(Lookup.Template)} but slightly more convenient.
  72.237 -     * Subclasses may override this method to produce the same semantics more efficiently.
  72.238 -     * @param clazz the supertype of the result
  72.239 -     * @return a live object representing instances of that type
  72.240 -     * @since org.openide.util 6.10
  72.241 -     */
  72.242 -    public <T> Lookup.Result<T> lookupResult(Class<T> clazz) {
  72.243 -        return lookup(new Lookup.Template<T>(clazz));
  72.244 -    }
  72.245 -
  72.246 -    /**
  72.247 -     * Find all instances corresponding to a given class.
  72.248 -     * Equivalent to calling {@link #lookupResult} and asking for {@link Lookup.Result#allInstances} but slightly more convenient.
  72.249 -     * Subclasses may override this method to produce the same semantics more efficiently.
  72.250 -     * <div class="nonnormative">
  72.251 -     * <p>Example usage:</p>
  72.252 -     * <pre>
  72.253 -     * for (MyService svc : Lookup.getDefault().lookupAll(MyService.class)) {
  72.254 -     *     svc.useMe();
  72.255 -     * }
  72.256 -     * </pre>
  72.257 -     * </div>
  72.258 -     * @param clazz the supertype of the result
  72.259 -     * @return all currently available instances of that type
  72.260 -     * @since org.openide.util 6.10
  72.261 -     */
  72.262 -    public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
  72.263 -        return lookupResult(clazz).allInstances();
  72.264 -    }
  72.265 -
  72.266 -    /**
  72.267 -     * Objects implementing interface Lookup.Provider are capable of
  72.268 -     * and willing to provide a lookup (usually bound to the object).
  72.269 -     * @since 3.6
  72.270 -     */
  72.271 -    public interface Provider {
  72.272 -        /**
  72.273 -         * Returns lookup associated with the object.
  72.274 -         * @return fully initialized lookup instance provided by this object
  72.275 -         */
  72.276 -        Lookup getLookup();
  72.277 -    }
  72.278 -
  72.279 -    /*
  72.280 -     * I expect this class to grow in the future, but for now, it is
  72.281 -     * enough to start with something simple.
  72.282 -     */
  72.283 -
  72.284 -    /** Template defining a pattern to filter instances by.
  72.285 -     */
  72.286 -    public static final class Template<T> extends Object {
  72.287 -        /** cached hash code */
  72.288 -        private int hashCode;
  72.289 -
  72.290 -        /** type of the service */
  72.291 -        private Class<T> type;
  72.292 -
  72.293 -        /** identity to search for */
  72.294 -        private String id;
  72.295 -
  72.296 -        /** instance to search for */
  72.297 -        private T instance;
  72.298 -
  72.299 -        /** General template to find all possible instances.
  72.300 -         * @deprecated Use <code>new Template (Object.class)</code> which
  72.301 -         *   is going to be better typed with JDK1.5 templates and should produce
  72.302 -         *   the same result.
  72.303 -         */
  72.304 -        @Deprecated
  72.305 -        public Template() {
  72.306 -            this(null);
  72.307 -        }
  72.308 -
  72.309 -        /** Create a simple template matching by class.
  72.310 -         * @param type the class of service we are looking for (subclasses will match)
  72.311 -         */
  72.312 -        public Template(Class<T> type) {
  72.313 -            this(type, null, null);
  72.314 -        }
  72.315 -
  72.316 -        /** Constructor to create new template.
  72.317 -         * @param type the class of service we are looking for or <code>null</code> to leave unspecified
  72.318 -         * @param id the ID of the item/service we are looking for or <code>null</code> to leave unspecified
  72.319 -         * @param instance a specific known instance to look for or <code>null</code> to leave unspecified
  72.320 -         */
  72.321 -        public Template(Class<T> type, String id, T instance) {
  72.322 -            this.type = extractType(type);
  72.323 -            this.id = id;
  72.324 -            this.instance = instance;
  72.325 -        }
  72.326 -
  72.327 -        @SuppressWarnings("unchecked")
  72.328 -        private Class<T> extractType(Class<T> type) {
  72.329 -            return (type == null) ? (Class<T>)Object.class : type;
  72.330 -        }
  72.331 -
  72.332 -        /** Get the class (or superclass or interface) to search for.
  72.333 -         * If it was not specified in the constructor, <code>Object</code> is used as
  72.334 -         * this will match any instance.
  72.335 -         * @return the class to search for
  72.336 -         */
  72.337 -        public Class<T> getType() {
  72.338 -            return type;
  72.339 -        }
  72.340 -
  72.341 -        /** Get the persistent identifier being searched for, if any.
  72.342 -         * @return the ID or <code>null</code>
  72.343 -         * @see Lookup.Item#getId
  72.344 -         *
  72.345 -         * @since 1.8
  72.346 -         */
  72.347 -        public String getId() {
  72.348 -            return id;
  72.349 -        }
  72.350 -
  72.351 -        /** Get the specific instance being searched for, if any.
  72.352 -         * Most useful for finding an <code>Item</code> when the instance
  72.353 -         * is already known.
  72.354 -         *
  72.355 -         * @return the object to find or <code>null</code>
  72.356 -         *
  72.357 -         * @since 1.8
  72.358 -         */
  72.359 -        public T getInstance() {
  72.360 -            return instance;
  72.361 -        }
  72.362 -
  72.363 -        /* Computes hashcode for this template. The hashcode is cached.
  72.364 -         * @return hashcode
  72.365 -         */
  72.366 -        @Override
  72.367 -        public int hashCode() {
  72.368 -            if (hashCode != 0) {
  72.369 -                return hashCode;
  72.370 -            }
  72.371 -
  72.372 -            hashCode = ((type == null) ? 1 : type.hashCode()) + ((id == null) ? 2 : id.hashCode()) +
  72.373 -                ((instance == null) ? 3 : 0);
  72.374 -
  72.375 -            return hashCode;
  72.376 -        }
  72.377 -
  72.378 -        /* Checks whether two templates represent the same query.
  72.379 -         * @param obj another template to check
  72.380 -         * @return true if so, false otherwise
  72.381 -         */
  72.382 -        @Override
  72.383 -        public boolean equals(Object obj) {
  72.384 -            if (!(obj instanceof Template)) {
  72.385 -                return false;
  72.386 -            }
  72.387 -
  72.388 -            Template t = (Template) obj;
  72.389 -
  72.390 -            if (hashCode() != t.hashCode()) {
  72.391 -                // this is an optimalization - the hashCodes should have been
  72.392 -                // precomputed
  72.393 -                return false;
  72.394 -            }
  72.395 -
  72.396 -            if (type != t.type) {
  72.397 -                return false;
  72.398 -            }
  72.399 -
  72.400 -            if (id == null) {
  72.401 -                if (t.id != null) {
  72.402 -                    return false;
  72.403 -                }
  72.404 -            } else {
  72.405 -                if (!id.equals(t.id)) {
  72.406 -                    return false;
  72.407 -                }
  72.408 -            }
  72.409 -
  72.410 -            if (instance == null) {
  72.411 -                return (t.instance == null);
  72.412 -            } else {
  72.413 -                return instance.equals(t.instance);
  72.414 -            }
  72.415 -        }
  72.416 -
  72.417 -        /* for debugging */
  72.418 -        @Override
  72.419 -        public String toString() {
  72.420 -            return "Lookup.Template[type=" + type + ",id=" + id + ",instance=" + instance + "]"; // NOI18N
  72.421 -        }
  72.422 -    }
  72.423 -
  72.424 -    /** Result of a lookup request.
  72.425 -     * Allows access to all matching instances at once.
  72.426 -     * Also permits listening to changes in the result.
  72.427 -     * Result can contain duplicate items.
  72.428 -     */
  72.429 -    public static abstract class Result<T> extends Object {
  72.430 -        /** Registers a listener that is invoked when there is a possible
  72.431 -         * change in this result.
  72.432 -         *
  72.433 -         * @param l the listener to add
  72.434 -         */
  72.435 -        public abstract void addLookupListener(LookupListener l);
  72.436 -
  72.437 -        /** Unregisters a listener previously added.
  72.438 -         * @param l the listener to remove
  72.439 -         */
  72.440 -        public abstract void removeLookupListener(LookupListener l);
  72.441 -
  72.442 -        /** Get all instances in the result. The return value type
  72.443 -         * should be List instead of Collection, but it is too late to change it.
  72.444 -         * @return unmodifiable collection of all instances that will never change its content
  72.445 -         */
  72.446 -        public abstract Collection<? extends T> allInstances();
  72.447 -
  72.448 -        /** Get all classes represented in the result.
  72.449 -         * That is, the set of concrete classes
  72.450 -         * used by instances present in the result.
  72.451 -         * All duplicate classes will be omitted.
  72.452 -         * @return unmodifiable set of <code>Class</code> objects that will never change its content
  72.453 -         *
  72.454 -         * @since 1.8
  72.455 -         */
  72.456 -        public Set<Class<? extends T>> allClasses() {
  72.457 -            return Collections.emptySet();
  72.458 -        }
  72.459 -
  72.460 -        /** Get all registered items.
  72.461 -         * This should include all pairs of instances together
  72.462 -         * with their classes, IDs, and so on. The return value type
  72.463 -         * should be List instead of Collection, but it is too late to change it.
  72.464 -         * @return unmodifiable collection of {@link Lookup.Item} that will never change its content
  72.465 -         *
  72.466 -         * @since 1.8
  72.467 -         */
  72.468 -        public Collection<? extends Item<T>> allItems() {
  72.469 -            return Collections.emptyList();
  72.470 -        }
  72.471 -    }
  72.472 -
  72.473 -    /** A single item in a lookup result.
  72.474 -     * This wrapper provides unified access to not just the instance,
  72.475 -     * but its class, a possible persistent identifier, and so on.
  72.476 -     *
  72.477 -     * @since 1.25
  72.478 -     */
  72.479 -    public static abstract class Item<T> extends Object {
  72.480 -        /** Get the instance itself.
  72.481 -         * @return the instance or null if the instance cannot be created
  72.482 -         */
  72.483 -        public abstract T getInstance();
  72.484 -
  72.485 -        /** Get the implementing class of the instance.
  72.486 -         * @return the class of the item
  72.487 -         */
  72.488 -        public abstract Class<? extends T> getType();
  72.489 -
  72.490 -        // XXX can it be null??
  72.491 -
  72.492 -        /** Get a persistent indentifier for the item.
  72.493 -         * This identifier should uniquely represent the item
  72.494 -         * within its containing lookup (and if possible within the
  72.495 -         * global lookup as a whole). For example, it might represent
  72.496 -         * the source of the instance as a file name. The ID may be
  72.497 -         * persisted and in a later session used to find the same instance
  72.498 -         * as was encountered earlier, by means of passing it into a
  72.499 -         * lookup template.
  72.500 -         *
  72.501 -         * @return a string ID of the item
  72.502 -         */
  72.503 -        public abstract String getId();
  72.504 -
  72.505 -        /** Get a human presentable name for the item.
  72.506 -         * This might be used when summarizing all the items found in a
  72.507 -         * lookup result in some part of a GUI.
  72.508 -         * @return the string suitable for presenting the object to a user
  72.509 -         */
  72.510 -        public abstract String getDisplayName();
  72.511 -
  72.512 -        /* show ID for debugging */
  72.513 -        @Override
  72.514 -        public String toString() {
  72.515 -            return getId();
  72.516 -        }
  72.517 -    }
  72.518 -
  72.519 -    //
  72.520 -    // Implementation of the default lookup
  72.521 -    //
  72.522 -    private static final class Empty extends Lookup {
  72.523 -        private static final Result NO_RESULT = new Result() {
  72.524 -                public void addLookupListener(LookupListener l) {
  72.525 -                }
  72.526 -
  72.527 -                public void removeLookupListener(LookupListener l) {
  72.528 -                }
  72.529 -
  72.530 -                public Collection allInstances() {
  72.531 -                    return Collections.EMPTY_SET;
  72.532 -                }
  72.533 -            };
  72.534 -
  72.535 -        Empty() {
  72.536 -        }
  72.537 -
  72.538 -        public <T> T lookup(Class<T> clazz) {
  72.539 -            return null;
  72.540 -        }
  72.541 -
  72.542 -        @SuppressWarnings("unchecked")
  72.543 -        public <T> Result<T> lookup(Template<T> template) {
  72.544 -            return NO_RESULT;
  72.545 -        }
  72.546 -    }
  72.547 -}
    73.1 --- a/openide.util/src/org/openide/util/LookupEvent.java	Sat Oct 31 15:06:58 2009 +0100
    73.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.3 @@ -1,57 +0,0 @@
    73.4 -/*
    73.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    73.6 - *
    73.7 - * Copyright 1997-2009 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 - * Contributor(s):
   73.28 - *
   73.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   73.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   73.31 - * Microsystems, Inc. All Rights Reserved.
   73.32 - *
   73.33 - * If you wish your version of this file to be governed by only the CDDL
   73.34 - * or only the GPL Version 2, indicate your decision by adding
   73.35 - * "[Contributor] elects to include this software in this distribution
   73.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   73.37 - * single choice of license, a recipient has the option to distribute
   73.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   73.39 - * to extend the choice of license to its licensees as provided above.
   73.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   73.41 - * Version 2 license, then the option applies only if the new code is
   73.42 - * made subject to such option by the copyright holder.
   73.43 - */
   73.44 -package org.openide.util;
   73.45 -
   73.46 -import java.util.*;
   73.47 -
   73.48 -
   73.49 -/** An event describing the change in the lookup's result.
   73.50 - *
   73.51 - * @author  Jaroslav Tulach
   73.52 - */
   73.53 -public final class LookupEvent extends EventObject {
   73.54 -    /** Create a new lookup event.
   73.55 -     * @param source the lookup result which has changed
   73.56 -     */
   73.57 -    public LookupEvent(Lookup.Result source) {
   73.58 -        super(source);
   73.59 -    }
   73.60 -}
    74.1 --- a/openide.util/src/org/openide/util/LookupListener.java	Sat Oct 31 15:06:58 2009 +0100
    74.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.3 @@ -1,59 +0,0 @@
    74.4 -/*
    74.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    74.6 - *
    74.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    74.8 - *
    74.9 - * The contents of this file are subject to the terms of either the GNU
   74.10 - * General Public License Version 2 only ("GPL") or the Common
   74.11 - * Development and Distribution License("CDDL") (collectively, the
   74.12 - * "License"). You may not use this file except in compliance with the
   74.13 - * License. You can obtain a copy of the License at
   74.14 - * http://www.netbeans.org/cddl-gplv2.html
   74.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   74.16 - * specific language governing permissions and limitations under the
   74.17 - * License.  When distributing the software, include this License Header
   74.18 - * Notice in each file and include the License file at
   74.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   74.20 - * particular file as subject to the "Classpath" exception as provided
   74.21 - * by Sun in the GPL Version 2 section of the License file that
   74.22 - * accompanied this code. If applicable, add the following below the
   74.23 - * License Header, with the fields enclosed by brackets [] replaced by
   74.24 - * your own identifying information:
   74.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   74.26 - *
   74.27 - * Contributor(s):
   74.28 - *
   74.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   74.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   74.31 - * Microsystems, Inc. All Rights Reserved.
   74.32 - *
   74.33 - * If you wish your version of this file to be governed by only the CDDL
   74.34 - * or only the GPL Version 2, indicate your decision by adding
   74.35 - * "[Contributor] elects to include this software in this distribution
   74.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   74.37 - * single choice of license, a recipient has the option to distribute
   74.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   74.39 - * to extend the choice of license to its licensees as provided above.
   74.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   74.41 - * Version 2 license, then the option applies only if the new code is
   74.42 - * made subject to such option by the copyright holder.
   74.43 - */
   74.44 -package org.openide.util;
   74.45 -
   74.46 -import java.util.*;
   74.47 -
   74.48 -
   74.49 -/** General listener for changes in lookup.
   74.50 - *
   74.51 - * @author  Jaroslav Tulach
   74.52 - */
   74.53 -public interface LookupListener extends EventListener {
   74.54 -    /** A change in lookup occured. Please note that this method
   74.55 -     * should never block since it might be called from lookup implementation
   74.56 -     * internal threads. If you block here you are in risk that the thread
   74.57 -     * you wait for might in turn to wait for the lookup internal thread to
   74.58 -     * finish its work.
   74.59 -     * @param ev event describing the change
   74.60 -     */
   74.61 -    public void resultChanged(LookupEvent ev);
   74.62 -}
    75.1 --- a/openide.util/src/org/openide/util/lookup/ALPairComparator.java	Sat Oct 31 15:06:58 2009 +0100
    75.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.3 @@ -1,88 +0,0 @@
    75.4 -/*
    75.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    75.6 - *
    75.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    75.8 - *
    75.9 - * The contents of this file are subject to the terms of either the GNU
   75.10 - * General Public License Version 2 only ("GPL") or the Common
   75.11 - * Development and Distribution License("CDDL") (collectively, the
   75.12 - * "License"). You may not use this file except in compliance with the
   75.13 - * License. You can obtain a copy of the License at
   75.14 - * http://www.netbeans.org/cddl-gplv2.html
   75.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   75.16 - * specific language governing permissions and limitations under the
   75.17 - * License.  When distributing the software, include this License Header
   75.18 - * Notice in each file and include the License file at
   75.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   75.20 - * particular file as subject to the "Classpath" exception as provided
   75.21 - * by Sun in the GPL Version 2 section of the License file that
   75.22 - * accompanied this code. If applicable, add the following below the
   75.23 - * License Header, with the fields enclosed by brackets [] replaced by
   75.24 - * your own identifying information:
   75.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   75.26 - *
   75.27 - * Contributor(s):
   75.28 - *
   75.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   75.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   75.31 - * Microsystems, Inc. All Rights Reserved.
   75.32 - *
   75.33 - * If you wish your version of this file to be governed by only the CDDL
   75.34 - * or only the GPL Version 2, indicate your decision by adding
   75.35 - * "[Contributor] elects to include this software in this distribution
   75.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   75.37 - * single choice of license, a recipient has the option to distribute
   75.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   75.39 - * to extend the choice of license to its licensees as provided above.
   75.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   75.41 - * Version 2 license, then the option applies only if the new code is
   75.42 - * made subject to such option by the copyright holder.
   75.43 - */
   75.44 -package org.openide.util.lookup;
   75.45 -
   75.46 -import java.util.Comparator;
   75.47 -import org.openide.util.lookup.AbstractLookup.Pair;
   75.48 -
   75.49 -
   75.50 -/** Implementation of comparator for AbstractLookup.Pair
   75.51 - *
   75.52 - * @author  Jaroslav Tulach
   75.53 - */
   75.54 -final class ALPairComparator implements Comparator<Pair<?>> {
   75.55 -    public static final Comparator<Pair<?>> DEFAULT = new ALPairComparator();
   75.56 -
   75.57 -    /** Creates a new instance of ALPairComparator */
   75.58 -    private ALPairComparator() {
   75.59 -    }
   75.60 -
   75.61 -    /** Compares two items.
   75.62 -    */
   75.63 -    public int compare(Pair<?> i1, Pair<?> i2) {
   75.64 -        int result = i1.getIndex() - i2.getIndex();
   75.65 -
   75.66 -        if (result == 0) {
   75.67 -            if (i1 != i2) {
   75.68 -                java.io.ByteArrayOutputStream bs = new java.io.ByteArrayOutputStream();
   75.69 -                java.io.PrintStream ps = new java.io.PrintStream(bs);
   75.70 -
   75.71 -                ps.println(
   75.72 -                    "Duplicate pair in tree" + // NOI18N
   75.73 -                    "Pair1: " + i1 + " pair2: " + i2 + " index1: " + i1.getIndex() + " index2: " +
   75.74 -                    i2.getIndex() // NOI18N
   75.75 -                     +" item1: " + i1.getInstance() + " item2: " + i2.getInstance() // NOI18N
   75.76 -                     +" id1: " + Integer.toHexString(System.identityHashCode(i1)) // NOI18N
   75.77 -                     +" id2: " + Integer.toHexString(System.identityHashCode(i2)) // NOI18N
   75.78 -                );
   75.79 -
   75.80 -                //                print (ps, false);
   75.81 -                ps.close();
   75.82 -
   75.83 -                throw new IllegalStateException(bs.toString());
   75.84 -            }
   75.85 -
   75.86 -            return 0;
   75.87 -        }
   75.88 -
   75.89 -        return result;
   75.90 -    }
   75.91 -}
    76.1 --- a/openide.util/src/org/openide/util/lookup/AbstractLookup.java	Sat Oct 31 15:06:58 2009 +0100
    76.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.3 @@ -1,1467 +0,0 @@
    76.4 -/*
    76.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    76.6 - *
    76.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    76.8 - *
    76.9 - * The contents of this file are subject to the terms of either the GNU
   76.10 - * General Public License Version 2 only ("GPL") or the Common
   76.11 - * Development and Distribution License("CDDL") (collectively, the
   76.12 - * "License"). You may not use this file except in compliance with the
   76.13 - * License. You can obtain a copy of the License at
   76.14 - * http://www.netbeans.org/cddl-gplv2.html
   76.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   76.16 - * specific language governing permissions and limitations under the
   76.17 - * License.  When distributing the software, include this License Header
   76.18 - * Notice in each file and include the License file at
   76.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   76.20 - * particular file as subject to the "Classpath" exception as provided
   76.21 - * by Sun in the GPL Version 2 section of the License file that
   76.22 - * accompanied this code. If applicable, add the following below the
   76.23 - * License Header, with the fields enclosed by brackets [] replaced by
   76.24 - * your own identifying information:
   76.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   76.26 - *
   76.27 - * Contributor(s):
   76.28 - *
   76.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   76.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   76.31 - * Microsystems, Inc. All Rights Reserved.
   76.32 - *
   76.33 - * If you wish your version of this file to be governed by only the CDDL
   76.34 - * or only the GPL Version 2, indicate your decision by adding
   76.35 - * "[Contributor] elects to include this software in this distribution
   76.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   76.37 - * single choice of license, a recipient has the option to distribute
   76.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   76.39 - * to extend the choice of license to its licensees as provided above.
   76.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   76.41 - * Version 2 license, then the option applies only if the new code is
   76.42 - * made subject to such option by the copyright holder.
   76.43 - */
   76.44 -package org.openide.util.lookup;
   76.45 -
   76.46 -import java.io.PrintStream;
   76.47 -import org.openide.util.Lookup;
   76.48 -import org.openide.util.LookupEvent;
   76.49 -import org.openide.util.LookupListener;
   76.50 -
   76.51 -import java.io.IOException;
   76.52 -import java.io.ObjectOutputStream;
   76.53 -import java.io.Serializable;
   76.54 -
   76.55 -import java.lang.ref.ReferenceQueue;
   76.56 -import java.lang.ref.WeakReference;
   76.57 -import java.util.ArrayList;
   76.58 -import java.util.Arrays;
   76.59 -import java.util.Collection;
   76.60 -import java.util.Collections;
   76.61 -import java.util.Enumeration;
   76.62 -import java.util.HashMap;
   76.63 -import java.util.HashSet;
   76.64 -import java.util.Iterator;
   76.65 -import java.util.LinkedHashSet;
   76.66 -import java.util.Map;
   76.67 -import java.util.Set;
   76.68 -import java.util.TreeSet;
   76.69 -
   76.70 -import java.util.concurrent.Executor;
   76.71 -import org.netbeans.modules.openide.util.ActiveQueue;
   76.72 -
   76.73 -
   76.74 -/** Implementation of the lookup from OpenAPIs that is based on the
   76.75 - * introduction of Item. This class should provide the default way
   76.76 - * of how to store (Class, Object) pairs in the lookups. It offers
   76.77 - * protected methods for subclasses to register the pairs.
   76.78 - * <p>Serializable since 3.27.
   76.79 - * @author  Jaroslav Tulach
   76.80 - * @since 1.9
   76.81 - */
   76.82 -public class AbstractLookup extends Lookup implements Serializable {
   76.83 -    static final long serialVersionUID = 5L;
   76.84 -
   76.85 -    /** lock for initialization of the maps of lookups */
   76.86 -    private static final Object treeLock = new Object();
   76.87 -
   76.88 -    /** the tree that registers all items (or Integer as a treshold size) */
   76.89 -    private Object tree;
   76.90 -
   76.91 -    /** count of items in to lookup */
   76.92 -    private int count;
   76.93 -
   76.94 -    /** Constructor to create this lookup and associate it with given
   76.95 -     * Content. The content than allows the creator to invoke protected
   76.96 -     * methods which are not accessible for any other user of the lookup.
   76.97 -     *
   76.98 -     * @param content the content to assciate with
   76.99 -     *
  76.100 -     * @since 1.25
  76.101 -     */
  76.102 -    public AbstractLookup(Content content) {
  76.103 -        content.attach(this);
  76.104 -    }
  76.105 -
  76.106 -    /** Constructor for testing purposes that allows specification of storage
  76.107 -     * as mechanism as well.
  76.108 -     */
  76.109 -    AbstractLookup(Content content, Storage<?> storage) {
  76.110 -        this(content);
  76.111 -        this.tree = storage;
  76.112 -        initialize();
  76.113 -    }
  76.114 -
  76.115 -    /** Constructor for testing purposes that allows specification of storage
  76.116 -     * as mechanism as well.
  76.117 -     * @param trashhold number of Pair to "remain small"
  76.118 -     */
  76.119 -    AbstractLookup(Content content, Integer trashhold) {
  76.120 -        this(content);
  76.121 -        this.tree = trashhold;
  76.122 -    }
  76.123 -
  76.124 -    /** Default constructor for subclasses that do not need to provide a content
  76.125 -     */
  76.126 -    protected AbstractLookup() {
  76.127 -    }
  76.128 -
  76.129 -    @Override
  76.130 -    public String toString() {
  76.131 -        if (tree instanceof Storage) {
  76.132 -            return "AbstractLookup" + lookup(new Lookup.Template<Object>(Object.class)).allItems(); // NOI18N
  76.133 -        } else {
  76.134 -            return super.toString();
  76.135 -        }
  76.136 -    }
  76.137 -
  76.138 -    /** Entres the storage management system.
  76.139 -     */
  76.140 -    @SuppressWarnings("unchecked")
  76.141 -    private <T> AbstractLookup.Storage<T> enterStorage() {
  76.142 -        for (;;) {
  76.143 -            synchronized (treeLock) {
  76.144 -                if (tree instanceof AbstractLookup.Storage) {
  76.145 -                    if (tree instanceof DelegatingStorage) {
  76.146 -                        // somebody is using the lookup right now
  76.147 -                        DelegatingStorage del = (DelegatingStorage) tree;
  76.148 -
  76.149 -                        // check whether there is not access from the same 
  76.150 -                        // thread (can throw exception)
  76.151 -                        del.checkForTreeModification();
  76.152 -
  76.153 -                        try {
  76.154 -                            treeLock.wait();
  76.155 -                        } catch (InterruptedException ex) {
  76.156 -                            // ignore and go on
  76.157 -                        }
  76.158 -
  76.159 -                        continue;
  76.160 -                    } else {
  76.161 -                        // ok, tree is initialized and nobody is using it yet
  76.162 -                        tree = new DelegatingStorage((Storage<T>) tree);
  76.163 -
  76.164 -                        return (Storage<T>) tree;
  76.165 -                    }
  76.166 -                }
  76.167 -
  76.168 -                // first time initialization of the tree
  76.169 -                if (tree instanceof Integer) {
  76.170 -                    tree = new ArrayStorage((Integer) tree);
  76.171 -                } else {
  76.172 -                    tree = new ArrayStorage();
  76.173 -                }
  76.174 -            }
  76.175 -
  76.176 -            // the tree has not yet been initilized, initialize and go on again
  76.177 -            initialize();
  76.178 -        }
  76.179 -    }
  76.180 -
  76.181 -    /** Exists tree ownership.
  76.182 -     */
  76.183 -    private AbstractLookup.Storage exitStorage() {
  76.184 -        synchronized (treeLock) {
  76.185 -            AbstractLookup.Storage stor = ((DelegatingStorage) tree).exitDelegate();
  76.186 -            tree = stor;
  76.187 -            treeLock.notifyAll();
  76.188 -
  76.189 -            return stor;
  76.190 -        }
  76.191 -    }
  76.192 -
  76.193 -    /** Method for subclasses to initialize them selves.
  76.194 -     */
  76.195 -    protected void initialize() {
  76.196 -    }
  76.197 -
  76.198 -    /** Notifies subclasses that a query is about to be processed.
  76.199 -     * @param template the template
  76.200 -     */
  76.201 -    protected void beforeLookup(Template<?> template) {
  76.202 -    }
  76.203 -
  76.204 -    /** The method to add instance to the lookup with.
  76.205 -     * @param pair class/instance pair
  76.206 -     */
  76.207 -    protected final void addPair(Pair<?> pair) {
  76.208 -        addPairImpl(pair, null);
  76.209 -    }
  76.210 -
  76.211 -    /** The method to add instance to the lookup with.
  76.212 -     * @param pair class/instance pair
  76.213 -     * @param notifyIn the executor that will handle the notification of events
  76.214 -     * @since 7.16
  76.215 -     */
  76.216 -    protected final void addPair(Pair<?> pair, Executor notifyIn) {
  76.217 -        addPairImpl(pair, notifyIn);
  76.218 -    }
  76.219 -
  76.220 -    private final <Transaction> void addPairImpl(Pair<?> pair, Executor notifyIn) {
  76.221 -        HashSet<R> toNotify = new HashSet<R>();
  76.222 -
  76.223 -        AbstractLookup.Storage<Transaction> t = enterStorage();
  76.224 -        Transaction transaction = null;
  76.225 -
  76.226 -        try {
  76.227 -            transaction = t.beginTransaction(-2);
  76.228 -
  76.229 -            if (t.add(pair, transaction)) {
  76.230 -                try {
  76.231 -                    pair.setIndex(t, count++);
  76.232 -                } catch (IllegalStateException ex) {
  76.233 -                    // remove the pair
  76.234 -                    t.remove(pair, transaction);
  76.235 -
  76.236 -                    // rethrow the exception
  76.237 -                    throw ex;
  76.238 -                }
  76.239 -
  76.240 -                // if the pair is newly added and was not there before
  76.241 -                t.endTransaction(transaction, toNotify);
  76.242 -            } else {
  76.243 -                // just finish the process by calling endTransaction
  76.244 -                t.endTransaction(transaction, new HashSet<R>());
  76.245 -            }
  76.246 -        } finally {
  76.247 -            exitStorage();
  76.248 -        }
  76.249 -
  76.250 -        notifyIn(notifyIn, toNotify);
  76.251 -    }
  76.252 -
  76.253 -    /** Remove instance.
  76.254 -     * @param pair class/instance pair
  76.255 -     */
  76.256 -    protected final void removePair(Pair<?> pair) {
  76.257 -        removePairImpl(pair, null);
  76.258 -    }
  76.259 -    /** Remove instance.
  76.260 -     * @param pair class/instance pair
  76.261 -     * @param notifyIn the executor that will handle the notification of events
  76.262 -     * @since 7.16
  76.263 -     */
  76.264 -    protected final void removePair(Pair<?> pair, Executor notifyIn) {
  76.265 -        removePairImpl(pair, notifyIn);
  76.266 -    }
  76.267 -
  76.268 -    private <Transaction> void removePairImpl(Pair<?> pair, Executor notifyIn) {
  76.269 -        HashSet<R> toNotify = new HashSet<R>();
  76.270 -
  76.271 -        AbstractLookup.Storage<Transaction> t = enterStorage();
  76.272 -        Transaction transaction = null;
  76.273 -
  76.274 -        try {
  76.275 -            transaction = t.beginTransaction(-1);
  76.276 -            t.remove(pair, transaction);
  76.277 -            t.endTransaction(transaction, toNotify);
  76.278 -        } finally {
  76.279 -            exitStorage();
  76.280 -        }
  76.281 -
  76.282 -        notifyIn(notifyIn, toNotify);
  76.283 -    }
  76.284 -
  76.285 -    /** Changes all pairs in the lookup to new values.
  76.286 -     * @param collection the collection of (Pair) objects
  76.287 -     */
  76.288 -    protected final void setPairs(Collection<? extends Pair> collection) {
  76.289 -        setPairs(collection, null);
  76.290 -    }
  76.291 -
  76.292 -    /** Changes all pairs in the lookup to new values, notifies listeners
  76.293 -     * using provided executor.
  76.294 -     * 
  76.295 -     * @param collection the collection of (Pair) objects
  76.296 -     * @param notifyIn the executor that will handle the notification of events
  76.297 -     * @since 7.16
  76.298 -     */
  76.299 -    protected final void setPairs(Collection<? extends Pair> collection, Executor notifyIn) {
  76.300 -        HashSet<R> listeners = setPairsAndCollectListeners(collection);
  76.301 -        notifyIn(notifyIn, listeners);
  76.302 -    }
  76.303 -    
  76.304 -    private final void notifyIn(Executor notifyIn, final HashSet<R> listeners) {
  76.305 -        NotifyListeners notify = new NotifyListeners(listeners);
  76.306 -        if (notify.shallRun()) {
  76.307 -            if (notifyIn == null) {
  76.308 -                notify.run();
  76.309 -            } else {
  76.310 -                notifyIn.execute(notify);
  76.311 -            }
  76.312 -        }
  76.313 -    }
  76.314 -    
  76.315 -    /** Getter for set of pairs. Package private contract with MetaInfServicesLookup.
  76.316 -     * @return a LinkedHashSet that can be modified
  76.317 -     */
  76.318 -    final LinkedHashSet<Pair<?>> getPairsAsLHS() {
  76.319 -        AbstractLookup.Storage<?> t = enterStorage();
  76.320 -
  76.321 -        try {
  76.322 -            Enumeration<Pair<Object>> en = t.lookup(Object.class);
  76.323 -            TreeSet<Pair<?>> arr = new TreeSet<Pair<?>>(ALPairComparator.DEFAULT);
  76.324 -            while (en.hasMoreElements()) {
  76.325 -                Pair<Object> item = en.nextElement();
  76.326 -                arr.add(item);
  76.327 -            }
  76.328 -            return new LinkedHashSet<Pair<?>>(arr);
  76.329 -        } finally {
  76.330 -            exitStorage();
  76.331 -        }
  76.332 -    }
  76.333 -
  76.334 -    /** Collects listeners without notification. Needed in MetaInfServicesLookup
  76.335 -     * right now, but maybe will become an API later.
  76.336 -     */
  76.337 -    final <Transaction> HashSet<R> setPairsAndCollectListeners(Collection<? extends Pair> collection) {
  76.338 -        HashSet<R> toNotify = new HashSet<R>(27);
  76.339 -
  76.340 -        AbstractLookup.Storage<Transaction> t = enterStorage();
  76.341 -        Transaction transaction = null;
  76.342 -
  76.343 -        try {
  76.344 -            // map between the Items and their indexes (Integer)
  76.345 -            HashMap<Item<?>,Info> shouldBeThere = new HashMap<Item<?>,Info>(collection.size() * 2);
  76.346 -
  76.347 -            count = 0;
  76.348 -
  76.349 -            Iterator it = collection.iterator();
  76.350 -            transaction = t.beginTransaction(collection.size());
  76.351 -
  76.352 -            while (it.hasNext()) {
  76.353 -                Pair item = (Pair) it.next();
  76.354 -
  76.355 -                if (t.add(item, transaction)) {
  76.356 -                    // the item has not been there yet
  76.357 -                    //t.endTransaction(transaction, toNotify);
  76.358 -                }
  76.359 -
  76.360 -                // remeber the item, because it should not be removed
  76.361 -                shouldBeThere.put(item, new Info(count++, transaction));
  76.362 -
  76.363 -                //                    arr.clear ();
  76.364 -            }
  76.365 -
  76.366 -            //            Object transaction = t.beginTransaction ();
  76.367 -            // deletes all objects that should not be there and
  76.368 -            t.retainAll(shouldBeThere, transaction);
  76.369 -
  76.370 -            // collect listeners
  76.371 -            t.endTransaction(transaction, toNotify);
  76.372 -
  76.373 -            /*
  76.374 -            // check consistency
  76.375 -            Enumeration en = t.lookup (java.lang.Object.class);
  76.376 -            boolean[] max = new boolean[count];
  76.377 -            int mistake = -1;
  76.378 -            while (en.hasMoreElements ()) {
  76.379 -                Pair item = (Pair)en.nextElement ();
  76.380 -
  76.381 -                if (max[item.index]) {
  76.382 -                    mistake = item.index;
  76.383 -                }
  76.384 -                max[item.index] = true;
  76.385 -            }
  76.386 -
  76.387 -            if (mistake != -1) {
  76.388 -                System.err.println ("Mistake at: " + mistake);
  76.389 -                tree.print (System.err, true);
  76.390 -            }
  76.391 -            */
  76.392 -        } finally {
  76.393 -            exitStorage();
  76.394 -        }
  76.395 -
  76.396 -        return toNotify;
  76.397 -    }
  76.398 -
  76.399 -    private final void writeObject(ObjectOutputStream oos)
  76.400 -    throws IOException {
  76.401 -        AbstractLookup.Storage s = enterStorage();
  76.402 -
  76.403 -        try {
  76.404 -            // #36830: Serializing only InheritanceTree no ArrayStorage
  76.405 -            s.beginTransaction(Integer.MAX_VALUE);
  76.406 -
  76.407 -            // #32040: don't write half-made changes
  76.408 -            oos.defaultWriteObject();
  76.409 -        } finally {
  76.410 -            exitStorage();
  76.411 -        }
  76.412 -    }
  76.413 -
  76.414 -    public final <T> T lookup(Class<T> clazz) {
  76.415 -        Lookup.Item<T> item = lookupItem(new Lookup.Template<T>(clazz));
  76.416 -        return (item == null) ? null : item.getInstance();
  76.417 -    }
  76.418 -
  76.419 -    @Override
  76.420 -    public final <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
  76.421 -        AbstractLookup.this.beforeLookup(template);
  76.422 -
  76.423 -        ArrayList<Pair<T>> list = null;
  76.424 -        AbstractLookup.Storage<?> t = enterStorage();
  76.425 -
  76.426 -        try {
  76.427 -            Enumeration<Pair<T>> en;
  76.428 -
  76.429 -            try {
  76.430 -                en = t.lookup(template.getType());
  76.431 -
  76.432 -                return findSmallest(en, template, false);
  76.433 -            } catch (AbstractLookup.ISE ex) {
  76.434 -                // not possible to enumerate the exception, ok, copy it 
  76.435 -                // to create new
  76.436 -                list = new ArrayList<Pair<T>>();
  76.437 -                en = t.lookup(null); // this should get all the items without any checks
  76.438 -
  76.439 -                // the checks will be done out side of the storage
  76.440 -                while (en.hasMoreElements()) {
  76.441 -                    list.add(en.nextElement());
  76.442 -                }
  76.443 -            }
  76.444 -        } finally {
  76.445 -            exitStorage();
  76.446 -        }
  76.447 -
  76.448 -        return findSmallest(Collections.enumeration(list), template, true);
  76.449 -    }
  76.450 -
  76.451 -    private static <T> Pair<T> findSmallest(Enumeration<Pair<T>> en, Lookup.Template<T> template, boolean deepCheck) {
  76.452 -        int smallest = InheritanceTree.unsorted(en) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
  76.453 -        Pair<T> res = null;
  76.454 -
  76.455 -        while (en.hasMoreElements()) {
  76.456 -            Pair<T> item = en.nextElement();
  76.457 -
  76.458 -            if (matches(template, item, deepCheck)) {
  76.459 -                if (smallest == Integer.MIN_VALUE) {
  76.460 -                    // ok, sorted enumeration the first that matches is fine
  76.461 -                    return item;
  76.462 -                } else {
  76.463 -                    // check for the smallest item
  76.464 -                    if (smallest > item.getIndex()) {
  76.465 -                        smallest = item.getIndex();
  76.466 -                        res = item;
  76.467 -                    }
  76.468 -                }
  76.469 -            }
  76.470 -        }
  76.471 -
  76.472 -        return res;
  76.473 -    }
  76.474 -
  76.475 -    public final <T> Lookup.Result<T> lookup(Lookup.Template<T> template) {
  76.476 -        for (;;) {
  76.477 -            AbstractLookup.ISE toRun = null;
  76.478 -
  76.479 -            AbstractLookup.Storage<?> t = enterStorage();
  76.480 -
  76.481 -            try {
  76.482 -                R<T> r = new R<T>();
  76.483 -                ReferenceToResult<T> newRef = new ReferenceToResult<T>(r, this, template);
  76.484 -                newRef.next = t.registerReferenceToResult(newRef);
  76.485 -
  76.486 -                return r;
  76.487 -            } catch (AbstractLookup.ISE ex) {
  76.488 -                toRun = ex;
  76.489 -            } finally {
  76.490 -                exitStorage();
  76.491 -            }
  76.492 -
  76.493 -            toRun.recover(this);
  76.494 -
  76.495 -            // and try again
  76.496 -        }
  76.497 -    }
  76.498 -
  76.499 -    /** Notifies listeners.
  76.500 -     * @param allAffectedResults set of R
  76.501 -     */
  76.502 -    static final class NotifyListeners implements Runnable {
  76.503 -        private final ArrayList<Object> evAndListeners;
  76.504 -        
  76.505 -        public NotifyListeners(Set<R> allAffectedResults) {
  76.506 -            if (allAffectedResults.isEmpty()) {
  76.507 -                evAndListeners = null;
  76.508 -                return;
  76.509 -            }
  76.510 -
  76.511 -            evAndListeners = new ArrayList<Object>();
  76.512 -            {
  76.513 -                for (R<?> result : allAffectedResults) {
  76.514 -                    result.collectFires(evAndListeners);
  76.515 -                }
  76.516 -            }
  76.517 -        }
  76.518 -
  76.519 -        public boolean shallRun() {
  76.520 -            return evAndListeners != null && !evAndListeners.isEmpty();
  76.521 -        }
  76.522 -
  76.523 -        public void run() {
  76.524 -            Iterator it = evAndListeners.iterator();
  76.525 -            while (it.hasNext()) {
  76.526 -                LookupEvent ev = (LookupEvent)it.next();
  76.527 -                LookupListener l = (LookupListener)it.next();
  76.528 -                l.resultChanged(ev);
  76.529 -            }
  76.530 -        }
  76.531 -    }
  76.532 -
  76.533 -    /**
  76.534 -     * Call resultChanged on all listeners.
  76.535 -     * @param listeners array of listeners in the format used by
  76.536 -     *        javax.swing.EventListenerList. It means that there are Class
  76.537 -     *        objects on even positions and the listeners on odd positions
  76.538 -     * @param ev the event to fire
  76.539 -     */
  76.540 -    static void notifyListeners(Object[] listeners, LookupEvent ev, Collection<Object> evAndListeners) {
  76.541 -        for (int i = listeners.length - 1; i >= 0; i--) {
  76.542 -            if (! (listeners[i] instanceof LookupListener)) {
  76.543 -                continue;
  76.544 -            }
  76.545 -            LookupListener ll = (LookupListener)listeners[i];
  76.546 -
  76.547 -            try {
  76.548 -                if (evAndListeners != null) {
  76.549 -                    if (ll instanceof WaitableResult) {
  76.550 -                        WaitableResult<?> wr = (WaitableResult<?>)ll;
  76.551 -                        wr.collectFires(evAndListeners);
  76.552 -                    } else {
  76.553 -                        evAndListeners.add(ev);
  76.554 -                        evAndListeners.add(ll);
  76.555 -                    }
  76.556 -                } else {
  76.557 -                    ll.resultChanged(ev);
  76.558 -                }
  76.559 -            } catch (StackOverflowError err) {
  76.560 -                throw new CycleError(evAndListeners); // NOI18N
  76.561 -            } catch (RuntimeException e) {
  76.562 -                // Such as e.g. occurred in #32040. Do not halt other things.
  76.563 -                e.printStackTrace();
  76.564 -            }
  76.565 -        }
  76.566 -    }
  76.567 -
  76.568 -    private static class CycleError extends StackOverflowError {
  76.569 -        private final Collection<Object> print;
  76.570 -        public CycleError(Collection<Object> evAndListeners) {
  76.571 -            this.print = evAndListeners;
  76.572 -        }
  76.573 -
  76.574 -        @Override
  76.575 -        public String getMessage() {
  76.576 -            StringBuilder sb = new StringBuilder();
  76.577 -            sb.append("StackOverflowError, here are the listeners:\n"); // NOI18N
  76.578 -            for (Object o : print) {
  76.579 -                sb.append('\n').append(o);
  76.580 -                if (sb.length() > 10000) {
  76.581 -                    break;
  76.582 -                }
  76.583 -            }
  76.584 -            return sb.toString();
  76.585 -        }
  76.586 -    } // end of CycleError
  76.587 -
  76.588 -    /** A method that defines matching between Item and Template.
  76.589 -     * @param t template providing the criteria
  76.590 -     * @param item the item to match
  76.591 -     * @param deepCheck true if type of the pair should be tested, false if it is already has been tested
  76.592 -     * @return true if item matches the template requirements, false if not
  76.593 -     */
  76.594 -    static boolean matches(Template<?> t, Pair<?> item, boolean deepCheck) {
  76.595 -        String id = t.getId();
  76.596 -
  76.597 -        if (id != null && !id.equals(item.getId())) {
  76.598 -            return false;
  76.599 -        }
  76.600 -
  76.601 -        Object instance = t.getInstance();
  76.602 -
  76.603 -        if ((instance != null) && !item.creatorOf(instance)) {
  76.604 -            return false;
  76.605 -        }
  76.606 -
  76.607 -        if (deepCheck) {
  76.608 -            return item.instanceOf(t.getType());
  76.609 -        } else {
  76.610 -            return true;
  76.611 -        }
  76.612 -    }
  76.613 -
  76.614 -    /**
  76.615 -     * Compares the array elements for equality.
  76.616 -     * @return true if all elements in the arrays are equal
  76.617 -     *  (by calling equals(Object x) method)
  76.618 -     */
  76.619 -    private static boolean compareArrays(Object[] a, Object[] b) {
  76.620 -        // handle null values
  76.621 -        if (a == null) {
  76.622 -            return (b == null);
  76.623 -        } else {
  76.624 -            if (b == null) {
  76.625 -                return false;
  76.626 -            }
  76.627 -        }
  76.628 -
  76.629 -        if (a.length != b.length) {
  76.630 -            return false;
  76.631 -        }
  76.632 -
  76.633 -        for (int i = 0; i < a.length; i++) {
  76.634 -            // handle null values for individual elements
  76.635 -            if (a[i] == null) {
  76.636 -                if (b[i] != null) {
  76.637 -                    return false;
  76.638 -                }
  76.639 -
  76.640 -                // both are null --> ok, take next
  76.641 -                continue;
  76.642 -            } else {
  76.643 -                if (b[i] == null) {
  76.644 -                    return false;
  76.645 -                }
  76.646 -            }
  76.647 -
  76.648 -            // perform the comparison
  76.649 -            if (!a[i].equals(b[i])) {
  76.650 -                return false;
  76.651 -            }
  76.652 -        }
  76.653 -
  76.654 -        return true;
  76.655 -    }
  76.656 -
  76.657 -    /** Method to be called when a result is cleared to signal that the list
  76.658 -     * of all result should be checked for clearing.
  76.659 -     * @param template the template the result was for
  76.660 -     * @return true if the hash map with all items has been cleared
  76.661 -     */
  76.662 -    <T> boolean cleanUpResult(Lookup.Template<T> template) {
  76.663 -        AbstractLookup.Storage<?> t = enterStorage();
  76.664 -
  76.665 -        try {
  76.666 -            return t.cleanUpResult(template) == null;
  76.667 -        } finally {
  76.668 -            exitStorage();
  76.669 -        }
  76.670 -    }
  76.671 -
  76.672 -    /** Storage check for tests. */
  76.673 -    static boolean isSimple(AbstractLookup l) {
  76.674 -        return DelegatingStorage.isSimple((Storage)l.tree);
  76.675 -    }
  76.676 -
  76.677 -    /** Generic support for listeners, so it can be used in other results
  76.678 -     * as well.
  76.679 -     * @param add true to add it, false to modify
  76.680 -     * @param l listener to modify
  76.681 -     * @param ref the value of the reference to listener or listener list
  76.682 -     * @return new value to the reference to listener or list
  76.683 -     */
  76.684 -    @SuppressWarnings("unchecked")
  76.685 -    static Object modifyListenerList(boolean add, LookupListener l, Object ref) {
  76.686 -        if (add) {
  76.687 -            if (ref == null) {
  76.688 -                return l;
  76.689 -            }
  76.690 -
  76.691 -            if (ref instanceof LookupListener) {
  76.692 -                ArrayList arr = new ArrayList();
  76.693 -                arr.add(ref);
  76.694 -                ref = arr;
  76.695 -            }
  76.696 -
  76.697 -            ((ArrayList) ref).add(l);
  76.698 -
  76.699 -            return ref;
  76.700 -        } else {
  76.701 -            // remove
  76.702 -            if (ref == null) {
  76.703 -                return null;
  76.704 -            }
  76.705 -
  76.706 -            if (ref == l) {
  76.707 -                return null;
  76.708 -            }
  76.709 -
  76.710 -            ArrayList arr = (ArrayList) ref;
  76.711 -            arr.remove(l);
  76.712 -
  76.713 -            if (arr.size() == 1) {
  76.714 -                return arr.iterator().next();
  76.715 -            } else {
  76.716 -                return arr;
  76.717 -            }
  76.718 -        }
  76.719 -    }
  76.720 -
  76.721 -    private static ReferenceQueue<Object> activeQueue() {
  76.722 -        return ActiveQueue.queue();
  76.723 -    }
  76.724 -
  76.725 -    /** Storage to keep the internal structure of Pairs and to answer
  76.726 -     * different queries.
  76.727 -     */
  76.728 -    interface Storage<Transaction> {
  76.729 -        /** Initializes a modification operation by creating an object
  76.730 -         * that will be passsed to all add, remove, retainAll methods
  76.731 -         * and should collect enough information about the change to
  76.732 -         * notify listeners about the transaction later
  76.733 -         *
  76.734 -         * @param ensure the amount of items that will appear in the storage
  76.735 -         *   after the modifications (-1 == remove one, -2 == add one, >= 0
  76.736 -         *   the amount of objects at the end
  76.737 -         * @return a token to identify the transaction
  76.738 -         */
  76.739 -        public Transaction beginTransaction(int ensure);
  76.740 -
  76.741 -        /** Collects all affected results R that were modified in the
  76.742 -         * given transaction.
  76.743 -         *
  76.744 -         * @param modified place to add results R to
  76.745 -         * @param transaction the transaction indentification
  76.746 -         */
  76.747 -        public void endTransaction(Transaction transaction, Set<R> modifiedResults);
  76.748 -
  76.749 -        /** Adds an item into the storage.
  76.750 -        * @param item to add
  76.751 -        * @param transaction transaction token
  76.752 -        * @return true if the Item has been added for the first time or false if some other
  76.753 -        *    item equal to this one already existed in the lookup
  76.754 -        */
  76.755 -        public boolean add(AbstractLookup.Pair<?> item, Transaction transaction);
  76.756 -
  76.757 -        /** Removes an item.
  76.758 -        */
  76.759 -        public void remove(AbstractLookup.Pair item, Transaction transaction);
  76.760 -
  76.761 -        /** Removes all items that are not present in the provided collection.
  76.762 -        * @param retain collection of Pairs to keep them in
  76.763 -        * @param transaction the transaction context
  76.764 -        */
  76.765 -        public void retainAll(Map retain, Transaction transaction);
  76.766 -
  76.767 -        /** Queries for instances of given class.
  76.768 -        * @param clazz the class to check
  76.769 -        * @return enumeration of Item
  76.770 -        * @see #unsorted
  76.771 -        */
  76.772 -        public <T> Enumeration<Pair<T>> lookup(Class<T> clazz);
  76.773 -
  76.774 -        /** Registers another reference to a result with the storage. This method
  76.775 -         * has also a special meaning.
  76.776 -         *
  76.777 -         * @param newRef the new reference to remember
  76.778 -         * @return the previous reference that was kept (null if newRef is the first one)
  76.779 -         *    the applications is expected to link from newRef to this returned
  76.780 -         *    value to form a linked list
  76.781 -         */
  76.782 -        public ReferenceToResult<?> registerReferenceToResult(ReferenceToResult<?> newRef);
  76.783 -
  76.784 -        /** Given the provided template, Do cleanup the results.
  76.785 -         * @param templ template of a result(s) that should be checked
  76.786 -         * @return null if all references for this template were cleared or one of them
  76.787 -         */
  76.788 -        public ReferenceToResult<?> cleanUpResult(Lookup.Template<?> templ);
  76.789 -    }
  76.790 -
  76.791 -    /** Extension to the default lookup item that offers additional information
  76.792 -     * for the data structures use in AbstractLookup
  76.793 -     */
  76.794 -    public static abstract class Pair<T> extends Lookup.Item<T> implements Serializable {
  76.795 -        private static final long serialVersionUID = 1L;
  76.796 -
  76.797 -        /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */
  76.798 -        private int index = -1;
  76.799 -
  76.800 -        /** For use by subclasses. */
  76.801 -        protected Pair() {
  76.802 -        }
  76.803 -
  76.804 -        final int getIndex() {
  76.805 -            return index;
  76.806 -        }
  76.807 -
  76.808 -        final void setIndex(AbstractLookup.Storage<?> tree, int x) {
  76.809 -            if (tree == null) {
  76.810 -                this.index = x;
  76.811 -
  76.812 -                return;
  76.813 -            }
  76.814 -
  76.815 -            if (this.index == -1) {
  76.816 -                this.index = x;
  76.817 -            } else {
  76.818 -                throw new IllegalStateException("You cannot use " + this + " in more than one AbstractLookup. Prev: " + this.index + " new: " + x); // NOI18N
  76.819 -            }
  76.820 -        }
  76.821 -
  76.822 -        /** Tests whether this item can produce object
  76.823 -        * of class c.
  76.824 -        */
  76.825 -        protected abstract boolean instanceOf(Class<?> c);
  76.826 -
  76.827 -        /** Method that can test whether an instance of a class has been created
  76.828 -         * by this item.
  76.829 -         *
  76.830 -         * @param obj the instance
  76.831 -         * @return if the item has already create an instance and it is the same
  76.832 -         *   as obj.
  76.833 -         */
  76.834 -        protected abstract boolean creatorOf(Object obj);
  76.835 -    }
  76.836 -
  76.837 -    /** Result based on one instance returned.
  76.838 -     */
  76.839 -    static final class R<T> extends WaitableResult<T> {
  76.840 -        /** reference our result is attached to (do not modify) */
  76.841 -        public ReferenceToResult<T> reference;
  76.842 -
  76.843 -        /** listeners on the results or pointer to one listener */
  76.844 -        private Object listeners;
  76.845 -
  76.846 -        public R() {
  76.847 -        }
  76.848 -
  76.849 -        /** Checks whether we have simple behaviour of complex.
  76.850 -         */
  76.851 -        private boolean isSimple() {
  76.852 -            Storage s = (Storage) reference.lookup.tree;
  76.853 -
  76.854 -            return DelegatingStorage.isSimple(s);
  76.855 -        }
  76.856 -
  76.857 -        //
  76.858 -        // Handling cache management for both cases, no caches
  76.859 -        // for simple (but mark that we needed them, so refresh can
  76.860 -        // be done in cloneList) and complex when all 3 types
  76.861 -        // of result are cached
  76.862 -        //
  76.863 -        private Object getFromCache(int indx) {
  76.864 -            if (isSimple()) {
  76.865 -                return null;
  76.866 -            }
  76.867 -
  76.868 -            Object maybeArray = reference.caches;
  76.869 -
  76.870 -            if (maybeArray instanceof Object[]) {
  76.871 -                return ((Object[]) maybeArray)[indx];
  76.872 -            }
  76.873 -
  76.874 -            return null;
  76.875 -        }
  76.876 -
  76.877 -        @SuppressWarnings("unchecked")
  76.878 -        private Set<Class<? extends T>> getClassesCache() {
  76.879 -            return (Set<Class<? extends T>>) getFromCache(0);
  76.880 -        }
  76.881 -
  76.882 -        private void setClassesCache(Set s) {
  76.883 -            if (isSimple()) {
  76.884 -                // mark it as being used
  76.885 -                reference.caches = reference;
  76.886 -
  76.887 -                return;
  76.888 -            }
  76.889 -
  76.890 -            if (!(reference.caches instanceof Object[])) {
  76.891 -                reference.caches = new Object[3];
  76.892 -            }
  76.893 -
  76.894 -            ((Object[]) reference.caches)[0] = s;
  76.895 -        }
  76.896 -
  76.897 -        @SuppressWarnings("unchecked")
  76.898 -        private Collection<T> getInstancesCache() {
  76.899 -            return (Collection<T>) getFromCache(1);
  76.900 -        }
  76.901 -
  76.902 -        private void setInstancesCache(Collection c) {
  76.903 -            if (isSimple()) {
  76.904 -                // mark it as being used
  76.905 -                reference.caches = reference;
  76.906 -
  76.907 -                return;
  76.908 -            }
  76.909 -
  76.910 -            if (!(reference.caches instanceof Object[])) {
  76.911 -                reference.caches = new Object[3];
  76.912 -            }
  76.913 -
  76.914 -            ((Object[]) reference.caches)[1] = c;
  76.915 -        }
  76.916 -
  76.917 -        @SuppressWarnings("unchecked")
  76.918 -        private Pair<T>[] getItemsCache() {
  76.919 -            return (Pair<T>[]) getFromCache(2);
  76.920 -        }
  76.921 -
  76.922 -        private void setItemsCache(Collection<?> c) {
  76.923 -            if (isSimple()) {
  76.924 -                // mark it as being used
  76.925 -                reference.caches = reference;
  76.926 -
  76.927 -                return;
  76.928 -            }
  76.929 -
  76.930 -            if (!(reference.caches instanceof Object[])) {
  76.931 -                reference.caches = new Object[3];
  76.932 -            }
  76.933 -
  76.934 -            ((Object[]) reference.caches)[2] = c.toArray(new Pair[0]);
  76.935 -        }
  76.936 -
  76.937 -        private void clearCaches() {
  76.938 -            if (reference.caches instanceof Object[]) {
  76.939 -                reference.caches = new Object[3];
  76.940 -            }
  76.941 -        }
  76.942 -
  76.943 -        /** Ok, register listeners to all classes and super classes.
  76.944 -         */
  76.945 -        public synchronized void addLookupListener(LookupListener l) {
  76.946 -            listeners = modifyListenerList(true, l, listeners);
  76.947 -        }
  76.948 -
  76.949 -        /** Ok, register listeners to all classes and super classes.
  76.950 -         */
  76.951 -        public synchronized void removeLookupListener(LookupListener l) {
  76.952 -            listeners = modifyListenerList(false, l, listeners);
  76.953 -        }
  76.954 -
  76.955 -        /** Delete all cached values, the template changed.
  76.956 -         */
  76.957 -        protected  void collectFires(Collection<Object> evAndListeners) {
  76.958 -            Object[] previousItems = getItemsCache();
  76.959 -            clearCaches();
  76.960 -            
  76.961 -            if (previousItems != null) {
  76.962 -                Object[] newArray = allItemsWithoutBeforeLookup().toArray();
  76.963 -
  76.964 -                if (compareArrays(previousItems, newArray)) {
  76.965 -                    // do not fire any change if nothing has been changed
  76.966 -                    return;
  76.967 -                }
  76.968 -            }
  76.969 -
  76.970 -            LookupListener[] arr;
  76.971 -
  76.972 -            synchronized (this) {
  76.973 -                if (listeners == null) {
  76.974 -                    return;
  76.975 -                }
  76.976 -
  76.977 -                if (listeners instanceof LookupListener) {
  76.978 -                    arr = new LookupListener[] { (LookupListener) listeners };
  76.979 -                } else {
  76.980 -                    ArrayList<?> l = (ArrayList<?>) listeners;
  76.981 -                    arr = l.toArray(new LookupListener[l.size()]);
  76.982 -                }
  76.983 -            }
  76.984 -
  76.985 -            final LookupListener[] ll = arr;
  76.986 -            final LookupEvent ev = new LookupEvent(this);
  76.987 -            notifyListeners(ll, ev, evAndListeners);
  76.988 -        }
  76.989 -
  76.990 -        public Collection<T> allInstances() {
  76.991 -            reference.lookup.beforeLookup(reference.template);
  76.992 -
  76.993 -            Collection<T> s = getInstancesCache();
  76.994 -
  76.995 -            if (s != null) {
  76.996 -                return s;
  76.997 -            }
  76.998 -
  76.999 -            Collection<Pair<T>> items = allItemsWithoutBeforeLookup();
 76.1000 -            ArrayList<T> list = new ArrayList<T>(items.size());
 76.1001 -
 76.1002 -            Iterator<Pair<T>> it = items.iterator();
 76.1003 -
 76.1004 -            while (it.hasNext()) {
 76.1005 -                Pair<T> item = it.next();
 76.1006 -                T obj = item.getInstance();
 76.1007 -
 76.1008 -                if (reference.template.getType().isInstance(obj)) {
 76.1009 -                    list.add(obj);
 76.1010 -                }
 76.1011 -            }
 76.1012 -            
 76.1013 -            s = Collections.unmodifiableList(list);
 76.1014 -            setInstancesCache(s);
 76.1015 -
 76.1016 -            return s;
 76.1017 -        }
 76.1018 -
 76.1019 -        /** Set of all classes.
 76.1020 -         *
 76.1021 -         */
 76.1022 -        @Override
 76.1023 -        public Set<Class<? extends T>> allClasses() {
 76.1024 -            reference.lookup.beforeLookup(reference.template);
 76.1025 -
 76.1026 -            Set<Class<? extends T>> s = getClassesCache();
 76.1027 -
 76.1028 -            if (s != null) {
 76.1029 -                return s;
 76.1030 -            }
 76.1031 -
 76.1032 -            s = new HashSet<Class<? extends T>>();
 76.1033 -
 76.1034 -            for (Pair<T> item : allItemsWithoutBeforeLookup()) {
 76.1035 -                Class<? extends T> clazz = item.getType();
 76.1036 -
 76.1037 -                if (clazz != null) {
 76.1038 -                    s.add(clazz);
 76.1039 -                }
 76.1040 -            }
 76.1041 -
 76.1042 -            s = Collections.unmodifiableSet(s);
 76.1043 -            setClassesCache(s);
 76.1044 -
 76.1045 -            return s;
 76.1046 -        }
 76.1047 -
 76.1048 -        /** Items are stored directly in the allItems.
 76.1049 -         */
 76.1050 -        @Override
 76.1051 -        public Collection<? extends Item<T>> allItems() {
 76.1052 -            reference.lookup.beforeLookup(reference.template);
 76.1053 -
 76.1054 -            return allItemsWithoutBeforeLookup();
 76.1055 -        }
 76.1056 -
 76.1057 -        /** Implements the search for allItems, but without asking for before lookup */
 76.1058 -        private Collection<Pair<T>> allItemsWithoutBeforeLookup() {
 76.1059 -            Pair<T>[] c = getItemsCache();
 76.1060 -
 76.1061 -            if (c != null) {
 76.1062 -                return Collections.unmodifiableList(Arrays.asList(c));
 76.1063 -            }
 76.1064 -
 76.1065 -            ArrayList<Pair<Object>> saferCheck = null;
 76.1066 -            AbstractLookup.Storage<?> t = reference.lookup.enterStorage();
 76.1067 -
 76.1068 -            try {
 76.1069 -                try {
 76.1070 -                    return Collections.unmodifiableCollection(initItems(t));
 76.1071 -                } catch (AbstractLookup.ISE ex) {
 76.1072 -                    // do less effective evaluation of items outside of the 
 76.1073 -                    // locked storage
 76.1074 -                    saferCheck = new ArrayList<Pair<Object>>();
 76.1075 -
 76.1076 -                    Enumeration<Pair<Object>> en = t.lookup(null); // get all Pairs
 76.1077 -
 76.1078 -                    while (en.hasMoreElements()) {
 76.1079 -                        Pair<Object> i = en.nextElement();
 76.1080 -                        saferCheck.add(i);
 76.1081 -                    }
 76.1082 -                }
 76.1083 -            } finally {
 76.1084 -                reference.lookup.exitStorage();
 76.1085 -            }
 76.1086 -            return extractPairs(saferCheck);
 76.1087 -        }
 76.1088 -
 76.1089 -        @SuppressWarnings("unchecked")
 76.1090 -        private Collection<Pair<T>> extractPairs(final ArrayList<Pair<Object>> saferCheck) {
 76.1091 -            TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
 76.1092 -            for (Pair<Object> i : saferCheck) {
 76.1093 -                if (matches(reference.template, i, false)) {
 76.1094 -                    items.add((Pair<T>)i);
 76.1095 -                }
 76.1096 -            }
 76.1097 -            return Collections.unmodifiableCollection(items);
 76.1098 -        }
 76.1099 -
 76.1100 -        /** Initializes items.
 76.1101 -         */
 76.1102 -        private Collection<Pair<T>> initItems(Storage<?> t) {
 76.1103 -            // manipulation with the tree must be synchronized
 76.1104 -            Enumeration<Pair<T>> en = t.lookup(reference.template.getType());
 76.1105 -
 76.1106 -            // InheritanceTree is comparator for AbstractLookup.Pairs
 76.1107 -            TreeSet<Pair<T>> items = new TreeSet<Pair<T>>(ALPairComparator.DEFAULT);
 76.1108 -
 76.1109 -            while (en.hasMoreElements()) {
 76.1110 -                Pair<T> i = en.nextElement();
 76.1111 -
 76.1112 -                if (matches(reference.template, i, false)) {
 76.1113 -                    items.add(i);
 76.1114 -                }
 76.1115 -            }
 76.1116 -
 76.1117 -            // create a correctly sorted copy using the tree as the comparator
 76.1118 -            setItemsCache(items);
 76.1119 -
 76.1120 -            return items;
 76.1121 -        }
 76.1122 -
 76.1123 -        /** Used by proxy results to synchronize before lookup.
 76.1124 -         */
 76.1125 -        protected void beforeLookup(Lookup.Template t) {
 76.1126 -            if (t.getType() == reference.template.getType()) {
 76.1127 -                reference.lookup.beforeLookup(t);
 76.1128 -            }
 76.1129 -        }
 76.1130 -
 76.1131 -        /* Do not need to implement it, the default way is ok.
 76.1132 -        public boolean equals(java.lang.Object obj) {
 76.1133 -            return obj == this;
 76.1134 -        }
 76.1135 -        */
 76.1136 -        @Override
 76.1137 -        public String toString() {
 76.1138 -            return super.toString() + " for " + reference.template;
 76.1139 -        }
 76.1140 -    }
 76.1141 -     // end of R
 76.1142 -
 76.1143 -    /** A class that can be used by the creator of the AbstractLookup to
 76.1144 -     * control its content. It can be passed to AbstractLookup constructor
 76.1145 -     * and used to add and remove pairs.
 76.1146 -     *
 76.1147 -     * @since 1.25
 76.1148 -     */
 76.1149 -    public static class Content extends Object implements Serializable {
 76.1150 -        private static final long serialVersionUID = 1L;
 76.1151 -
 76.1152 -        // one of them is always null (except attach stage)
 76.1153 -
 76.1154 -        /** abstract lookup we are connected to */
 76.1155 -        private AbstractLookup al;
 76.1156 -        private transient Object notifyIn;
 76.1157 -        
 76.1158 -        /** Default constructor.
 76.1159 -         */
 76.1160 -        public Content() {
 76.1161 -            this(null);
 76.1162 -        }
 76.1163 -        
 76.1164 -        /** Creates a content associated with an executor to handle dispatch
 76.1165 -         * of changes.
 76.1166 -         * @param notifyIn the executor to notify changes in
 76.1167 -         * @since  7.16
 76.1168 -         */
 76.1169 -        public Content(Executor notifyIn) {
 76.1170 -            this.notifyIn = notifyIn;
 76.1171 -        }
 76.1172 -        
 76.1173 -        /** for testing purposes */
 76.1174 -        final void attachExecutor(Executor notifyIn) {
 76.1175 -            this.notifyIn = notifyIn;
 76.1176 -        }
 76.1177 -
 76.1178 -        /** A lookup attaches to this object.
 76.1179 -         */
 76.1180 -        final synchronized void attach(AbstractLookup al) {
 76.1181 -            if (this.al == null) {
 76.1182 -                this.al = al;
 76.1183 -
 76.1184 -                ArrayList<Pair> ep = getEarlyPairs();
 76.1185 -                if (ep != null) {
 76.1186 -                    notifyIn = null;
 76.1187 -                    setPairs(ep);
 76.1188 -                }
 76.1189 -            } else {
 76.1190 -                throw new IllegalStateException(
 76.1191 -                    "Trying to use content for " + al + " but it is already used for " + this.al
 76.1192 -                ); // NOI18N
 76.1193 -            }
 76.1194 -        }
 76.1195 -
 76.1196 -        /** The method to add instance to the lookup with.
 76.1197 -         * @param pair class/instance pair
 76.1198 -         */
 76.1199 -        public final void addPair(Pair<?> pair) {
 76.1200 -            AbstractLookup a = al;
 76.1201 -            Executor e = getExecutor();
 76.1202 -
 76.1203 -            if (a != null || e != null) {
 76.1204 -                a.addPair(pair, e);
 76.1205 -            } else {
 76.1206 -                if (notifyIn == null) {
 76.1207 -                    notifyIn = new ArrayList<Pair>(3);
 76.1208 -                }
 76.1209 -
 76.1210 -                getEarlyPairs().add(pair);
 76.1211 -            }
 76.1212 -        }
 76.1213 -
 76.1214 -        /** Remove instance.
 76.1215 -         * @param pair class/instance pair
 76.1216 -         */
 76.1217 -        public final void removePair(Pair<?> pair) {
 76.1218 -            AbstractLookup a = al;
 76.1219 -            Executor e = getExecutor();
 76.1220 -
 76.1221 -            if (a != null || e != null) {
 76.1222 -                a.removePair(pair, e);
 76.1223 -            } else {
 76.1224 -                if (notifyIn == null) {
 76.1225 -                    notifyIn = new ArrayList<Pair>(3);
 76.1226 -                }
 76.1227 -
 76.1228 -                getEarlyPairs().remove(pair);
 76.1229 -            }
 76.1230 -        }
 76.1231 -
 76.1232 -        /** Changes all pairs in the lookup to new values.
 76.1233 -         * @param c the collection of (Pair) objects
 76.1234 -         */
 76.1235 -        public final void setPairs(Collection<? extends Pair> c) {
 76.1236 -            AbstractLookup a = al;
 76.1237 -            Executor e = getExecutor();
 76.1238 -            
 76.1239 -            if (a != null || e != null) {
 76.1240 -                a.setPairs(c, e);
 76.1241 -            } else {
 76.1242 -                notifyIn = new ArrayList<Pair>(c);
 76.1243 -            }
 76.1244 -        }
 76.1245 -
 76.1246 -        @SuppressWarnings("unchecked")
 76.1247 -        private ArrayList<Pair> getEarlyPairs() {
 76.1248 -            Object o = notifyIn;
 76.1249 -            return o instanceof ArrayList ? (ArrayList<Pair>)o : null;
 76.1250 -        }
 76.1251 -        
 76.1252 -        private Executor getExecutor() {
 76.1253 -            Object o = notifyIn;
 76.1254 -            return o instanceof Executor ? (Executor)o : null;
 76.1255 -        }
 76.1256 -    }
 76.1257 -     // end of Content
 76.1258 -
 76.1259 -    /** Just a holder for index & modified values.
 76.1260 -     */
 76.1261 -    final static class Info extends Object {
 76.1262 -        public int index;
 76.1263 -        public Object transaction;
 76.1264 -
 76.1265 -        public Info(int i, Object t) {
 76.1266 -            index = i;
 76.1267 -            transaction = t;
 76.1268 -        }
 76.1269 -    }
 76.1270 -
 76.1271 -    /** Reference to a result R
 76.1272 -     */
 76.1273 -    static final class ReferenceToResult<T> extends WeakReference<R<T>> implements Runnable {
 76.1274 -        /** next refernece in chain, modified only from AbstractLookup or this */
 76.1275 -        private ReferenceToResult<?> next;
 76.1276 -
 76.1277 -        /** the template for the result */
 76.1278 -        public final Template<T> template;
 76.1279 -
 76.1280 -        /** the lookup we are attached to */
 76.1281 -        public final AbstractLookup lookup;
 76.1282 -
 76.1283 -        /** caches for results */
 76.1284 -        public Object caches;
 76.1285 -
 76.1286 -        /** Creates a weak refernece to a new result R in context of lookup
 76.1287 -         * for given template
 76.1288 -         */
 76.1289 -        private ReferenceToResult(R<T> result, AbstractLookup lookup, Template<T> template) {
 76.1290 -            super(result, activeQueue());
 76.1291 -            this.template = template;
 76.1292 -            this.lookup = lookup;
 76.1293 -            getResult().reference = this;
 76.1294 -        }
 76.1295 -
 76.1296 -        /** Returns the result or null
 76.1297 -         */
 76.1298 -        R<T> getResult() {
 76.1299 -            return get();
 76.1300 -        }
 76.1301 -
 76.1302 -        /** Cleans the reference. Implements Runnable interface, do not call
 76.1303 -         * directly.
 76.1304 -         */
 76.1305 -        public void run() {
 76.1306 -            lookup.cleanUpResult(this.template);
 76.1307 -        }
 76.1308 -
 76.1309 -        /** Clones the reference list to given Storage.
 76.1310 -         * @param storage storage to clone to
 76.1311 -         */
 76.1312 -        public void cloneList(AbstractLookup.Storage<?> storage) {
 76.1313 -            ReferenceIterator it = new ReferenceIterator(this);
 76.1314 -
 76.1315 -            while (it.next()) {
 76.1316 -                ReferenceToResult<?> current = it.current();
 76.1317 -                ReferenceToResult<?> newRef = current.cloneRef();
 76.1318 -                newRef.next = storage.registerReferenceToResult(newRef);
 76.1319 -                newRef.caches = current.caches;
 76.1320 -
 76.1321 -                if (current.caches == current) {
 76.1322 -                    current.getResult().initItems(storage);
 76.1323 -                }
 76.1324 -            }
 76.1325 -        }
 76.1326 -
 76.1327 -        private ReferenceToResult<T> cloneRef() {
 76.1328 -            return new ReferenceToResult<T>(getResult(), lookup, template);
 76.1329 -        }
 76.1330 -    }
 76.1331 -     // end of ReferenceToResult
 76.1332 -
 76.1333 -    /** Supporting class to iterate over linked list of ReferenceToResult
 76.1334 -     * Use:
 76.1335 -     * <PRE>
 76.1336 -     *  ReferenceIterator it = new ReferenceIterator (this.ref);
 76.1337 -     *  while (it.next ()) {
 76.1338 -     *    it.current (): // do some work
 76.1339 -     *  }
 76.1340 -     *  this.ref = it.first (); // remember the first one
 76.1341 -     */
 76.1342 -    static final class ReferenceIterator extends Object {
 76.1343 -        private ReferenceToResult<?> first;
 76.1344 -        private ReferenceToResult<?> current;
 76.1345 -
 76.1346 -        /** hard reference to current result, so it is not GCed meanwhile */
 76.1347 -        private R<?> currentResult;
 76.1348 -
 76.1349 -        /** Initializes the iterator with first reference.
 76.1350 -         */
 76.1351 -        public ReferenceIterator(ReferenceToResult<?> first) {
 76.1352 -            this.first = first;
 76.1353 -        }
 76.1354 -
 76.1355 -        /** Moves the current to next possition */
 76.1356 -        public boolean next() {
 76.1357 -            ReferenceToResult<?> prev;
 76.1358 -            ReferenceToResult<?> ref;
 76.1359 -
 76.1360 -            if (current == null) {
 76.1361 -                ref = first;
 76.1362 -                prev = null;
 76.1363 -            } else {
 76.1364 -                prev = current;
 76.1365 -                ref = current.next;
 76.1366 -            }
 76.1367 -
 76.1368 -            while (ref != null) {
 76.1369 -                R<?> result = ref.get();
 76.1370 -
 76.1371 -                if (result == null) {
 76.1372 -                    if (prev == null) {
 76.1373 -                        // move the head
 76.1374 -                        first = ref.next;
 76.1375 -                    } else {
 76.1376 -                        // skip over this reference
 76.1377 -                        prev.next = ref.next;
 76.1378 -                    }
 76.1379 -
 76.1380 -                    prev = ref;
 76.1381 -                    ref = ref.next;
 76.1382 -                } else {
 76.1383 -                    // we have found next item
 76.1384 -                    currentResult = result;
 76.1385 -                    current = ref;
 76.1386 -
 76.1387 -                    return true;
 76.1388 -                }
 76.1389 -            }
 76.1390 -
 76.1391 -            currentResult = null;
 76.1392 -            current = null;
 76.1393 -
 76.1394 -            return false;
 76.1395 -        }
 76.1396 -
 76.1397 -        /** Access to current reference.
 76.1398 -         */
 76.1399 -        public ReferenceToResult<?> current() {
 76.1400 -            return current;
 76.1401 -        }
 76.1402 -
 76.1403 -        /** Access to reference that is supposed to be the first one.
 76.1404 -         */
 76.1405 -        public ReferenceToResult<?> first() {
 76.1406 -            return first;
 76.1407 -        }
 76.1408 -    }
 76.1409 -
 76.1410 -    /** Signals that a lookup is being modified from a lookup query.
 76.1411 -     *
 76.1412 -     * @author  Jaroslav Tulach
 76.1413 -     */
 76.1414 -    static final class ISE extends IllegalStateException {
 76.1415 -        static final long serialVersionUID = 100L;
 76.1416 -        
 76.1417 -        /** list of jobs to execute. */
 76.1418 -        private java.util.List<Job> jobs;
 76.1419 -
 76.1420 -        /** @param msg message
 76.1421 -         */
 76.1422 -        public ISE(String msg) {
 76.1423 -            super(msg);
 76.1424 -        }
 76.1425 -
 76.1426 -        /** Registers a job to be executed partially out and partially in
 76.1427 -         * the lock over storage.
 76.1428 -         */
 76.1429 -        public void registerJob(Job job) {
 76.1430 -            if (jobs == null) {
 76.1431 -                jobs = new java.util.ArrayList<Job>();
 76.1432 -            }
 76.1433 -
 76.1434 -            jobs.add(job);
 76.1435 -        }
 76.1436 -
 76.1437 -        /** Executes the jobs outside, and then inside a locked session.
 76.1438 -         */
 76.1439 -        public void recover(AbstractLookup lookup) {
 76.1440 -            if (jobs == null) {
 76.1441 -                // no recovery plan, throw itself
 76.1442 -                throw this;
 76.1443 -            }
 76.1444 -
 76.1445 -            for (Job j : jobs) {
 76.1446 -                j.before();
 76.1447 -            }
 76.1448 -
 76.1449 -            AbstractLookup.Storage s = lookup.enterStorage();
 76.1450 -
 76.1451 -            try {
 76.1452 -                for (Job j : jobs) {
 76.1453 -                    j.inside();
 76.1454 -                }
 76.1455 -            } finally {
 76.1456 -                lookup.exitStorage();
 76.1457 -            }
 76.1458 -        }
 76.1459 -
 76.1460 -        /** A job to be executed partially outside and partially inside
 76.1461 -         * the storage lock.
 76.1462 -         */
 76.1463 -        static interface Job {
 76.1464 -            public void before();
 76.1465 -
 76.1466 -            public void inside();
 76.1467 -        }
 76.1468 -    }
 76.1469 -     // end of ISE
 76.1470 -}
    77.1 --- a/openide.util/src/org/openide/util/lookup/ArrayStorage.java	Sat Oct 31 15:06:58 2009 +0100
    77.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.3 @@ -1,477 +0,0 @@
    77.4 -/*
    77.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    77.6 - *
    77.7 - * Copyright 1997-2009 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 - * Contributor(s):
   77.28 - *
   77.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   77.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   77.31 - * Microsystems, Inc. All Rights Reserved.
   77.32 - *
   77.33 - * If you wish your version of this file to be governed by only the CDDL
   77.34 - * or only the GPL Version 2, indicate your decision by adding
   77.35 - * "[Contributor] elects to include this software in this distribution
   77.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   77.37 - * single choice of license, a recipient has the option to distribute
   77.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   77.39 - * to extend the choice of license to its licensees as provided above.
   77.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   77.41 - * Version 2 license, then the option applies only if the new code is
   77.42 - * made subject to such option by the copyright holder.
   77.43 - */
   77.44 -package org.openide.util.lookup;
   77.45 -
   77.46 -import org.openide.util.Lookup;
   77.47 -
   77.48 -
   77.49 -
   77.50 -import java.util.*;
   77.51 -import org.openide.util.lookup.AbstractLookup.Pair;
   77.52 -
   77.53 -
   77.54 -/** ArrayStorage of Pairs from AbstractLookup.
   77.55 - * @author  Jaroslav Tulach
   77.56 - */
   77.57 -final class ArrayStorage extends Object
   77.58 -implements AbstractLookup.Storage<ArrayStorage.Transaction> {
   77.59 -    /** default trashold */
   77.60 -    static final Integer DEFAULT_TRASH = new Integer(11);
   77.61 -
   77.62 -    /** list of items */
   77.63 -    private Object content;
   77.64 -
   77.65 -    /** linked list of refernces to results */
   77.66 -    private transient AbstractLookup.ReferenceToResult<?> results;
   77.67 -
   77.68 -    /** Constructor
   77.69 -     */
   77.70 -    public ArrayStorage() {
   77.71 -        this(DEFAULT_TRASH);
   77.72 -    }
   77.73 -
   77.74 -    /** Constructs new ArrayStorage */
   77.75 -    public ArrayStorage(Integer treshhold) {
   77.76 -        this.content = treshhold;
   77.77 -    }
   77.78 -
   77.79 -    /** Adds an item into the tree.
   77.80 -    * @param item to add
   77.81 -    * @return true if the Item has been added for the first time or false if some other
   77.82 -    *    item equal to this one already existed in the lookup
   77.83 -    */
   77.84 -    public boolean add(AbstractLookup.Pair<?> item, Transaction changed) {
   77.85 -        Object[] arr = changed.current;
   77.86 -
   77.87 -        if (changed.arr == null) {
   77.88 -            // just simple add of one item
   77.89 -            for (int i = 0; i < arr.length; i++) {
   77.90 -                if (arr[i] == null) {
   77.91 -                    arr[i] = item;
   77.92 -                    changed.add(item);
   77.93 -
   77.94 -                    return true;
   77.95 -                }
   77.96 -
   77.97 -                if (arr[i].equals(item)) {
   77.98 -                    // reassign the item number
   77.99 -                    item.setIndex(null, ((AbstractLookup.Pair) arr[i]).getIndex());
  77.100 -
  77.101 -                    // already there, but update it
  77.102 -                    arr[i] = item;
  77.103 -
  77.104 -                    return false;
  77.105 -                }
  77.106 -            }
  77.107 -
  77.108 -            // cannot happen as the beginTransaction ensured we can finish 
  77.109 -            // correctly
  77.110 -            throw new IllegalStateException();
  77.111 -        } else {
  77.112 -            // doing remainAll after that, let Transaction hold the new array
  77.113 -            int newIndex = changed.addPair(item);
  77.114 -
  77.115 -            for (int i = 0; i < arr.length; i++) {
  77.116 -                if (arr[i] == null) {
  77.117 -                    changed.add(item);
  77.118 -
  77.119 -                    return true;
  77.120 -                }
  77.121 -
  77.122 -                if (arr[i].equals(item)) {
  77.123 -                    // already there
  77.124 -                    if (i != newIndex) {
  77.125 -                        // change in index
  77.126 -                        changed.add(item);
  77.127 -
  77.128 -                        return false;
  77.129 -                    } else {
  77.130 -                        // no change
  77.131 -                        return false;
  77.132 -                    }
  77.133 -                }
  77.134 -            }
  77.135 -
  77.136 -            // if not found in the original array
  77.137 -            changed.add(item);
  77.138 -
  77.139 -            return true;
  77.140 -        }
  77.141 -    }
  77.142 -
  77.143 -    /** Removes an item.
  77.144 -    */
  77.145 -    public void remove(AbstractLookup.Pair item, Transaction changed) {
  77.146 -        Object[] arr = changed.current;
  77.147 -        if (arr == null) {
  77.148 -            return;
  77.149 -        }
  77.150 -
  77.151 -        int found = -1;
  77.152 -
  77.153 -        for (int i = 0; i < arr.length;) {
  77.154 -            if (arr[i] == null) {
  77.155 -                // end of task
  77.156 -                return;
  77.157 -            }
  77.158 -
  77.159 -            if ((found == -1) && arr[i].equals(item)) {
  77.160 -                // already there
  77.161 -                Pair<?> p = (Pair<?>)arr[i];
  77.162 -                p.setIndex(null, -1);
  77.163 -                changed.add(p);
  77.164 -                found = i;
  77.165 -            }
  77.166 -
  77.167 -            i++;
  77.168 -
  77.169 -            if (found != -1) {
  77.170 -                if (i < arr.length && !(arr[i] instanceof Integer)) {
  77.171 -                    // moving the array
  77.172 -                    arr[i - 1] = arr[i];
  77.173 -                } else {
  77.174 -                    arr[i - 1] = null;
  77.175 -                }
  77.176 -            }
  77.177 -        }
  77.178 -    }
  77.179 -
  77.180 -    /** Removes all items that are not present in the provided collection.
  77.181 -    * @param retain Pair -> AbstractLookup.Info map
  77.182 -    * @param notify set of Classes that has possibly changed
  77.183 -    */
  77.184 -    public void retainAll(Map retain, Transaction changed) {
  77.185 -        Object[] arr = changed.current;
  77.186 -
  77.187 -        for (int from = 0; from < arr.length; from++) {
  77.188 -            if (!(arr[from] instanceof AbstractLookup.Pair)) {
  77.189 -                // end of content
  77.190 -                break;
  77.191 -            }
  77.192 -
  77.193 -            AbstractLookup.Pair p = (AbstractLookup.Pair) arr[from];
  77.194 -
  77.195 -            AbstractLookup.Info info = (AbstractLookup.Info) retain.get(p);
  77.196 -
  77.197 -            if (info == null) {
  77.198 -                // was removed
  77.199 -
  77.200 -                /*
  77.201 -                if (info != null) {
  77.202 -                if (info.index < arr.length) {
  77.203 -                    newArr[info.index] = p;
  77.204 -                }
  77.205 -
  77.206 -                if (p.getIndex() != info.index) {
  77.207 -                    p.setIndex (null, info.index);
  77.208 -                    changed.add (p);
  77.209 -                }
  77.210 -                } else {
  77.211 -                // removed
  77.212 -                 */
  77.213 -                changed.add(p);
  77.214 -            }
  77.215 -        }
  77.216 -    }
  77.217 -
  77.218 -    /** Queries for instances of given class.
  77.219 -    * @param clazz the class to check
  77.220 -    * @return enumeration of Item
  77.221 -    * @see #unsorted
  77.222 -    */
  77.223 -    public <T> Enumeration<Pair<T>> lookup(final Class<T> clazz) {
  77.224 -        if (content instanceof Object[]) {
  77.225 -            final Enumeration<Object> all = InheritanceTree.arrayEn((Object[]) content);
  77.226 -            class JustPairs implements Enumeration<Pair<T>> {
  77.227 -                private Pair<T> next;
  77.228 -
  77.229 -                @SuppressWarnings("unchecked")
  77.230 -                private Pair<T> findNext() {
  77.231 -                    for (;;) {
  77.232 -                        if (next != null) {
  77.233 -                            return next;
  77.234 -                        }
  77.235 -                        if (!all.hasMoreElements()) {
  77.236 -                            return null;
  77.237 -                        }
  77.238 -                        Object o = all.nextElement();
  77.239 -                        boolean ok;
  77.240 -                        if (o instanceof AbstractLookup.Pair) {
  77.241 -                            ok = (clazz == null) || ((AbstractLookup.Pair<?>) o).instanceOf(clazz);
  77.242 -                        } else {
  77.243 -                            ok = false;
  77.244 -                        }
  77.245 -
  77.246 -                        next = ok ? (Pair<T>) o : null;
  77.247 -                    }
  77.248 -                }
  77.249 -                
  77.250 -                public boolean hasMoreElements() {
  77.251 -                    return findNext() != null;
  77.252 -                }
  77.253 -
  77.254 -                public Pair<T> nextElement() {
  77.255 -                    Pair<T> r = findNext();
  77.256 -                    if (r == null) {
  77.257 -                        throw new NoSuchElementException();
  77.258 -                    }
  77.259 -                    next = null;
  77.260 -                    return r;
  77.261 -                }
  77.262 -            } // end of JustPairs
  77.263 -            return new JustPairs();
  77.264 -        } else {
  77.265 -            return InheritanceTree.emptyEn();
  77.266 -        }
  77.267 -    }
  77.268 -
  77.269 -    /** Associates another result with this storage.
  77.270 -     */
  77.271 -    public AbstractLookup.ReferenceToResult registerReferenceToResult(AbstractLookup.ReferenceToResult<?> newRef) {
  77.272 -        AbstractLookup.ReferenceToResult prev = this.results;
  77.273 -        this.results = newRef;
  77.274 -
  77.275 -        return prev;
  77.276 -    }
  77.277 -
  77.278 -    /** Cleanup the references
  77.279 -     */
  77.280 -    public AbstractLookup.ReferenceToResult cleanUpResult(Lookup.Template<?> templ) {
  77.281 -        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
  77.282 -
  77.283 -        while (it.next()) {
  77.284 -            // empty
  77.285 -        }
  77.286 -
  77.287 -        return this.results = it.first();
  77.288 -    }
  77.289 -
  77.290 -    /** We use a hash set of all modified Pair to handle the transaction */
  77.291 -    public Transaction beginTransaction(int ensure) {
  77.292 -        return new Transaction(ensure, content);
  77.293 -    }
  77.294 -
  77.295 -    /** Extract all results.
  77.296 -     */
  77.297 -    public void endTransaction(Transaction changed, Set<AbstractLookup.R> modified) {
  77.298 -        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
  77.299 -
  77.300 -        if (changed.arr == null) {
  77.301 -            // either add or remove, only check the content of check HashSet
  77.302 -            while (it.next()) {
  77.303 -                AbstractLookup.ReferenceToResult ref = it.current();
  77.304 -                Iterator<Pair<?>> pairs = changed.iterator();
  77.305 -
  77.306 -                while (pairs.hasNext()) {
  77.307 -                    AbstractLookup.Pair p = (AbstractLookup.Pair) pairs.next();
  77.308 -
  77.309 -                    if (AbstractLookup.matches(ref.template, p, true)) {
  77.310 -                        modified.add(ref.getResult());
  77.311 -                    }
  77.312 -                }
  77.313 -            }
  77.314 -        } else {
  77.315 -            // do full check of changes
  77.316 -            while (it.next()) {
  77.317 -                AbstractLookup.ReferenceToResult ref = it.current();
  77.318 -
  77.319 -                int oldIndex = -1;
  77.320 -                int newIndex = -1;
  77.321 -
  77.322 -                for (;;) {
  77.323 -                    oldIndex = findMatching(ref.template, changed.current, oldIndex);
  77.324 -                    newIndex = findMatching(ref.template, changed.arr, newIndex);
  77.325 -
  77.326 -                    if ((oldIndex == -1) && (newIndex == -1)) {
  77.327 -                        break;
  77.328 -                    }
  77.329 -
  77.330 -                    if (
  77.331 -                        (oldIndex == -1) || (newIndex == -1) ||
  77.332 -                            !changed.current[oldIndex].equals(changed.arr[newIndex])
  77.333 -                    ) {
  77.334 -                        modified.add(ref.getResult());
  77.335 -
  77.336 -                        break;
  77.337 -                    }
  77.338 -                }
  77.339 -            }
  77.340 -        }
  77.341 -
  77.342 -        this.results = it.first();
  77.343 -        this.content = changed.newContent(this.content);
  77.344 -    }
  77.345 -
  77.346 -    private static int findMatching(Lookup.Template t, Object[] arr, int from) {
  77.347 -        while (++from < arr.length) {
  77.348 -            if (arr[from] instanceof AbstractLookup.Pair) {
  77.349 -                if (AbstractLookup.matches(t, (AbstractLookup.Pair) arr[from], true)) {
  77.350 -                    return from;
  77.351 -                }
  77.352 -            }
  77.353 -        }
  77.354 -
  77.355 -        return -1;
  77.356 -    }
  77.357 -
  77.358 -    /** HashSet with additional field for new array which is callocated
  77.359 -     * in case we are doing replace to hold all new items.
  77.360 -     */
  77.361 -    static final class Transaction extends HashSet<Pair<?>> {
  77.362 -        /** array with current objects */
  77.363 -        public final Object[] current;
  77.364 -
  77.365 -        /** array with new objects */
  77.366 -        public final Object[] arr;
  77.367 -
  77.368 -        /** number of objects in the array */
  77.369 -        private int cnt;
  77.370 -
  77.371 -        public Transaction(int ensure, Object currentContent) {
  77.372 -            Integer trashold;
  77.373 -            Object[] _arr;
  77.374 -
  77.375 -            if (currentContent instanceof Integer) {
  77.376 -                trashold = (Integer) currentContent;
  77.377 -                _arr = null;
  77.378 -            } else {
  77.379 -                _arr = (Object[]) currentContent;
  77.380 -
  77.381 -                if (_arr[_arr.length - 1] instanceof Integer) {
  77.382 -                    trashold = (Integer) _arr[_arr.length - 1];
  77.383 -                } else {
  77.384 -                    // nowhere to grow we have reached the limit
  77.385 -                    trashold = null;
  77.386 -                }
  77.387 -            }
  77.388 -
  77.389 -            int maxSize = (trashold == null) ? _arr.length : trashold.intValue();
  77.390 -
  77.391 -            if (ensure > maxSize) {
  77.392 -                throw new UnsupportedOperationException();
  77.393 -            }
  77.394 -
  77.395 -            if (ensure == -1) {
  77.396 -                // remove => it is ok
  77.397 -                this.current = currentContent instanceof Integer ? null : (Object[]) currentContent;
  77.398 -                this.arr = null;
  77.399 -
  77.400 -                return;
  77.401 -            }
  77.402 -
  77.403 -            if (ensure == -2) {
  77.404 -                // adding one
  77.405 -                if (_arr == null) {
  77.406 -                    // first time add, let's allocate the array
  77.407 -                    _arr = new Object[2];
  77.408 -                    _arr[1] = trashold;
  77.409 -                } else {
  77.410 -                    if (_arr[_arr.length - 1] instanceof AbstractLookup.Pair) {
  77.411 -                        // we are full
  77.412 -                        throw new UnsupportedOperationException();
  77.413 -                    } else {
  77.414 -                        // ensure we have allocated enough space
  77.415 -                        if (_arr.length < 2 || _arr[_arr.length - 2] != null) {
  77.416 -                            // double the array
  77.417 -                            int newSize = (_arr.length - 1) * 2;
  77.418 -                            
  77.419 -                            if (newSize <= 1) {
  77.420 -                                newSize = 2;
  77.421 -                            }
  77.422 -
  77.423 -                            if (newSize > maxSize) {
  77.424 -                                newSize = maxSize;
  77.425 -
  77.426 -                                if (newSize <= _arr.length) {
  77.427 -                                    // no space to get in
  77.428 -                                    throw new UnsupportedOperationException();
  77.429 -                                }
  77.430 -
  77.431 -                                _arr = new Object[newSize];
  77.432 -                            } else {
  77.433 -                                // still a lot of space
  77.434 -                                _arr = new Object[newSize + 1];
  77.435 -                                _arr[newSize] = trashold;
  77.436 -                            }
  77.437 -
  77.438 -                            // copy content of original array without the last Integer into 
  77.439 -                            // the new one
  77.440 -                            System.arraycopy(currentContent, 0, _arr, 0, ((Object[]) currentContent).length - 1);
  77.441 -                        }
  77.442 -                    }
  77.443 -                }
  77.444 -
  77.445 -                this.current = _arr;
  77.446 -                this.arr = null;
  77.447 -            } else {
  77.448 -                // allocate array for complete replacement
  77.449 -                if (ensure == maxSize) {
  77.450 -                    this.arr = new Object[ensure];
  77.451 -                } else {
  77.452 -                    this.arr = new Object[ensure + 1];
  77.453 -                    this.arr[ensure] = trashold;
  77.454 -                }
  77.455 -
  77.456 -                this.current = (currentContent instanceof Object[]) ? (Object[]) currentContent : new Object[0];
  77.457 -            }
  77.458 -        }
  77.459 -
  77.460 -        public int addPair(AbstractLookup.Pair<?> p) {
  77.461 -            p.setIndex(null, cnt);
  77.462 -            arr[cnt++] = p;
  77.463 -
  77.464 -            return p.getIndex();
  77.465 -        }
  77.466 -
  77.467 -        public Object newContent(Object prev) {
  77.468 -            if (arr == null) {
  77.469 -                if (current == null) {
  77.470 -                    return prev;
  77.471 -                } else {
  77.472 -                    return current;
  77.473 -                }
  77.474 -            } else {
  77.475 -                return arr;
  77.476 -            }
  77.477 -        }
  77.478 -    }
  77.479 -     // end of Transaction
  77.480 -}
    78.1 --- a/openide.util/src/org/openide/util/lookup/DelegatingStorage.java	Sat Oct 31 15:06:58 2009 +0100
    78.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.3 @@ -1,180 +0,0 @@
    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-2006 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 -package org.openide.util.lookup;
   78.45 -
   78.46 -import org.openide.util.Lookup;
   78.47 -
   78.48 -import java.io.*;
   78.49 -
   78.50 -import java.lang.ref.WeakReference;
   78.51 -
   78.52 -import java.util.*;
   78.53 -import org.openide.util.lookup.AbstractLookup.Pair;
   78.54 -
   78.55 -
   78.56 -/** Storages that can switch between another storages.
   78.57 - * @author  Jaroslav Tulach
   78.58 - */
   78.59 -final class DelegatingStorage<Transaction> extends Object
   78.60 -implements Serializable, AbstractLookup.Storage<Transaction> {
   78.61 -    /** object to delegate to */
   78.62 -    private AbstractLookup.Storage<Transaction> delegate;
   78.63 -
   78.64 -    /** thread just accessing the storage */
   78.65 -    private Thread owner;
   78.66 -
   78.67 -    public DelegatingStorage(AbstractLookup.Storage<Transaction> d) {
   78.68 -        this.delegate = d;
   78.69 -        this.owner = Thread.currentThread();
   78.70 -    }
   78.71 -
   78.72 -    /** Never serialize yourself, always put there the delegate */
   78.73 -    public Object writeReplace() {
   78.74 -        return this.delegate;
   78.75 -    }
   78.76 -
   78.77 -    /** Method to check whether there is not multiple access from the same thread.
   78.78 -     */
   78.79 -    public void checkForTreeModification() {
   78.80 -        if (Thread.currentThread() == owner) {
   78.81 -            throw new AbstractLookup.ISE("You are trying to modify lookup from lookup query!"); // NOI18N
   78.82 -        }
   78.83 -    }
   78.84 -
   78.85 -    /** Checks whether we have simple behaviour or complex.
   78.86 -     */
   78.87 -    public static boolean isSimple(AbstractLookup.Storage s) {
   78.88 -        if (s instanceof DelegatingStorage) {
   78.89 -            return ((DelegatingStorage) s).delegate instanceof ArrayStorage;
   78.90 -        } else {
   78.91 -            return s instanceof ArrayStorage;
   78.92 -        }
   78.93 -    }
   78.94 -
   78.95 -    /** Exits from the owners ship of the storage.
   78.96 -     */
   78.97 -    public AbstractLookup.Storage<Transaction> exitDelegate() {
   78.98 -        if (Thread.currentThread() != owner) {
   78.99 -            throw new IllegalStateException("Onwer: " + owner + " caller: " + Thread.currentThread()); // NOI18N
  78.100 -        }
  78.101 -
  78.102 -        AbstractLookup.Storage<Transaction> d = delegate;
  78.103 -        delegate = null;
  78.104 -
  78.105 -        return d;
  78.106 -    }
  78.107 -
  78.108 -    public boolean add(AbstractLookup.Pair<?> item, Transaction transaction) {
  78.109 -        return delegate.add(item, transaction);
  78.110 -    }
  78.111 -
  78.112 -    public void remove(org.openide.util.lookup.AbstractLookup.Pair item, Transaction transaction) {
  78.113 -        delegate.remove(item, transaction);
  78.114 -    }
  78.115 -
  78.116 -    public void retainAll(Map retain, Transaction transaction) {
  78.117 -        delegate.retainAll(retain, transaction);
  78.118 -    }
  78.119 -
  78.120 -    /** A special method to change the backing storage.
  78.121 -     * In fact it is not much typesafe as it changes the
  78.122 -     * type of Transaction but we know that nobody is currently
  78.123 -     * holding a transaction object, so there cannot be inconsitencies.
  78.124 -     */
  78.125 -    @SuppressWarnings("unchecked")
  78.126 -    private void changeDelegate(InheritanceTree st) {
  78.127 -        delegate = (AbstractLookup.Storage<Transaction>)st;
  78.128 -    }
  78.129 -
  78.130 -    public Transaction beginTransaction(int ensure) {
  78.131 -        try {
  78.132 -            return delegate.beginTransaction(ensure);
  78.133 -        } catch (UnsupportedOperationException ex) {
  78.134 -            // let's convert to InheritanceTree
  78.135 -            ArrayStorage arr = (ArrayStorage) delegate;
  78.136 -            InheritanceTree inh = new InheritanceTree();
  78.137 -            changeDelegate(inh);
  78.138 -
  78.139 -            //
  78.140 -            // Copy content
  78.141 -            //
  78.142 -            Enumeration<Pair<Object>> en = arr.lookup(Object.class);
  78.143 -
  78.144 -            while (en.hasMoreElements()) {
  78.145 -                if (!inh.add(en.nextElement(), new ArrayList<Class>())) {
  78.146 -                    throw new IllegalStateException("All objects have to be accepted"); // NOI18N
  78.147 -                }
  78.148 -            }
  78.149 -
  78.150 -            //
  78.151 -            // Copy listeners
  78.152 -            //
  78.153 -            AbstractLookup.ReferenceToResult<?> ref = arr.cleanUpResult(null);
  78.154 -
  78.155 -            if (ref != null) {
  78.156 -                ref.cloneList(inh);
  78.157 -            }
  78.158 -
  78.159 -            // we have added the current content and now we can start transaction
  78.160 -            return delegate.beginTransaction(ensure);
  78.161 -        }
  78.162 -    }
  78.163 -
  78.164 -    public org.openide.util.lookup.AbstractLookup.ReferenceToResult cleanUpResult(
  78.165 -        org.openide.util.Lookup.Template templ
  78.166 -    ) {
  78.167 -        return delegate.cleanUpResult(templ);
  78.168 -    }
  78.169 -
  78.170 -    public void endTransaction(Transaction transaction, Set<AbstractLookup.R> modified) {
  78.171 -        delegate.endTransaction(transaction, modified);
  78.172 -    }
  78.173 -
  78.174 -    public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
  78.175 -        return delegate.lookup(clazz);
  78.176 -    }
  78.177 -
  78.178 -    public org.openide.util.lookup.AbstractLookup.ReferenceToResult registerReferenceToResult(
  78.179 -        org.openide.util.lookup.AbstractLookup.ReferenceToResult newRef
  78.180 -    ) {
  78.181 -        return delegate.registerReferenceToResult(newRef);
  78.182 -    }
  78.183 -}
    79.1 --- a/openide.util/src/org/openide/util/lookup/ExcludingLookup.java	Sat Oct 31 15:06:58 2009 +0100
    79.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.3 @@ -1,428 +0,0 @@
    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-2006 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 -package org.openide.util.lookup;
   79.45 -
   79.46 -import java.lang.ref.Reference;
   79.47 -import java.lang.ref.WeakReference;
   79.48 -import org.openide.util.Lookup;
   79.49 -import org.openide.util.LookupListener;
   79.50 -
   79.51 -import java.util.*;
   79.52 -import org.openide.util.LookupEvent;
   79.53 -
   79.54 -
   79.55 -/** Allows exclusion of certain instances from lookup.
   79.56 - *
   79.57 - * @author Jaroslav Tulach
   79.58 - */
   79.59 -final class ExcludingLookup extends org.openide.util.Lookup {
   79.60 -    /** the other lookup that we delegate to */
   79.61 -    private Lookup delegate;
   79.62 -
   79.63 -    /** classes to exclude (Class[]) or just one class (Class) */
   79.64 -    private Object classes;
   79.65 -
   79.66 -    /**
   79.67 -     * Creates new Result object with supplied instances parameter.
   79.68 -     * @param instances to be used to return from the lookup
   79.69 -     */
   79.70 -    ExcludingLookup(Lookup delegate, Class[] classes) {
   79.71 -        this.delegate = delegate;
   79.72 -
   79.73 -        for (Class c : classes) {
   79.74 -            if (c == null) {
   79.75 -                throw new NullPointerException();
   79.76 -            }
   79.77 -        }
   79.78 -        if (classes.length == 1) {
   79.79 -            this.classes = classes[0];
   79.80 -        } else {
   79.81 -            this.classes = classes;
   79.82 -        }
   79.83 -    }
   79.84 -
   79.85 -    @Override
   79.86 -    public String toString() {
   79.87 -        return "ExcludingLookup: " + delegate + " excludes: " + Arrays.asList(classes()); // NOI18N
   79.88 -    }
   79.89 -
   79.90 -    public <T> Result<T> lookup(Template<T> template) {
   79.91 -        if (template == null) {
   79.92 -            throw new NullPointerException();
   79.93 -        }
   79.94 -
   79.95 -        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
   79.96 -            // empty result
   79.97 -            return Lookup.EMPTY.lookup(template);
   79.98 -        }
   79.99 -
  79.100 -        return new R<T>(template.getType(), delegate.lookup(template));
  79.101 -    }
  79.102 -
  79.103 -    public <T> T lookup(Class<T> clazz) {
  79.104 -        if (areSubclassesOfThisClassAlwaysExcluded(clazz)) {
  79.105 -            return null;
  79.106 -        }
  79.107 -
  79.108 -        T res = delegate.lookup(clazz);
  79.109 -
  79.110 -        if (isObjectAccessible(clazz, res, 0)) {
  79.111 -            return res;
  79.112 -        } else {
  79.113 -            return null;
  79.114 -        }
  79.115 -    }
  79.116 -
  79.117 -    @Override
  79.118 -    public <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
  79.119 -        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
  79.120 -            return null;
  79.121 -        }
  79.122 -
  79.123 -        Lookup.Item<T> retValue = delegate.lookupItem(template);
  79.124 -
  79.125 -        if (isObjectAccessible(template.getType(), retValue, 2)) {
  79.126 -            return retValue;
  79.127 -        } else {
  79.128 -            return null;
  79.129 -        }
  79.130 -    }
  79.131 -
  79.132 -    /** @return true if the instance of class c shall never be returned from this lookup
  79.133 -     */
  79.134 -    private boolean areSubclassesOfThisClassAlwaysExcluded(Class<?> c) {
  79.135 -        Class<?>[] arr = classes();
  79.136 -
  79.137 -        for (int i = 0; i < arr.length; i++) {
  79.138 -            if (arr[i].isAssignableFrom(c)) {
  79.139 -                return true;
  79.140 -            }
  79.141 -        }
  79.142 -
  79.143 -        return false;
  79.144 -    }
  79.145 -
  79.146 -    /** Returns the array of classes this lookup filters.
  79.147 -     */
  79.148 -    final Class<?>[] classes() {
  79.149 -        if (classes instanceof Class[]) {
  79.150 -            return (Class[]) classes;
  79.151 -        } else {
  79.152 -            return new Class[] { (Class) classes };
  79.153 -        }
  79.154 -    }
  79.155 -
  79.156 -    /** Does a check whether two classes are accessible (in the super/sub class)
  79.157 -     * releation ship without walking thru any of the classes mentioned in the
  79.158 -     * barrier.
  79.159 -     */
  79.160 -    private static boolean isAccessible(Class<?>[] barriers, Class<?> from, Class<?> to) {
  79.161 -        if ((to == null) || !from.isAssignableFrom(to)) {
  79.162 -            // no way to reach each other by walking up
  79.163 -            return false;
  79.164 -        }
  79.165 -
  79.166 -        for (int i = 0; i < barriers.length; i++) {
  79.167 -            if (to == barriers[i]) {
  79.168 -                return false;
  79.169 -            }
  79.170 -        }
  79.171 -
  79.172 -        if (from == to) {
  79.173 -            return true;
  79.174 -        }
  79.175 -
  79.176 -        //
  79.177 -        // depth first search
  79.178 -        //
  79.179 -        if (isAccessible(barriers, from, to.getSuperclass())) {
  79.180 -            return true;
  79.181 -        }
  79.182 -
  79.183 -        Class[] interfaces = to.getInterfaces();
  79.184 -
  79.185 -        for (int i = 0; i < interfaces.length; i++) {
  79.186 -            if (isAccessible(barriers, from, interfaces[i])) {
  79.187 -                return true;
  79.188 -            }
  79.189 -        }
  79.190 -
  79.191 -        return false;
  79.192 -    }
  79.193 -
  79.194 -    /** based on type decides whether the class accepts or not anObject
  79.195 -     * @param from the base type of the query
  79.196 -     * @param to depending on value of type either Object, Class or Item
  79.197 -     * @param type 0,1,2 for Object, Class or Item
  79.198 -     * @return true if we can access the to from from by walking around the bariers
  79.199 -     */
  79.200 -    private final boolean isObjectAccessible(Class from, Object to, int type) {
  79.201 -        if (to == null) {
  79.202 -            return false;
  79.203 -        }
  79.204 -
  79.205 -        return isObjectAccessible(classes(), from, to, type);
  79.206 -    }
  79.207 -
  79.208 -    /** based on type decides whether the class accepts or not anObject
  79.209 -     * @param barriers classes to avoid when testing reachability
  79.210 -     * @param from the base type of the query
  79.211 -     * @param to depending on value of type either Object, Class or Item
  79.212 -     * @param type 0,1,2 for Object, Class or Item
  79.213 -     * @return true if we can access the to from from by walking around the bariers
  79.214 -     */
  79.215 -    static final boolean isObjectAccessible(Class[] barriers, Class from, Object to, int type) {
  79.216 -        if (to == null) {
  79.217 -            return false;
  79.218 -        }
  79.219 -
  79.220 -        switch (type) {
  79.221 -        case 0:
  79.222 -            return isAccessible(barriers, from, to.getClass());
  79.223 -
  79.224 -        case 1:
  79.225 -            return isAccessible(barriers, from, (Class) to);
  79.226 -
  79.227 -        case 2: {
  79.228 -            Item item = (Item) to;
  79.229 -
  79.230 -            return isAccessible(barriers, from, item.getType());
  79.231 -        }
  79.232 -
  79.233 -        default:
  79.234 -            throw new IllegalStateException("Type: " + type);
  79.235 -        }
  79.236 -    }
  79.237 -
  79.238 -    /** Filters collection accroding to set of given filters.
  79.239 -     */
  79.240 -    final <E, T extends Collection<E>> T filter(
  79.241 -        Class<?>[] arr, Class<?> from, T c, int type, T prototype
  79.242 -    ) {
  79.243 -        T ret = null;
  79.244 -
  79.245 -
  79.246 -// optimistic strategy expecting we will not need to filter
  79.247 -TWICE: 
  79.248 -        for (;;) {
  79.249 -            Iterator<E> it = c.iterator();
  79.250 -BIG: 
  79.251 -            while (it.hasNext()) {
  79.252 -                E res = it.next();
  79.253 -
  79.254 -                if (!isObjectAccessible(arr, from, res, type)) {
  79.255 -                    if (ret == null) {
  79.256 -                        // we need to restart the scanning again 
  79.257 -                        // as there is an active filter
  79.258 -                        ret = prototype;
  79.259 -                        continue TWICE;
  79.260 -                    }
  79.261 -
  79.262 -                    continue BIG;
  79.263 -                }
  79.264 -
  79.265 -                if (ret != null) {
  79.266 -                    // if we are running the second round from TWICE
  79.267 -                    ret.add(res);
  79.268 -                }
  79.269 -            }
  79.270 -
  79.271 -            // ok, processed
  79.272 -            break TWICE;
  79.273 -        }
  79.274 -
  79.275 -        return (ret != null) ? ret : c;
  79.276 -    }
  79.277 -
  79.278 -    /** Delegating result that filters unwanted items and instances.
  79.279 -     */
  79.280 -    private final class R<T> extends WaitableResult<T> implements LookupListener {
  79.281 -        private Result<T> result;
  79.282 -        private WeakResult<T> weak;
  79.283 -        private Object listeners;
  79.284 -        private Class<?> from;
  79.285 -
  79.286 -        R(Class<?> from, Result<T> delegate) {
  79.287 -            this.from = from;
  79.288 -            this.result = delegate;
  79.289 -            this.weak = new WeakResult<T>(this, delegate);
  79.290 -        }
  79.291 -
  79.292 -        protected void beforeLookup(Template t) {
  79.293 -            if (result instanceof WaitableResult) {
  79.294 -                ((WaitableResult) result).beforeLookup(t);
  79.295 -            }
  79.296 -        }
  79.297 -
  79.298 -        public void addLookupListener(LookupListener l) {
  79.299 -            boolean add;
  79.300 -
  79.301 -            synchronized (this) {
  79.302 -                listeners = AbstractLookup.modifyListenerList(true, l, listeners);
  79.303 -                add = listeners != null;
  79.304 -            }
  79.305 -
  79.306 -            if (add) {
  79.307 -                result.addLookupListener(weak);
  79.308 -            }
  79.309 -        }
  79.310 -
  79.311 -        public void removeLookupListener(LookupListener l) {
  79.312 -            boolean remove;
  79.313 -
  79.314 -            synchronized (this) {
  79.315 -                listeners = AbstractLookup.modifyListenerList(false, l, listeners);
  79.316 -                remove = listeners == null;
  79.317 -            }
  79.318 -
  79.319 -            if (remove) {
  79.320 -                result.removeLookupListener(weak);
  79.321 -            }
  79.322 -        }
  79.323 -
  79.324 -        public Collection<? extends T> allInstances() {
  79.325 -            return openCol(result.allInstances(), 0);
  79.326 -        }
  79.327 -
  79.328 -        private <S> Collection<S> openCol(Collection<S> c, int type) {
  79.329 -            return filter(classes(), from, c, type, new ArrayList<S>(c.size()));
  79.330 -        }
  79.331 -
  79.332 -        @Override
  79.333 -        public Set<Class<? extends T>> allClasses() {
  79.334 -            return filter(classes(), from, result.allClasses(), 1, new HashSet<Class<? extends T>>());
  79.335 -        }
  79.336 -
  79.337 -        @Override
  79.338 -        public Collection<? extends Item<T>> allItems() {
  79.339 -            return openCol(result.allItems(), 2);
  79.340 -        }
  79.341 -
  79.342 -        public void resultChanged(org.openide.util.LookupEvent ev) {
  79.343 -            if (ev.getSource() == result) {
  79.344 -                collectFires(null);
  79.345 -            }
  79.346 -        }
  79.347 -
  79.348 -        protected void collectFires(Collection<Object> evAndListeners) {
  79.349 -            LookupListener[] arr;
  79.350 -
  79.351 -            synchronized (this) {
  79.352 -                if (listeners == null) {
  79.353 -                    return;
  79.354 -                }
  79.355 -
  79.356 -                if (listeners instanceof LookupListener) {
  79.357 -                    arr = new LookupListener[] { (LookupListener) listeners };
  79.358 -                } else {
  79.359 -                    ArrayList<?> l = (ArrayList<?>) listeners;
  79.360 -                    arr = l.toArray(new LookupListener[l.size()]);
  79.361 -                }
  79.362 -            }
  79.363 -
  79.364 -            final LookupListener[] ll = arr;
  79.365 -            final org.openide.util.LookupEvent newev = new org.openide.util.LookupEvent(this);
  79.366 -            AbstractLookup.notifyListeners(ll, newev, evAndListeners);
  79.367 -        }
  79.368 -    } // end of R
  79.369 -    
  79.370 -    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
  79.371 -        private Lookup.Result source;
  79.372 -        private Reference<R<T>> result;
  79.373 -        
  79.374 -        public WeakResult(R<T> r, Lookup.Result<T> s) {
  79.375 -            this.result = new WeakReference<R<T>>(r);
  79.376 -            this.source = s;
  79.377 -        }
  79.378 -        
  79.379 -        protected void beforeLookup(Lookup.Template t) {
  79.380 -            R r = (R)result.get();
  79.381 -            if (r != null) {
  79.382 -                r.beforeLookup(t);
  79.383 -            } else {
  79.384 -                source.removeLookupListener(this);
  79.385 -            }
  79.386 -        }
  79.387 -
  79.388 -        protected void collectFires(Collection<Object> evAndListeners) {
  79.389 -            R<T> r = result.get();
  79.390 -            if (r != null) {
  79.391 -                r.collectFires(evAndListeners);
  79.392 -            } else {
  79.393 -                source.removeLookupListener(this);
  79.394 -            }
  79.395 -        }
  79.396 -
  79.397 -        public void addLookupListener(LookupListener l) {
  79.398 -            assert false;
  79.399 -        }
  79.400 -
  79.401 -        public void removeLookupListener(LookupListener l) {
  79.402 -            assert false;
  79.403 -        }
  79.404 -
  79.405 -        public Collection<T> allInstances() {
  79.406 -            assert false;
  79.407 -            return null;
  79.408 -        }
  79.409 -
  79.410 -        public void resultChanged(LookupEvent ev) {
  79.411 -            R r = (R)result.get();
  79.412 -            if (r != null) {
  79.413 -                r.resultChanged(ev);
  79.414 -            } else {
  79.415 -                source.removeLookupListener(this);
  79.416 -            }
  79.417 -        }
  79.418 -
  79.419 -        @Override
  79.420 -        public Collection<? extends Item<T>> allItems() {
  79.421 -            assert false;
  79.422 -            return null;
  79.423 -        }
  79.424 -
  79.425 -        @Override
  79.426 -        public Set<Class<? extends T>> allClasses() {
  79.427 -            assert false;
  79.428 -            return null;
  79.429 -        }
  79.430 -    } // end of WeakResult
  79.431 -}
    80.1 --- a/openide.util/src/org/openide/util/lookup/InheritanceTree.java	Sat Oct 31 15:06:58 2009 +0100
    80.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.3 @@ -1,1276 +0,0 @@
    80.4 -/*
    80.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    80.6 - *
    80.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    80.8 - *
    80.9 - * The contents of this file are subject to the terms of either the GNU
   80.10 - * General Public License Version 2 only ("GPL") or the Common
   80.11 - * Development and Distribution License("CDDL") (collectively, the
   80.12 - * "License"). You may not use this file except in compliance with the
   80.13 - * License. You can obtain a copy of the License at
   80.14 - * http://www.netbeans.org/cddl-gplv2.html
   80.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   80.16 - * specific language governing permissions and limitations under the
   80.17 - * License.  When distributing the software, include this License Header
   80.18 - * Notice in each file and include the License file at
   80.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   80.20 - * particular file as subject to the "Classpath" exception as provided
   80.21 - * by Sun in the GPL Version 2 section of the License file that
   80.22 - * accompanied this code. If applicable, add the following below the
   80.23 - * License Header, with the fields enclosed by brackets [] replaced by
   80.24 - * your own identifying information:
   80.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   80.26 - *
   80.27 - * Contributor(s):
   80.28 - *
   80.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   80.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   80.31 - * Microsystems, Inc. All Rights Reserved.
   80.32 - *
   80.33 - * If you wish your version of this file to be governed by only the CDDL
   80.34 - * or only the GPL Version 2, indicate your decision by adding
   80.35 - * "[Contributor] elects to include this software in this distribution
   80.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   80.37 - * single choice of license, a recipient has the option to distribute
   80.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   80.39 - * to extend the choice of license to its licensees as provided above.
   80.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   80.41 - * Version 2 license, then the option applies only if the new code is
   80.42 - * made subject to such option by the copyright holder.
   80.43 - */
   80.44 -package org.openide.util.lookup;
   80.45 -
   80.46 -import org.openide.util.Lookup;
   80.47 -import org.openide.util.lookup.AbstractLookup.Pair;
   80.48 -import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
   80.49 -import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
   80.50 -
   80.51 -import java.io.*;
   80.52 -
   80.53 -import java.lang.ref.WeakReference;
   80.54 -
   80.55 -import java.util.*;
   80.56 -
   80.57 -
   80.58 -/** A tree to represent classes with inheritance. Description of the
   80.59 - * data structure by Petr Nejedly:
   80.60 - * <P>
   80.61 - * So pretend I'm Lookup implementation. I've got a bunch of Items (e.g.
   80.62 - * setPairs() method),
   80.63 - * didn't do anything on them yet (no startup penalty) so I know nothing
   80.64 - * about them.
   80.65 - * Then I'll be asked for all instances implementing given interface or a
   80.66 - * class. I surely need
   80.67 - * to check all the Items now, as I don't know anything abou them. I surely
   80.68 - * don't want to call
   80.69 - * Item.getClass() as it will dismiss the whole effort. So all I have is
   80.70 - * Item.instanceOf()
   80.71 - * and I'll call it on every Item. I'll cache results, so the next time
   80.72 - * you'll ask me for
   80.73 - * the same interface/class, I'll answer immediatelly. But what if you ask
   80.74 - * me for another
   80.75 - * interface/class? I'll have to scan all Items for it again, unless I can
   80.76 - * be sure some
   80.77 - * of them can't implement it. The only source of this knowledge are the
   80.78 - * previous questions
   80.79 - * and my rulings on them. Here the algorithm have to be split into two
   80.80 - * paths. If you
   80.81 - * previously asked me for interfaces only, I'll have no hint for
   80.82 - * subsequent queries,
   80.83 - * but if you asked me for a class in history, and then for another class
   80.84 - * and these classes
   80.85 - * are not in inheritance relation (I can check hierarchy of lookup
   80.86 - * arguments, because
   80.87 - * they are already resolved/loaded) I can tell that those returned in
   80.88 - * previous query can't
   80.89 - * implement the newly asked class (they are in different hierarchy branch)
   80.90 - * and I need to
   80.91 - * ask less Items.
   80.92 - * <P>
   80.93 - * So if we use mostly classes for asking for services (and it is a trend
   80.94 - * to use
   80.95 - * abstract classes for this purpose in IDE anyway), this could be usable.
   80.96 - * <P>
   80.97 - * The data structure for separating the Items based on previous queries is
   80.98 - * simple
   80.99 - * tree, with every node tagged with one class. The tree's root is,
  80.100 - * naturally,
  80.101 - * java.lang.Object, is marked invited and initially contains all the
  80.102 - * Items.
  80.103 - * For every class query, the missing part of class hierarchy tree is
  80.104 - * created,
  80.105 - * the node of the class looked up is marked as invited and all Items from
  80.106 - * nearest
  80.107 - * invited parent (sperclass) are dragged to this node. The result are then
  80.108 - * all
  80.109 - * Items from this node and all the nodes deeper in hierarchy. Because it
  80.110 - * may
  80.111 - * be too complicated to walk through the children nodes, the results could
  80.112 - * be
  80.113 - * cached in the map.
  80.114 - * For interface lookup, there is a little hint in reality (interfaces
  80.115 - * and superinterfaces), but it would be harder to exploit it, so we could
  80.116 - * fall-back
  80.117 - * to walking through all the Items and cache results.
  80.118 - *
  80.119 - *
  80.120 - * @author  Jaroslav Tulach
  80.121 - */
  80.122 -final class InheritanceTree extends Object
  80.123 -implements Serializable, AbstractLookup.Storage<ArrayList<Class>> {
  80.124 -    private static final long serialVersionUID = 1L;
  80.125 -
  80.126 -    /** the root item (represents Object) */
  80.127 -    private transient Node object;
  80.128 -
  80.129 -    /** Map of queried interfaces.
  80.130 -     * <p>Type: <code>Map&lt;Class, (Collection&lt;AbstractLookup.Pair&gt; | AbstractLookup.Pair)&gt;</code>
  80.131 -     */
  80.132 -    private transient Map<Class,Object> interfaces;
  80.133 -
  80.134 -    /** Map (Class, ReferenceToResult) of all listeners that are waiting in
  80.135 -     * changes in class Class
  80.136 -     */
  80.137 -    private transient Map<Class,ReferenceToResult> reg;
  80.138 -
  80.139 -    /** Constructor
  80.140 -     */
  80.141 -    public InheritanceTree() {
  80.142 -        object = new Node(java.lang.Object.class);
  80.143 -    }
  80.144 -
  80.145 -    private void writeObject(ObjectOutputStream oos) throws IOException {
  80.146 -        oos.writeObject(object);
  80.147 -
  80.148 -        if (interfaces != null) {
  80.149 -            Iterator it = interfaces.entrySet().iterator();
  80.150 -
  80.151 -            while (it.hasNext()) {
  80.152 -                Map.Entry e = (Map.Entry) it.next();
  80.153 -                Class c = (Class) e.getKey();
  80.154 -                oos.writeObject(c.getName());
  80.155 -
  80.156 -                Object o = e.getValue();
  80.157 -
  80.158 -                if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
  80.159 -                    throw new ClassCastException(String.valueOf(o));
  80.160 -                }
  80.161 -
  80.162 -                oos.writeObject(o);
  80.163 -            }
  80.164 -        }
  80.165 -
  80.166 -        oos.writeObject(null);
  80.167 -    }
  80.168 -
  80.169 -    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
  80.170 -        object = (Node) ois.readObject();
  80.171 -        interfaces = new WeakHashMap<Class,Object>();
  80.172 -
  80.173 -        String clazz;
  80.174 -        ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
  80.175 -
  80.176 -        while ((clazz = (String) ois.readObject()) != null) {
  80.177 -            Object o = ois.readObject();
  80.178 -
  80.179 -            if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) {
  80.180 -                throw new ClassCastException(String.valueOf(o));
  80.181 -            }
  80.182 -
  80.183 -            Class c = Class.forName(clazz, false, l);
  80.184 -            interfaces.put(c, o);
  80.185 -        }
  80.186 -    }
  80.187 -
  80.188 -    /** Adds an item into the tree.
  80.189 -    * @param item to add
  80.190 -    * @return true if the Item has been added for the first time or false if some other
  80.191 -    *    item equal to this one already existed in the lookup
  80.192 -    */
  80.193 -    public boolean add(AbstractLookup.Pair<?> item, ArrayList<Class> affected) {
  80.194 -        Node node = registerClass(object, item);
  80.195 -
  80.196 -        affected.add(node.getType());
  80.197 -
  80.198 -        if (node.assignItem(this, item)) {
  80.199 -            // this is the first item added to n.items
  80.200 -            // ok, we have to test interfaces too
  80.201 -        } else {
  80.202 -            // equal item is already there => stop processing
  80.203 -            return false;
  80.204 -        }
  80.205 -
  80.206 -        boolean registeredAsInterface = registerInterface(item, affected);
  80.207 -
  80.208 -        return registeredAsInterface;
  80.209 -    }
  80.210 -
  80.211 -    /** Removes an item.
  80.212 -    */
  80.213 -    public void remove(AbstractLookup.Pair item, ArrayList<Class> affected) {
  80.214 -        Node n = removeClass(object, item);
  80.215 -
  80.216 -        if (n != null) {
  80.217 -            affected.add(n.getType());
  80.218 -        }
  80.219 -
  80.220 -        removeInterface(item, affected);
  80.221 -    }
  80.222 -
  80.223 -    /** Removes all items that are not present in the provided collection.
  80.224 -    * @param retain collection of Pairs to keep them in
  80.225 -    * @param notify set of Classes that has possibly changed
  80.226 -    */
  80.227 -    public void retainAll(Map retain, ArrayList<Class> notify) {
  80.228 -        retainAllInterface(retain, notify);
  80.229 -        retainAllClasses(object, retain, notify);
  80.230 -    }
  80.231 -
  80.232 -    /** Queries for instances of given class.
  80.233 -    * @param clazz the class to check
  80.234 -    * @return enumeration of Item
  80.235 -    * @see #unsorted
  80.236 -    */
  80.237 -    @SuppressWarnings("unchecked")
  80.238 -    public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
  80.239 -        if ((clazz != null) && clazz.isInterface()) {
  80.240 -            return (Enumeration)searchInterface(clazz);
  80.241 -        } else {
  80.242 -            return (Enumeration)searchClass(object, clazz);
  80.243 -        }
  80.244 -    }
  80.245 -
  80.246 -    /** A method to check whether the enumeration returned from
  80.247 -     * lookup method is sorted or is not
  80.248 -     * @param en enumeration to check
  80.249 -     * @return true if it is unsorted and needs to be sorted to find
  80.250 -     *   pair with smallest index
  80.251 -     */
  80.252 -    public static boolean unsorted(Enumeration en) {
  80.253 -        return en instanceof NeedsSortEnum;
  80.254 -    }
  80.255 -
  80.256 -    /** Prints debug messages.
  80.257 -     * @param out stream to output to
  80.258 -     * @param instances print also instances of the
  80.259 -     */
  80.260 -    public void print(java.io.PrintStream out, boolean instances) {
  80.261 -        printNode(object, "", out, instances); // NOI18N
  80.262 -    }
  80.263 -
  80.264 -    //
  80.265 -    // methods to work on classes which are not interfaces
  80.266 -    //
  80.267 -
  80.268 -    /** Searches the subtree and register the item where necessary.
  80.269 -    * @return the node that should contain the item
  80.270 -    */
  80.271 -    private static Node registerClass(Node n, AbstractLookup.Pair item) {
  80.272 -        if (!n.accepts(item)) {
  80.273 -            return null;
  80.274 -        }
  80.275 -
  80.276 -        if (n.children != null) {
  80.277 -            Iterator it = n.children.iterator();
  80.278 -
  80.279 -            for (;;) {
  80.280 -                Node ch = extractNode(it);
  80.281 -
  80.282 -                if (ch == null) {
  80.283 -                    break;
  80.284 -                }
  80.285 -
  80.286 -                Node result = registerClass(ch, item);
  80.287 -
  80.288 -                if (result != null) {
  80.289 -                    // it is in subclass, in case of classes, it cannot
  80.290 -                    // be any other class
  80.291 -                    return result;
  80.292 -                }
  80.293 -            }
  80.294 -        }
  80.295 -
  80.296 -        // ok, nobody of our subclasses wants the class, I'll take it
  80.297 -        return n;
  80.298 -    }
  80.299 -
  80.300 -    /** Removes the item from the tree of objects.
  80.301 -    * @return most narrow class that this item was removed from
  80.302 -    */
  80.303 -    private static Node removeClass(Node n, AbstractLookup.Pair item) {
  80.304 -        if (!n.accepts(item)) {
  80.305 -            return null;
  80.306 -        }
  80.307 -
  80.308 -        if ((n.items != null) && n.items.remove(item)) {
  80.309 -            // this node really contains the item
  80.310 -            return n;
  80.311 -        }
  80.312 -
  80.313 -        if (n.children != null) {
  80.314 -            Iterator it = n.children.iterator();
  80.315 -
  80.316 -            for (;;) {
  80.317 -                Node ch = extractNode(it);
  80.318 -
  80.319 -                if (ch == null) {
  80.320 -                    break;
  80.321 -                }
  80.322 -
  80.323 -                Node result = removeClass(ch, item);
  80.324 -
  80.325 -                // If the children node was emptied, remove it if possible.
  80.326 -                if (((ch.items == null) || ch.items.isEmpty()) && ((ch.children == null) || ch.children.isEmpty())) {
  80.327 -                    it.remove();
  80.328 -                }
  80.329 -
  80.330 -                if (result != null) {
  80.331 -                    // it is in subclass, in case of classes, it cannot
  80.332 -                    // be any other class
  80.333 -                    return result;
  80.334 -                }
  80.335 -            }
  80.336 -        }
  80.337 -
  80.338 -        // nobody found
  80.339 -        return null;
  80.340 -    }
  80.341 -
  80.342 -    /** Finds a node that represents a class.
  80.343 -    * @param n node to search from
  80.344 -    * @param clazz the clazz to find
  80.345 -    * @return node that represents clazz in the tree or null if the clazz is not
  80.346 -    *    represented under the node n
  80.347 -    */
  80.348 -    private Node classToNode(final Node n, final Class<?> clazz) {
  80.349 -        if (!n.accepts(clazz)) {
  80.350 -            // nothing from us
  80.351 -            return null;
  80.352 -        }
  80.353 -
  80.354 -        if (n.getType() == clazz) {
  80.355 -            // we have found what we need
  80.356 -            return n;
  80.357 -        }
  80.358 -
  80.359 -        if (n.children != null) {
  80.360 -            // have to proceed to children
  80.361 -            Iterator it = n.children.iterator();
  80.362 -
  80.363 -            for (;;) {
  80.364 -                final Node ch = extractNode(it);
  80.365 -
  80.366 -                if (ch == null) {
  80.367 -                    break;
  80.368 -                }
  80.369 -
  80.370 -                Node found = classToNode(ch, clazz);
  80.371 -
  80.372 -                if ((found != null) && ch.deserialized()) {
  80.373 -                    class VerifyJob implements AbstractLookup.ISE.Job {
  80.374 -                        private AbstractLookup.Pair<?>[] pairs;
  80.375 -                        private boolean[] answers;
  80.376 -
  80.377 -                        public VerifyJob(Collection<Pair> items) {
  80.378 -                            if (items != null) {
  80.379 -                                pairs = items.toArray(new AbstractLookup.Pair[0]);
  80.380 -                            }
  80.381 -                        }
  80.382 -
  80.383 -                        public void before() {
  80.384 -                            // make sure the node is converted into deserialized state
  80.385 -                            ch.deserialized();
  80.386 -
  80.387 -                            if (pairs != null) {
  80.388 -                                answers = new boolean[pairs.length];
  80.389 -
  80.390 -                                for (int i = 0; i < pairs.length; i++) {
  80.391 -                                    answers[i] = pairs[i].instanceOf(clazz);
  80.392 -                                }
  80.393 -                            }
  80.394 -                        }
  80.395 -
  80.396 -                        public void inside() {
  80.397 -                            if (pairs != null) {
  80.398 -                                for (int i = 0; i < pairs.length; i++) {
  80.399 -                                    if (answers[i]) {
  80.400 -                                        ch.assignItem(InheritanceTree.this, pairs[i]);
  80.401 -                                        n.items.remove(pairs[i]);
  80.402 -                                    }
  80.403 -                                }
  80.404 -                            }
  80.405 -
  80.406 -                            if (n.children != null) {
  80.407 -                                // consolidate all nodes that represent the same class
  80.408 -                                HashMap<Class,Node> nodes = new HashMap<Class,Node>(n.children.size() * 3);
  80.409 -
  80.410 -                                Iterator child = n.children.iterator();
  80.411 -
  80.412 -                                while (child.hasNext()) {
  80.413 -                                    Node node = extractNode(child);
  80.414 -                                    if (node == null) {
  80.415 -                                        continue;
  80.416 -                                    }
  80.417 -                                    Node prev = nodes.put(node.getType(), node);
  80.418 -
  80.419 -                                    if (prev != null) {
  80.420 -                                        child.remove();
  80.421 -                                        nodes.put(node.getType(), prev);
  80.422 -
  80.423 -                                        // mark as being deserialized
  80.424 -                                        prev.markDeserialized();
  80.425 -
  80.426 -                                        if (prev.children == null) {
  80.427 -                                            prev.children = node.children;
  80.428 -                                        } else {
  80.429 -                                            if (node.children != null) {
  80.430 -                                                prev.children.addAll(node.children);
  80.431 -                                            }
  80.432 -                                        }
  80.433 -
  80.434 -                                        if (node.items != null) {
  80.435 -                                            Iterator items = node.items.iterator();
  80.436 -
  80.437 -                                            while (items.hasNext()) {
  80.438 -                                                AbstractLookup.Pair item = (AbstractLookup.Pair) items.next();
  80.439 -                                                prev.assignItem(InheritanceTree.this, item);
  80.440 -                                            }
  80.441 -                                        }
  80.442 -                                    }
  80.443 -                                }
  80.444 -                            }
  80.445 -                        }
  80.446 -                    }
  80.447 -
  80.448 -                    VerifyJob verify = new VerifyJob(n.items);
  80.449 -
  80.450 -                    try {
  80.451 -                        verify.before();
  80.452 -                    } catch (AbstractLookup.ISE ex) {
  80.453 -                        // mark deserialized again
  80.454 -                        ch.markDeserialized();
  80.455 -                        ex.registerJob(verify);
  80.456 -                        throw ex;
  80.457 -                    }
  80.458 -
  80.459 -                    verify.inside();
  80.460 -
  80.461 -                    found = classToNode(ch, clazz);
  80.462 -                }
  80.463 -
  80.464 -                if (found != null) {
  80.465 -                    // class found in one of subnodes
  80.466 -                    return found;
  80.467 -                }
  80.468 -            }
  80.469 -        }
  80.470 -
  80.471 -        class TwoJobs implements AbstractLookup.ISE.Job {
  80.472 -            private AbstractLookup.Pair[] pairs;
  80.473 -            private boolean[] answers;
  80.474 -            private Node newNode;
  80.475 -
  80.476 -            public void before() {
  80.477 -                // have to create new subnode and possibly reparent one of my own
  80.478 -                // but all changes can be done only if we will not be interrupted from
  80.479 -                // outside - e.g. instanceOf methods will not throw exception
  80.480 -                // first of all let's compute the answers to method instanceOf
  80.481 -                AbstractLookup.Pair[] arr = null;
  80.482 -                boolean[] boolArr = null;
  80.483 -
  80.484 -                if (n.items != null) {
  80.485 -                    arr = new AbstractLookup.Pair[n.items.size()];
  80.486 -                    boolArr = new boolean[n.items.size()];
  80.487 -
  80.488 -                    int i = 0;
  80.489 -                    Iterator<Pair> it = n.items.iterator();
  80.490 -
  80.491 -                    while (it.hasNext()) {
  80.492 -                        AbstractLookup.Pair<?> item = it.next();
  80.493 -                        arr[i] = item;
  80.494 -                        boolArr[i] = item.instanceOf(clazz);
  80.495 -                        i++;
  80.496 -                    }
  80.497 -                }
  80.498 -
  80.499 -                pairs = arr;
  80.500 -                answers = boolArr;
  80.501 -            }
  80.502 -
  80.503 -            public void inside() {
  80.504 -                // test if the query has not chagned since
  80.505 -                if (pairs != null) {
  80.506 -                    if (!Arrays.equals(n.items.toArray(), pairs)) {
  80.507 -                        // ok, let try once more
  80.508 -                        return;
  80.509 -                    }
  80.510 -                }
  80.511 -
  80.512 -                internal();
  80.513 -            }
  80.514 -
  80.515 -            public void internal() {
  80.516 -                ArrayList<Node> reparent = null;
  80.517 -
  80.518 -                if (n.children == null) {
  80.519 -                    n.children = new ArrayList<Node>();
  80.520 -                } else {
  80.521 -                    // scan thru all my nodes if some of them are not a subclass
  80.522 -                    // of clazz => then they would need to become child of newNode
  80.523 -                    Iterator it = n.children.iterator();
  80.524 -
  80.525 -                    for (;;) {
  80.526 -                        Node r = extractNode(it);
  80.527 -
  80.528 -                        if (r == null) {
  80.529 -                            break;
  80.530 -                        }
  80.531 -
  80.532 -                        if (clazz.isAssignableFrom(r.getType())) {
  80.533 -                            if (reparent == null) {
  80.534 -                                reparent = new ArrayList<Node>();
  80.535 -                            }
  80.536 -
  80.537 -                            reparent.add(r);
  80.538 -                            it.remove();
  80.539 -                        }
  80.540 -                    }
  80.541 -                }
  80.542 -
  80.543 -                newNode = new Node(clazz);
  80.544 -                n.children.add(newNode);
  80.545 -
  80.546 -                if (reparent != null) {
  80.547 -                    // reassing reparent node as a child of newNode
  80.548 -                    newNode.children = reparent;
  80.549 -                }
  80.550 -
  80.551 -                // now take all my items that are instances of that class and
  80.552 -                // reasign them
  80.553 -                if (n.items != null) {
  80.554 -                    Iterator it = n.items.iterator();
  80.555 -                    int i = 0;
  80.556 -
  80.557 -                    while (it.hasNext()) {
  80.558 -                        AbstractLookup.Pair item = (AbstractLookup.Pair) it.next();
  80.559 -
  80.560 -                        if (answers[i]) { // answers[i] is precomputed value of item.instanceOf (clazz))
  80.561 -                            it.remove();
  80.562 -                            newNode.assignItem(InheritanceTree.this, pairs[i]);
  80.563 -                        }
  80.564 -
  80.565 -                        i++;
  80.566 -                    }
  80.567 -                }
  80.568 -            }
  80.569 -        }
  80.570 -
  80.571 -        TwoJobs j = new TwoJobs();
  80.572 -
  80.573 -        try {
  80.574 -            j.before();
  80.575 -        } catch (AbstractLookup.ISE ex) {
  80.576 -            // ok, it is not possible to call instanceOf now, let's 
  80.577 -            // schedule it for later
  80.578 -            // so register recovery job 
  80.579 -            ex.registerJob(j);
  80.580 -            throw ex;
  80.581 -        }
  80.582 -
  80.583 -        j.internal();
  80.584 -
  80.585 -        // newNode represents my clazz
  80.586 -        return j.newNode;
  80.587 -    }
  80.588 -
  80.589 -    /** Search for a requested class.
  80.590 -    * @return enumeration of Pair
  80.591 -    */
  80.592 -    private Enumeration<Pair> searchClass(Node n, Class<?> clazz) {
  80.593 -        if (clazz != null) {
  80.594 -            n = classToNode(n, clazz);
  80.595 -        }
  80.596 -
  80.597 -        if (n == null) {
  80.598 -            // not for us
  80.599 -            return emptyEn();
  80.600 -        } else {
  80.601 -            return nodeToEnum(n);
  80.602 -        }
  80.603 -    }
  80.604 -
  80.605 -    /** Retains all classes. Removes nodes which items and children are emptied, works
  80.606 -     * recursivelly from specified root node.
  80.607 -     * @param node root node from which to start to process the tree
  80.608 -     * @param retain a map from (Item, AbstractLookup.Info) that describes which items to retain
  80.609 -     *    and witch integer to assign them
  80.610 -     * @param notify collection of classes will be changed
  80.611 -     * @return <code>true<code> if some items were changed and node items and children are emptied,
  80.612 -     * those nodes, excluding root, will be removed from tree */
  80.613 -    private boolean retainAllClasses(Node node, Map retain, Collection<Class> notify) {
  80.614 -        boolean retained = false;
  80.615 -
  80.616 -        if ((node.items != null) && (retain != null)) {
  80.617 -            Iterator<Pair> it = node.items.iterator();
  80.618 -
  80.619 -            while (it.hasNext()) {
  80.620 -                AbstractLookup.Pair<?> item = it.next();
  80.621 -                AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(item);
  80.622 -
  80.623 -                if (n == null) {
  80.624 -                    // remove this item, it should not be there
  80.625 -                    it.remove();
  80.626 -                    retained = true;
  80.627 -                } else {
  80.628 -                    // change the index
  80.629 -                    if (item.getIndex() != n.index) {
  80.630 -                        item.setIndex(null, n.index);
  80.631 -
  80.632 -                        //                        notify.addAll ((ArrayList)n.transaction);
  80.633 -                    }
  80.634 -                }
  80.635 -            }
  80.636 -
  80.637 -            if (retained && (notify != null)) {
  80.638 -                // type of this node has been changed
  80.639 -                notify.add(node.getType());
  80.640 -            }
  80.641 -        }
  80.642 -
  80.643 -        if (node.children != null) {
  80.644 -            for (Iterator it = node.children.iterator();;) {
  80.645 -                Node ch = extractNode(it);
  80.646 -
  80.647 -                if (ch == null) {
  80.648 -                    break;
  80.649 -                }
  80.650 -
  80.651 -                boolean result = retainAllClasses(ch, retain, notify);
  80.652 -
  80.653 -                if (result) {
  80.654 -                    // The children node was emptied and has no children -> remove it.
  80.655 -                    it.remove();
  80.656 -                }
  80.657 -            }
  80.658 -        }
  80.659 -
  80.660 -        return retained && node.items.isEmpty() && ((node.children == null) || node.children.isEmpty());
  80.661 -    }
  80.662 -
  80.663 -    /** A method that creates enumeration of all items under given node.
  80.664 -     *
  80.665 -     * @param n node to create enumeration for
  80.666 -     * @return enumeration of Pairs
  80.667 -     */
  80.668 -    private static Enumeration<Pair> nodeToEnum(Node n) {
  80.669 -        if (n.children == null) {
  80.670 -            // create a simple enumeration because we do not have children
  80.671 -            Enumeration<Pair> e;
  80.672 -            if (n.items == null) {
  80.673 -                e = emptyEn();
  80.674 -            } else {
  80.675 -                e = Collections.enumeration(n.items);
  80.676 -            }
  80.677 -            return e;
  80.678 -        }
  80.679 -
  80.680 -        // create enumeration of Items
  80.681 -        return new NeedsSortEnum(n);
  80.682 -    }
  80.683 -
  80.684 -    //
  80.685 -    // Methods to work on interfaces
  80.686 -    // 
  80.687 -
  80.688 -    /** Registers an item with interfaces.
  80.689 -    * @param item item to register
  80.690 -    * @param affected list of classes that were affected
  80.691 -    * @return false if similar item has already been registered
  80.692 -    */
  80.693 -    @SuppressWarnings("unchecked")
  80.694 -    private boolean registerInterface(AbstractLookup.Pair<?> item, Collection<Class> affected) {
  80.695 -        if (interfaces == null) {
  80.696 -            return true;
  80.697 -        }
  80.698 -
  80.699 -        Iterator<Map.Entry<Class,Object>> it = interfaces.entrySet().iterator();
  80.700 -
  80.701 -        while (it.hasNext()) {
  80.702 -            Map.Entry<Class,Object> entry = it.next();
  80.703 -            Class<?> iface = entry.getKey();
  80.704 -
  80.705 -            if (item.instanceOf(iface)) {
  80.706 -                Object value = entry.getValue();
  80.707 -
  80.708 -                if (value instanceof Collection) {
  80.709 -                    Collection<Object> set = (Collection<Object>) value;
  80.710 -
  80.711 -                    if (!set.add(item)) {
  80.712 -                        // item is already there, probably (if everything is correct) is registered in 
  80.713 -                        // all other ifaces too, so stop additional testing
  80.714 -                        return false;
  80.715 -                    }
  80.716 -                } else {
  80.717 -                    // there is just one pair right now
  80.718 -                    if (value.equals(item)) {
  80.719 -                        // item is there => stop processing (same as above)
  80.720 -                        return false;
  80.721 -                    }
  80.722 -
  80.723 -                    // otherwise replace the single item with ArrayList
  80.724 -                    ArrayList<Object> ll = new ArrayList<Object>(3);
  80.725 -                    ll.add(value);
  80.726 -                    ll.add(item);
  80.727 -                    entry.setValue(ll);
  80.728 -                }
  80.729 -
  80.730 -                affected.add(iface);
  80.731 -            }
  80.732 -        }
  80.733 -
  80.734 -        return true;
  80.735 -    }
  80.736 -
  80.737 -    /** Removes interface.
  80.738 -    * @param item item to register
  80.739 -    * @param affected list of classes that were affected
  80.740 -    */
  80.741 -    @SuppressWarnings("unchecked")
  80.742 -    private void removeInterface(AbstractLookup.Pair item, Collection affected) {
  80.743 -        if (interfaces == null) {
  80.744 -            return;
  80.745 -        }
  80.746 -
  80.747 -        Iterator it = interfaces.entrySet().iterator();
  80.748 -
  80.749 -        while (it.hasNext()) {
  80.750 -            Map.Entry entry = (Map.Entry) it.next();
  80.751 -            Object value = entry.getValue();
  80.752 -
  80.753 -            if (value instanceof Collection) {
  80.754 -                Collection set = (Collection) value;
  80.755 -
  80.756 -                if (set.remove(item)) {
  80.757 -                    if (set.size() == 1) {
  80.758 -                        // if there is just one item remaining change to single item mode
  80.759 -                        entry.setValue(set.iterator().next());
  80.760 -                    }
  80.761 -
  80.762 -                    // adds the Class the item was register to into affected
  80.763 -                    affected.add(entry.getKey());
  80.764 -                }
  80.765 -            } else {
  80.766 -                // single item value
  80.767 -                if (value.equals(item)) {
  80.768 -                    // Emptied -> remove.
  80.769 -                    it.remove();
  80.770 -
  80.771 -                    affected.add(entry.getKey());
  80.772 -                }
  80.773 -            }
  80.774 -        }
  80.775 -    }
  80.776 -
  80.777 -    /** Retains some items.
  80.778 -    * @param retainItems items to retain and their mapping to index numbers
  80.779 -    *    (AbstractLookup.Pair -> AbstractLookup.Info)
  80.780 -    * @param affected list of classes that were affected
  80.781 -    */
  80.782 -    @SuppressWarnings("unchecked")
  80.783 -    private void retainAllInterface(Map retainItems, Collection affected) {
  80.784 -        if (interfaces == null) {
  80.785 -            return;
  80.786 -        }
  80.787 -
  80.788 -        Iterator it = interfaces.entrySet().iterator();
  80.789 -
  80.790 -        while (it.hasNext()) {
  80.791 -            Map.Entry entry = (Map.Entry) it.next();
  80.792 -            Object value = entry.getValue();
  80.793 -
  80.794 -            HashMap<?,?> retain = new HashMap(retainItems);
  80.795 -
  80.796 -            Iterator elems;
  80.797 -            boolean multi = value instanceof Collection;
  80.798 -
  80.799 -            if (multi) {
  80.800 -                // collection mode
  80.801 -                elems = ((Collection) value).iterator();
  80.802 -            } else {
  80.803 -                // single item mode
  80.804 -                elems = Collections.singleton(value).iterator();
  80.805 -            }
  80.806 -
  80.807 -            boolean changed = false;
  80.808 -            boolean reordered = false;
  80.809 -
  80.810 -            while (elems.hasNext()) {
  80.811 -                AbstractLookup.Pair p = (AbstractLookup.Pair) elems.next();
  80.812 -
  80.813 -                AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(p);
  80.814 -
  80.815 -                if (n == null) {
  80.816 -                    if (multi) {
  80.817 -                        // remove it
  80.818 -                        elems.remove();
  80.819 -                    }
  80.820 -
  80.821 -                    changed = true;
  80.822 -                } else {
  80.823 -                    if (p.getIndex() != n.index) {
  80.824 -                        // improve the index
  80.825 -                        p.setIndex(null, n.index);
  80.826 -
  80.827 -                        //                    affected.addAll ((ArrayList)n.transaction);
  80.828 -                        reordered = true;
  80.829 -                    }
  80.830 -                }
  80.831 -            }
  80.832 -
  80.833 -            if (reordered && value instanceof List) {
  80.834 -                // if reordered, than update the order in the collection
  80.835 -                List l = (List) value;
  80.836 -                Collections.sort(l, ALPairComparator.DEFAULT);
  80.837 -            }
  80.838 -
  80.839 -            if (changed) {
  80.840 -                if (multi) {
  80.841 -                    Collection c = (Collection) value;
  80.842 -
  80.843 -                    if (c.size() == 1) {
  80.844 -                        // back to single item mode
  80.845 -                        entry.setValue(c.iterator().next());
  80.846 -                    }
  80.847 -                } else {
  80.848 -                    // remove in single mode => remove completely
  80.849 -                    it.remove();
  80.850 -                }
  80.851 -
  80.852 -                // adds the Class the item was register to into affected
  80.853 -                affected.add(entry.getKey());
  80.854 -            }
  80.855 -        }
  80.856 -    }
  80.857 -
  80.858 -    /** Searches for a clazz between interfaces.
  80.859 -    * @param clazz class to search for
  80.860 -    * @return enumeration of Items
  80.861 -    */
  80.862 -    @SuppressWarnings("unchecked")
  80.863 -    private Enumeration<Pair> searchInterface(final Class<?> clazz) {
  80.864 -        if (interfaces == null) {
  80.865 -            // first call for interface, only initialize
  80.866 -            interfaces = new WeakHashMap();
  80.867 -        }
  80.868 -
  80.869 -        Object obj = interfaces.get(clazz);
  80.870 -
  80.871 -        if (obj == null) {
  80.872 -            // set of items
  80.873 -            AbstractLookup.Pair one = null;
  80.874 -            ArrayList items = null;
  80.875 -
  80.876 -            Enumeration en = lookup(Object.class);
  80.877 -
  80.878 -            while (en.hasMoreElements()) {
  80.879 -                AbstractLookup.Pair it = (AbstractLookup.Pair) en.nextElement();
  80.880 -
  80.881 -                if (it.instanceOf(clazz)) {
  80.882 -                    // ok, this item implements given clazz
  80.883 -                    if (one == null) {
  80.884 -                        one = it;
  80.885 -                    } else {
  80.886 -                        if (items == null) {
  80.887 -                            items = new ArrayList(3);
  80.888 -                            items.add(one);
  80.889 -                        }
  80.890 -
  80.891 -                        items.add(it);
  80.892 -                    }
  80.893 -                }
  80.894 -            }
  80.895 -
  80.896 -            if ((items == null) && (one != null)) {
  80.897 -                // single item mode
  80.898 -                interfaces.put(clazz, one);
  80.899 -
  80.900 -                return singletonEn(one);
  80.901 -            } else {
  80.902 -                if (items == null) {
  80.903 -                    items = new ArrayList(2);
  80.904 -                }
  80.905 -
  80.906 -                interfaces.put(clazz, items);
  80.907 -
  80.908 -                return Collections.enumeration(items);
  80.909 -            }
  80.910 -        } else {
  80.911 -            if (obj instanceof Collection) {
  80.912 -                return Collections.enumeration((Collection) obj);
  80.913 -            } else {
  80.914 -                // single item mode
  80.915 -                return singletonEn((Pair)obj);
  80.916 -            }
  80.917 -        }
  80.918 -    }
  80.919 -
  80.920 -    /** Extracts a node from an iterator, returning null if no next element found
  80.921 -     */
  80.922 -    private static Node extractNode(Iterator it) {
  80.923 -        while (it.hasNext()) {
  80.924 -            Node n = (Node) it.next();
  80.925 -
  80.926 -            if (n.get() == null) {
  80.927 -                it.remove();
  80.928 -            } else {
  80.929 -                return n;
  80.930 -            }
  80.931 -        }
  80.932 -
  80.933 -        return null;
  80.934 -    }
  80.935 -
  80.936 -    /** Prints debug info about the node.
  80.937 -     * @param n node to print
  80.938 -     * @param sp spaces to add
  80.939 -     * @param out where
  80.940 -     * @param instances print also instances
  80.941 -     */
  80.942 -    private static void printNode(Node n, String sp, java.io.PrintStream out, boolean instances) {
  80.943 -        int i;
  80.944 -        Iterator it;
  80.945 -
  80.946 -        Class type = n.getType();
  80.947 -
  80.948 -        out.print(sp);
  80.949 -        out.println("Node for: " + type + "\t" + ((type == null) ? null : type.getClassLoader())); // NOI18N
  80.950 -
  80.951 -        if (n.items != null) {
  80.952 -            i = 0;
  80.953 -            it = new ArrayList<Pair>(n.items).iterator();
  80.954 -
  80.955 -            while (it.hasNext()) {
  80.956 -                AbstractLookup.Pair p = (AbstractLookup.Pair) it.next();
  80.957 -                out.print(sp);
  80.958 -                out.print("  item (" + i++ + "): ");
  80.959 -                out.print(p); // NOI18N
  80.960 -                out.print(" id: " + Integer.toHexString(System.identityHashCode(p))); // NOI18N
  80.961 -                out.print(" index: "); // NOI18N
  80.962 -                out.print(p.getIndex());
  80.963 -
  80.964 -                if (instances) {
  80.965 -                    out.print(" I: " + p.getInstance());
  80.966 -                }
  80.967 -
  80.968 -                out.println();
  80.969 -            }
  80.970 -        }
  80.971 -
  80.972 -        if (n.children != null) {
  80.973 -            i = 0;
  80.974 -            it = n.children.iterator();
  80.975 -
  80.976 -            while (it.hasNext()) {
  80.977 -                Node ch = (Node) it.next();
  80.978 -                printNode(ch, sp + "  ", out, instances); // NOI18N
  80.979 -            }
  80.980 -        }
  80.981 -    }
  80.982 -
  80.983 -    public ReferenceToResult registerReferenceToResult(ReferenceToResult<?> newRef) {
  80.984 -        if (reg == null) {
  80.985 -            reg = new HashMap<Class,ReferenceToResult>();
  80.986 -        }
  80.987 -
  80.988 -        Class<? extends Object> clazz = newRef.template.getType();
  80.989 -
  80.990 -        // initialize the data structures if not yet
  80.991 -        lookup(clazz);
  80.992 -
  80.993 -        // newRef will be the new head of the list
  80.994 -        return reg.put(clazz, newRef);
  80.995 -    }
  80.996 -
  80.997 -    public ReferenceToResult cleanUpResult(Lookup.Template templ) {
  80.998 -        collectListeners(null, templ.getType());
  80.999 -
 80.1000 -        return (reg == null) ? null : reg.get(templ.getType());
 80.1001 -    }
 80.1002 -
 80.1003 -    public ArrayList<Class> beginTransaction(int ensure) {
 80.1004 -        return new ArrayList<Class>();
 80.1005 -    }
 80.1006 -
 80.1007 -    public void endTransaction(ArrayList<Class> list, Set<AbstractLookup.R> allAffectedResults) {
 80.1008 -        if (list.size() == 1) {
 80.1009 -            // probably the most common case
 80.1010 -            collectListeners(allAffectedResults, list.get(0));
 80.1011 -        } else {
 80.1012 -            Iterator it = list.iterator();
 80.1013 -
 80.1014 -            while (it.hasNext()) {
 80.1015 -                collectListeners(allAffectedResults, (Class) it.next());
 80.1016 -            }
 80.1017 -        }
 80.1018 -    }
 80.1019 -
 80.1020 -    /** Notifies all listeners that are interested in changes in this class.
 80.1021 -     * Should be called from synchronized places.
 80.1022 -     * @param allAffectedResults adds Results into this set
 80.1023 -     * @param c the class that has changed
 80.1024 -     */
 80.1025 -    private void collectListeners(Set<AbstractLookup.R> allAffectedResults, Class c) {
 80.1026 -        if (reg == null) {
 80.1027 -            return;
 80.1028 -        }
 80.1029 -
 80.1030 -        while (c != null) {
 80.1031 -            ReferenceToResult first = reg.get(c);
 80.1032 -            ReferenceIterator it = new ReferenceIterator(first);
 80.1033 -
 80.1034 -            while (it.next()) {
 80.1035 -                AbstractLookup.R result = it.current().getResult();
 80.1036 -
 80.1037 -                if (allAffectedResults != null) {
 80.1038 -                    // add result
 80.1039 -                    allAffectedResults.add(result);
 80.1040 -                }
 80.1041 -            }
 80.1042 -
 80.1043 -            if (first != it.first()) {
 80.1044 -                if (it.first() == null) {
 80.1045 -                    // we do not need have more results on this object
 80.1046 -                    reg.remove(c);
 80.1047 -                } else {
 80.1048 -                    // move the head of the list
 80.1049 -                    reg.put(c, it.first());
 80.1050 -                }
 80.1051 -            }
 80.1052 -
 80.1053 -            c = c.getSuperclass();
 80.1054 -        }
 80.1055 -
 80.1056 -        if (reg.isEmpty()) {
 80.1057 -            // clean up the list of all results if we do not need them anymore
 80.1058 -            reg = null;
 80.1059 -        }
 80.1060 -    }
 80.1061 -
 80.1062 -    /** Node in the tree.
 80.1063 -    */
 80.1064 -    static final class Node extends WeakReference<Class> implements Serializable {
 80.1065 -        static final long serialVersionUID = 3L;
 80.1066 -
 80.1067 -        /** children nodes */
 80.1068 -        public ArrayList<Node> children;
 80.1069 -
 80.1070 -        /** list of items assigned to this node (suspect to be subclasses) */
 80.1071 -        public Collection<Pair> items;
 80.1072 -
 80.1073 -        /** Constructor.
 80.1074 -        */
 80.1075 -        public Node(Class clazz) {
 80.1076 -            super(clazz);
 80.1077 -        }
 80.1078 -
 80.1079 -        /** Returns true if the object was deserialized also clears the serialized flag.
 80.1080 -         * @return true if so.
 80.1081 -         */
 80.1082 -        public boolean deserialized() {
 80.1083 -            if ((items == null) || items instanceof LinkedHashSet) {
 80.1084 -                return false;
 80.1085 -            }
 80.1086 -
 80.1087 -            if (items.isEmpty()) {
 80.1088 -                items = null;
 80.1089 -            } else {
 80.1090 -                items = new LinkedHashSet<Pair>(items);
 80.1091 -            }
 80.1092 -
 80.1093 -            return true;
 80.1094 -        }
 80.1095 -
 80.1096 -        /** Marks this item as being deserialized.
 80.1097 -         */
 80.1098 -        public void markDeserialized() {
 80.1099 -            if (items == null || items == Collections.EMPTY_LIST) {
 80.1100 -                items = Collections.emptyList();
 80.1101 -            } else {
 80.1102 -                items = Collections.synchronizedCollection(items);
 80.1103 -            }
 80.1104 -        }
 80.1105 -
 80.1106 -        /** Getter for the type associated with this node.
 80.1107 -         */
 80.1108 -        public Class<?> getType() {
 80.1109 -            Class<?> c = get();
 80.1110 -
 80.1111 -            // if  garbage collected, then return a garbage
 80.1112 -            return (c == null) ? Void.TYPE : c;
 80.1113 -        }
 80.1114 -
 80.1115 -        /** Checks whether a node can represent an class.
 80.1116 -        */
 80.1117 -        public boolean accepts(Class<?> clazz) {
 80.1118 -            if (getType() == Object.class) {
 80.1119 -                return true;
 80.1120 -            }
 80.1121 -
 80.1122 -            return getType().isAssignableFrom(clazz);
 80.1123 -        }
 80.1124 -
 80.1125 -        /** Checks whether item is instance of this node.
 80.1126 -        */
 80.1127 -        public boolean accepts(AbstractLookup.Pair<?> item) {
 80.1128 -            if (getType() == Object.class) {
 80.1129 -                // Object.class
 80.1130 -                return true;
 80.1131 -            }
 80.1132 -
 80.1133 -            return item.instanceOf(getType());
 80.1134 -        }
 80.1135 -
 80.1136 -        /** Assings an item to this node.
 80.1137 -        * @param item the item
 80.1138 -        * @return true if item has been added as new
 80.1139 -        */
 80.1140 -        public boolean assignItem(InheritanceTree tree, AbstractLookup.Pair<?> item) {
 80.1141 -            if ((items == null) || (items == Collections.EMPTY_LIST)) {
 80.1142 -                items = new LinkedHashSet<Pair>();
 80.1143 -                items.add(item);
 80.1144 -
 80.1145 -                return true;
 80.1146 -            }
 80.1147 -
 80.1148 -            if (items.contains(item)) {
 80.1149 -                Iterator<Pair> it = items.iterator();
 80.1150 -                Pair old;
 80.1151 -                for (;;) {
 80.1152 -                    old = it.next();
 80.1153 -                    if (item.equals(old)) {
 80.1154 -                        break;
 80.1155 -                    }
 80.1156 -                }
 80.1157 -
 80.1158 -                if (old != item) {
 80.1159 -                    // replace the items there
 80.1160 -                    item.setIndex(tree, old.getIndex());
 80.1161 -                }
 80.1162 -
 80.1163 -                it.remove();
 80.1164 -                items.add(item);
 80.1165 -
 80.1166 -                return false;
 80.1167 -            }
 80.1168 -
 80.1169 -            items.add(item);
 80.1170 -
 80.1171 -            return true;
 80.1172 -        }
 80.1173 -
 80.1174 -        private Object writeReplace() {
 80.1175 -            return new R(this);
 80.1176 -        }
 80.1177 -
 80.1178 -        @Override
 80.1179 -        public String toString() {
 80.1180 -            return "Node for " + get();
 80.1181 -        }
 80.1182 -    }
 80.1183 -     // End of class Node.
 80.1184 -
 80.1185 -    private static final class R implements Serializable {
 80.1186 -        static final long serialVersionUID = 1L;
 80.1187 -        private static ClassLoader l;
 80.1188 -        private String clazzName;
 80.1189 -        private transient Class<?> clazz;
 80.1190 -        private ArrayList<Node> children;
 80.1191 -        private Collection<Pair> items;
 80.1192 -
 80.1193 -        public R(Node n) {
 80.1194 -            this.clazzName = n.getType().getName();
 80.1195 -            this.children = n.children;
 80.1196 -
 80.1197 -            if (n.items instanceof LinkedHashSet || (n.items == null)) {
 80.1198 -                this.items = n.items;
 80.1199 -            } else {
 80.1200 -                this.items = new LinkedHashSet<Pair>(n.items);
 80.1201 -            }
 80.1202 -        }
 80.1203 -
 80.1204 -        private void readObject(ObjectInputStream ois)
 80.1205 -        throws IOException, ClassNotFoundException {
 80.1206 -            ois.defaultReadObject();
 80.1207 -
 80.1208 -            if (l == null) {
 80.1209 -                l = Lookup.getDefault().lookup(ClassLoader.class);
 80.1210 -            }
 80.1211 -
 80.1212 -            clazz = Class.forName(clazzName, false, l);
 80.1213 -        }
 80.1214 -
 80.1215 -        private Object readResolve() throws ObjectStreamException {
 80.1216 -            Node n = new Node(clazz);
 80.1217 -            n.children = children;
 80.1218 -            n.items = items;
 80.1219 -            n.markDeserialized();
 80.1220 -
 80.1221 -            return n;
 80.1222 -        }
 80.1223 -    }
 80.1224 -     // end of R
 80.1225 -
 80.1226 -    static Enumeration<Object> arrayEn(Object[] object) {
 80.1227 -        return Collections.enumeration(Arrays.asList(object));
 80.1228 -    }
 80.1229 -    static <T> Enumeration<T> singletonEn(T object) {
 80.1230 -        return Collections.enumeration(Collections.singleton(object));
 80.1231 -    }
 80.1232 -    static <T> Enumeration<T> emptyEn() {
 80.1233 -        return Collections.enumeration(Collections.<T>emptyList());
 80.1234 -    }
 80.1235 -
 80.1236 -    /** Just a marker class to be able to do instanceof and find out
 80.1237 -     * that this enumeration is not sorted
 80.1238 -     */
 80.1239 -    private static final class NeedsSortEnum extends LinkedList<Node>
 80.1240 -    implements Enumeration<Pair> {
 80.1241 -        private Enumeration<Pair> en;
 80.1242 -
 80.1243 -        public NeedsSortEnum(Node n) {
 80.1244 -            add(n);
 80.1245 -        }
 80.1246 -
 80.1247 -        private boolean ensureNext() {
 80.1248 -            for (;;) {
 80.1249 -                if (en != null && en.hasMoreElements()) {
 80.1250 -                    return true;
 80.1251 -                }
 80.1252 -                if (isEmpty()) {
 80.1253 -                    return false;
 80.1254 -                }
 80.1255 -
 80.1256 -                Node n2 = poll();
 80.1257 -                if (n2.children != null) {
 80.1258 -                    addAll(n2.children);
 80.1259 -                }
 80.1260 -
 80.1261 -                if (n2.items != null && !n2.items.isEmpty()) {
 80.1262 -                    en = Collections.enumeration(n2.items);
 80.1263 -                }
 80.1264 -            }
 80.1265 -        }
 80.1266 -
 80.1267 -        public boolean hasMoreElements() {
 80.1268 -            return ensureNext();
 80.1269 -        }
 80.1270 -
 80.1271 -        public Pair nextElement() {
 80.1272 -            if (!ensureNext()) {
 80.1273 -                throw new NoSuchElementException();
 80.1274 -            }
 80.1275 -            return en.nextElement();
 80.1276 -        }
 80.1277 -    }
 80.1278 -     // end of NeedsSortEnum
 80.1279 -}
    81.1 --- a/openide.util/src/org/openide/util/lookup/InstanceContent.java	Sat Oct 31 15:06:58 2009 +0100
    81.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.3 @@ -1,378 +0,0 @@
    81.4 -/*
    81.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    81.6 - *
    81.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    81.8 - *
    81.9 - * The contents of this file are subject to the terms of either the GNU
   81.10 - * General Public License Version 2 only ("GPL") or the Common
   81.11 - * Development and Distribution License("CDDL") (collectively, the
   81.12 - * "License"). You may not use this file except in compliance with the
   81.13 - * License. You can obtain a copy of the License at
   81.14 - * http://www.netbeans.org/cddl-gplv2.html
   81.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   81.16 - * specific language governing permissions and limitations under the
   81.17 - * License.  When distributing the software, include this License Header
   81.18 - * Notice in each file and include the License file at
   81.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   81.20 - * particular file as subject to the "Classpath" exception as provided
   81.21 - * by Sun in the GPL Version 2 section of the License file that
   81.22 - * accompanied this code. If applicable, add the following below the
   81.23 - * License Header, with the fields enclosed by brackets [] replaced by
   81.24 - * your own identifying information:
   81.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   81.26 - *
   81.27 - * Contributor(s):
   81.28 - *
   81.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   81.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   81.31 - * Microsystems, Inc. All Rights Reserved.
   81.32 - *
   81.33 - * If you wish your version of this file to be governed by only the CDDL
   81.34 - * or only the GPL Version 2, indicate your decision by adding
   81.35 - * "[Contributor] elects to include this software in this distribution
   81.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   81.37 - * single choice of license, a recipient has the option to distribute
   81.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   81.39 - * to extend the choice of license to its licensees as provided above.
   81.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   81.41 - * Version 2 license, then the option applies only if the new code is
   81.42 - * made subject to such option by the copyright holder.
   81.43 - */
   81.44 -package org.openide.util.lookup;
   81.45 -
   81.46 -import org.openide.util.lookup.AbstractLookup.Pair;
   81.47 -
   81.48 -import java.lang.ref.WeakReference;
   81.49 -
   81.50 -import java.util.*;
   81.51 -import java.util.concurrent.Executor;
   81.52 -import org.openide.util.Lookup.Item;
   81.53 -
   81.54 -
   81.55 -/** A special content implementation that can be passed to AbstractLookup
   81.56 - * and provides methods for registration of instances and lazy instances.
   81.57 - * <PRE>
   81.58 - *      InstanceContent ic = new InstanceContent ();
   81.59 - *      AbstractLookup al = new AbstractLookup (ic);
   81.60 - *
   81.61 - *      ic.add (new Object ());
   81.62 - *      ic.add (new Dimension (...));
   81.63 - *
   81.64 - *      Dimension theDim = (Dimension)al.lookup (Dimension.class);
   81.65 - * </PRE>
   81.66 - *
   81.67 - * @author  Jaroslav Tulach
   81.68 - *
   81.69 - * @since 1.25
   81.70 - */
   81.71 -public final class InstanceContent extends AbstractLookup.Content {
   81.72 -    /**
   81.73 -     * Create a new, empty content.
   81.74 -     */
   81.75 -    public InstanceContent() {
   81.76 -    }
   81.77 -
   81.78 -    /** Creates a content associated with an executor to handle dispatch
   81.79 -     * of changes.
   81.80 -     * @param notifyIn the executor to notify changes in
   81.81 -     * @since  7.16
   81.82 -     */
   81.83 -    public InstanceContent(Executor notifyIn) {
   81.84 -        super(notifyIn);
   81.85 -    }
   81.86 -    /** The method to add instance to the lookup with.
   81.87 -     * @param inst instance
   81.88 -     */
   81.89 -    public final void add(Object inst) {
   81.90 -        addPair(new SimpleItem<Object>(inst));
   81.91 -    }
   81.92 -
   81.93 -    /** Adds a convertible instance into the lookup. The <code>inst</code>
   81.94 -     * argument is just a key, not the actual value to appear in the lookup.
   81.95 -     * The value will be created on demand, later when it is really needed
   81.96 -     * by calling <code>convertor</code> methods.
   81.97 -     * <p>
   81.98 -     * This method is useful to delay creation of heavy weight objects.
   81.99 -     * Instead just register lightweight key and a convertor.
  81.100 -     * <p>
  81.101 -     * To remove registered object from lookup use {@link #remove(java.lang.Object, org.openide.util.lookup.InstanceContent.Convertor)}
  81.102 -     * with the same arguments.
  81.103 -     *
  81.104 -     * @param inst instance
  81.105 -     * @param conv convertor which postponing an instantiation,
  81.106 -     * if <code>conv==null</code> then the instance is registered directly.
  81.107 -     */
  81.108 -    public final <T,R> void add(T inst, Convertor<T,R> conv) {
  81.109 -        addPair(new ConvertingItem<T,R>(inst, conv));
  81.110 -    }
  81.111 -
  81.112 -    /** Remove instance.
  81.113 -     * @param inst instance
  81.114 -     */
  81.115 -    public final void remove(Object inst) {
  81.116 -        removePair(new SimpleItem<Object>(inst));
  81.117 -    }
  81.118 -
  81.119 -    /** Remove instance added with a convertor.
  81.120 -     * @param inst instance
  81.121 -     * @param conv convertor, if <code>conv==null</code> it is same like
  81.122 -     * remove(Object)
  81.123 -     */
  81.124 -    public final <T,R> void remove(T inst, Convertor<T,R> conv) {
  81.125 -        removePair(new ConvertingItem<T,R>(inst, conv));
  81.126 -    }
  81.127 -
  81.128 -    /** Changes all pairs in the lookup to new values. Converts collection of
  81.129 -     * instances to collection of pairs.
  81.130 -     * @param col the collection of (Item) objects
  81.131 -     * @param conv the convertor to use or null
  81.132 -     */
  81.133 -    public final <T,R> void set(Collection<T> col, Convertor<T,R> conv) {
  81.134 -        ArrayList<Pair<?>> l = new ArrayList<Pair<?>>(col.size());
  81.135 -        Iterator<T> it = col.iterator();
  81.136 -
  81.137 -        if (conv == null) {
  81.138 -            while (it.hasNext()) {
  81.139 -                l.add(new SimpleItem<T>(it.next()));
  81.140 -            }
  81.141 -        } else {
  81.142 -            while (it.hasNext()) {
  81.143 -                l.add(new ConvertingItem<T,R>(it.next(), conv));
  81.144 -            }
  81.145 -        }
  81.146 -
  81.147 -        setPairs(l);
  81.148 -    }
  81.149 -
  81.150 -    /** Convertor postpones an instantiation of an object.
  81.151 -     * @since 1.25
  81.152 -     */
  81.153 -    public static interface Convertor<T,R> {
  81.154 -        /** Convert obj to other object. There is no need to implement
  81.155 -         * cache mechanism. It is provided by
  81.156 -         * {@link Item#getInstance()} method itself. However the
  81.157 -         * method can be called more than once because instance is held
  81.158 -         * just by weak reference.
  81.159 -         *
  81.160 -         * @param obj the registered object
  81.161 -         * @return the object converted from this object
  81.162 -         */
  81.163 -        public R convert(T obj);
  81.164 -
  81.165 -        /** Return type of converted object. Accessible via
  81.166 -         * {@link Item#getType()}
  81.167 -         * @param obj the registered object
  81.168 -         * @return the class that will be produced from this object (class or
  81.169 -         *      superclass of convert (obj))
  81.170 -         */
  81.171 -        public Class<? extends R> type(T obj);
  81.172 -
  81.173 -        /** Computes the ID of the resulted object. Accessible via
  81.174 -         * {@link Item#getId()}.
  81.175 -         * @param obj the registered object
  81.176 -         * @return the ID for the object
  81.177 -         */
  81.178 -        public String id(T obj);
  81.179 -
  81.180 -        /** The human presentable name for the object. Accessible via
  81.181 -         * {@link Item#getDisplayName()}.
  81.182 -         * @param obj the registered object
  81.183 -         * @return the name representing the object for the user
  81.184 -         */
  81.185 -        public String displayName(T obj);
  81.186 -    }
  81.187 -
  81.188 -    /** Instance of one item representing an object.
  81.189 -     */
  81.190 -    final static class SimpleItem<T> extends Pair<T> {
  81.191 -        private T obj;
  81.192 -
  81.193 -        /** Create an item.
  81.194 -         * @obj object to register
  81.195 -         */
  81.196 -        public SimpleItem(T obj) {
  81.197 -            if (obj == null) {
  81.198 -                throw new NullPointerException();
  81.199 -            }
  81.200 -            this.obj = obj;
  81.201 -        }
  81.202 -
  81.203 -        /** Tests whether this item can produce object
  81.204 -         * of class c.
  81.205 -         */
  81.206 -        public boolean instanceOf(Class<?> c) {
  81.207 -            return c.isInstance(obj);
  81.208 -        }
  81.209 -
  81.210 -        /** Get instance of registered object. If convertor is specified then
  81.211 -         *  method InstanceLookup.Convertor.convertor is used and weak reference
  81.212 -         * to converted object is saved.
  81.213 -         * @return the instance of the object.
  81.214 -         */
  81.215 -        public T getInstance() {
  81.216 -            return obj;
  81.217 -        }
  81.218 -
  81.219 -        @Override
  81.220 -        public boolean equals(Object o) {
  81.221 -            if (o instanceof SimpleItem) {
  81.222 -                return obj.equals(((SimpleItem) o).obj);
  81.223 -            } else {
  81.224 -                return false;
  81.225 -            }
  81.226 -        }
  81.227 -
  81.228 -        @Override
  81.229 -        public int hashCode() {
  81.230 -            return obj.hashCode();
  81.231 -        }
  81.232 -
  81.233 -        /** An identity of the item.
  81.234 -         * @return string representing the item, that can be used for
  81.235 -         *   persistance purposes to locate the same item next time
  81.236 -         */
  81.237 -        public String getId() {
  81.238 -            return "IL[" + obj.toString(); // NOI18N
  81.239 -        }
  81.240 -
  81.241 -        /** Getter for display name of the item.
  81.242 -         */
  81.243 -        public String getDisplayName() {
  81.244 -            return obj.toString();
  81.245 -        }
  81.246 -
  81.247 -        /** Method that can test whether an instance of a class has been created
  81.248 -         * by this item.
  81.249 -         *
  81.250 -         * @param obj the instance
  81.251 -         * @return if the item has already create an instance and it is the same
  81.252 -         *  as obj.
  81.253 -         */
  81.254 -        protected boolean creatorOf(Object obj) {
  81.255 -            return obj == this.obj;
  81.256 -        }
  81.257 -
  81.258 -        /** The class of this item.
  81.259 -         * @return the correct class
  81.260 -         */
  81.261 -        @SuppressWarnings("unchecked")
  81.262 -        public Class<? extends T> getType() {
  81.263 -            return (Class<? extends T>)obj.getClass();
  81.264 -        }
  81.265 -    }
  81.266 -     // end of SimpleItem
  81.267 -
  81.268 -    /** Instance of one item registered in the map.
  81.269 -     */
  81.270 -    final static class ConvertingItem<T,R> extends Pair<R> {
  81.271 -        /** registered object */
  81.272 -        private T obj;
  81.273 -
  81.274 -        /** Reference to converted object. */
  81.275 -        private WeakReference<R> ref;
  81.276 -
  81.277 -        /** convertor to use */
  81.278 -        private Convertor<? super T,R> conv;
  81.279 -
  81.280 -        /** Create an item.
  81.281 -         * @obj object to register
  81.282 -         * @conv a convertor, can be <code>null</code>.
  81.283 -         */
  81.284 -        public ConvertingItem(T obj, Convertor<? super T,R> conv) {
  81.285 -            this.obj = obj;
  81.286 -            this.conv = conv;
  81.287 -        }
  81.288 -
  81.289 -        /** Tests whether this item can produce object
  81.290 -         * of class c.
  81.291 -         */
  81.292 -        public boolean instanceOf(Class<?> c) {
  81.293 -            return c.isAssignableFrom(getType());
  81.294 -        }
  81.295 -
  81.296 -        /** Returns converted object or null if obj has not been converted yet
  81.297 -         * or reference was cleared by garbage collector.
  81.298 -         */
  81.299 -        private R getConverted() {
  81.300 -            if (ref == null) {
  81.301 -                return null;
  81.302 -            }
  81.303 -
  81.304 -            return ref.get();
  81.305 -        }
  81.306 -
  81.307 -        /** Get instance of registered object. If convertor is specified then
  81.308 -         *  method InstanceLookup.Convertor.convertor is used and weak reference
  81.309 -         * to converted object is saved.
  81.310 -         * @return the instance of the object.
  81.311 -         */
  81.312 -        public synchronized R getInstance() {
  81.313 -            R converted = getConverted();
  81.314 -
  81.315 -            if (converted == null) {
  81.316 -                converted = conv.convert(obj);
  81.317 -                ref = new WeakReference<R>(converted);
  81.318 -            }
  81.319 -
  81.320 -            return converted;
  81.321 -        }
  81.322 -
  81.323 -        @Override
  81.324 -        public boolean equals(Object o) {
  81.325 -            if (o instanceof ConvertingItem) {
  81.326 -                return obj.equals(((ConvertingItem) o).obj);
  81.327 -            } else {
  81.328 -                return false;
  81.329 -            }
  81.330 -        }
  81.331 -
  81.332 -        @Override
  81.333 -        public int hashCode() {
  81.334 -            return obj.hashCode();
  81.335 -        }
  81.336 -
  81.337 -        /** An identity of the item.
  81.338 -         * @return string representing the item, that can be used for
  81.339 -         *   persistance purposes to locate the same item next time
  81.340 -         */
  81.341 -        public String getId() {
  81.342 -            return conv.id(obj);
  81.343 -        }
  81.344 -
  81.345 -        /** Getter for display name of the item.
  81.346 -         */
  81.347 -        public String getDisplayName() {
  81.348 -            return conv.displayName(obj);
  81.349 -        }
  81.350 -
  81.351 -        /** Method that can test whether an instance of a class has been created
  81.352 -         * by this item.
  81.353 -         *
  81.354 -         * @param obj the instance
  81.355 -         * @return if the item has already create an instance and it is the same
  81.356 -         *  as obj.
  81.357 -         */
  81.358 -        protected boolean creatorOf(Object obj) {
  81.359 -            if (conv == null) {
  81.360 -                return obj == this.obj;
  81.361 -            } else {
  81.362 -                return obj == getConverted();
  81.363 -            }
  81.364 -        }
  81.365 -
  81.366 -        /** The class of this item.
  81.367 -         * @return the correct class
  81.368 -         */
  81.369 -        @SuppressWarnings("unchecked")
  81.370 -        public Class<? extends R> getType() {
  81.371 -            R converted = getConverted();
  81.372 -
  81.373 -            if (converted == null) {
  81.374 -                return conv.type(obj);
  81.375 -            }
  81.376 -
  81.377 -            return (Class<? extends R>)converted.getClass();
  81.378 -        }
  81.379 -    }
  81.380 -     // end of ConvertingItem
  81.381 -}
    82.1 --- a/openide.util/src/org/openide/util/lookup/Lookups.java	Sat Oct 31 15:06:58 2009 +0100
    82.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.3 @@ -1,317 +0,0 @@
    82.4 -/*
    82.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    82.6 - *
    82.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    82.8 - *
    82.9 - * The contents of this file are subject to the terms of either the GNU
   82.10 - * General Public License Version 2 only ("GPL") or the Common
   82.11 - * Development and Distribution License("CDDL") (collectively, the
   82.12 - * "License"). You may not use this file except in compliance with the
   82.13 - * License. You can obtain a copy of the License at
   82.14 - * http://www.netbeans.org/cddl-gplv2.html
   82.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   82.16 - * specific language governing permissions and limitations under the
   82.17 - * License.  When distributing the software, include this License Header
   82.18 - * Notice in each file and include the License file at
   82.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   82.20 - * particular file as subject to the "Classpath" exception as provided
   82.21 - * by Sun in the GPL Version 2 section of the License file that
   82.22 - * accompanied this code. If applicable, add the following below the
   82.23 - * License Header, with the fields enclosed by brackets [] replaced by
   82.24 - * your own identifying information:
   82.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   82.26 - *
   82.27 - * Contributor(s):
   82.28 - *
   82.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   82.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
   82.31 - * Microsystems, Inc. All Rights Reserved.
   82.32 - *
   82.33 - * If you wish your version of this file to be governed by only the CDDL
   82.34 - * or only the GPL Version 2, indicate your decision by adding
   82.35 - * "[Contributor] elects to include this software in this distribution
   82.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   82.37 - * single choice of license, a recipient has the option to distribute
   82.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   82.39 - * to extend the choice of license to its licensees as provided above.
   82.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   82.41 - * Version 2 license, then the option applies only if the new code is
   82.42 - * made subject to such option by the copyright holder.
   82.43 - */
   82.44 -
   82.45 -package org.openide.util.lookup;
   82.46 -
   82.47 -import java.util.Arrays;
   82.48 -import org.netbeans.modules.openide.util.NamedServicesProvider;
   82.49 -import org.openide.util.Lookup;
   82.50 -
   82.51 -/**
   82.52 - * Static factory methods for creating common lookup implementations.
   82.53 - *
   82.54 - * @author David Strupl
   82.55 - * @since 2.21
   82.56 - */
   82.57 -public class Lookups {
   82.58 -
   82.59 -    /** static methods only */
   82.60 -    private Lookups() {}
   82.61 -
   82.62 -    /**
   82.63 -     * Creates a singleton lookup. It means lookup that contains only
   82.64 -     * one object specified via the supplied parameter. The lookup will
   82.65 -     * either return the object or null if the supplied template does
   82.66 -     * not match the class. If the specified argument is null the method
   82.67 -     * will end with NullPointerException.
   82.68 -     * @return Fully initialized lookup object ready to use
   82.69 -     * @throws NullPointerException if the supplied argument is null
   82.70 -     * @since 2.21
   82.71 -     */
   82.72 -    public static Lookup singleton(Object objectToLookup) {
   82.73 -        if (objectToLookup == null) {
   82.74 -            throw new NullPointerException();
   82.75 -        }
   82.76 -
   82.77 -        return new SingletonLookup(objectToLookup);
   82.78 -    }
   82.79 -
   82.80 -    /**
   82.81 -     * Creates a lookup that contains an array of objects specified via the
   82.82 -     * parameter. The resulting lookup is fixed in the following sense: it
   82.83 -     * contains only fixed set of objects passed in by the array parameter.
   82.84 -     * Its contents never changes so registering listeners on such lookup
   82.85 -     * does not have any observable effect (the listeners are never called).
   82.86 -     *
   82.87 -     * @param objectsToLookup list of objects to include
   82.88 -     * @return Fully initialized lookup object ready to use
   82.89 -     * @throws NullPointerException if the supplied argument is null
   82.90 -     * @since 2.21
   82.91 -     *
   82.92 -     */
   82.93 -    public static Lookup fixed(Object... objectsToLookup) {
   82.94 -        if (objectsToLookup == null) {
   82.95 -            throw new NullPointerException();
   82.96 -        }
   82.97 -
   82.98 -        if (objectsToLookup.length == 0) {
   82.99 -            return Lookup.EMPTY;
  82.100 -        }
  82.101 -
  82.102 -        if (objectsToLookup.length == 1) {
  82.103 -            return singleton(objectsToLookup[0]);
  82.104 -        }
  82.105 -
  82.106 -        return new SimpleLookup(Arrays.asList(objectsToLookup));
  82.107 -    }
  82.108 -
  82.109 -    /**
  82.110 -     * Creates a lookup that contains an array of objects specified via the
  82.111 -     * parameter. The resulting lookup is fixed in the following sense: it
  82.112 -     * contains only fixed set of objects passed in by the array parameter.
  82.113 -     * The objects returned from this lookup are converted to real objects
  82.114 -     * before they are returned by the lookup.
  82.115 -     * Its contents never changes so registering listeners on such lookup
  82.116 -     * does not have any observable effect (the listeners are never called).
  82.117 -     *
  82.118 -     * @return Fully initialized lookup object ready to use
  82.119 -     * @throws NullPointerException if the any of the arguments is null
  82.120 -     * @since 2.21
  82.121 -     *
  82.122 -     */
  82.123 -    public static <T,R> Lookup fixed(T[] keys, InstanceContent.Convertor<? super T,R> convertor) {
  82.124 -        if (keys == null) {
  82.125 -            throw new NullPointerException();
  82.126 -        }
  82.127 -
  82.128 -        if (convertor == null) {
  82.129 -            throw new NullPointerException();
  82.130 -        }
  82.131 -
  82.132 -        return new SimpleLookup(Arrays.asList(keys), convertor);
  82.133 -    }
  82.134 -
  82.135 -    /** Creates a lookup that delegates to another one but that one can change
  82.136 -     * from time to time. The returned lookup checks every time somebody calls
  82.137 -     * <code>lookup</code> or <code>lookupItem</code> method whether the
  82.138 -     * provider still returns the same lookup. If not, it updates state of
  82.139 -     * all {@link org.openide.util.Lookup.Result}s 
  82.140 -     * that it created (and that still exists).
  82.141 -     * <P>
  82.142 -     * The user of this method has to implement its provider's <code>getLookup</code>
  82.143 -     * method (must be thread safe and fast, will be called often and from any thread)
  82.144 -     * pass it to this method and use the returned lookup. Whenever the user
  82.145 -     * changes the return value from the <code>getLookup</code> method and wants
  82.146 -     * to notify listeners on the lookup about that it should trigger the event
  82.147 -     * firing, for example by calling <code>lookup.lookup (Object.class)</code>
  82.148 -     * directly on the lookup returned by this method
  82.149 -     * that forces a check of the return value of {@link org.openide.util.Lookup.Provider#getLookup}</code>.
  82.150 -     *
  82.151 -     * @param provider the provider that returns a lookup to delegate to
  82.152 -     * @return lookup delegating to the lookup returned by the provider
  82.153 -     * @since 3.9
  82.154 -     */
  82.155 -    public static Lookup proxy(Lookup.Provider provider) {
  82.156 -        return new SimpleProxyLookup(provider);
  82.157 -    }
  82.158 -
  82.159 -    /** Returns a lookup that implements the JDK1.3 JAR services mechanism and delegates
  82.160 -     * to META-INF/services/name.of.class files.
  82.161 -     * <p>Some extensions to the JAR services specification are implemented:
  82.162 -     * <ol>
  82.163 -     * <li>An entry may be followed by a line of the form <code>#position=<i>integer</i></code>
  82.164 -     *     to specify ordering. (Smaller numbers first, entries with unspecified position last.)
  82.165 -     * <li>A line of the form <code>#-<i>classname</i></code> suppresses an entry registered
  82.166 -     *     in another file, so can be used to supersede one implementation with another.
  82.167 -     * </ol>
  82.168 -     * <p>Note: It is not dynamic - so if you need to change the classloader or JARs,
  82.169 -     * wrap it in a {@link ProxyLookup} and change the delegate when necessary.
  82.170 -     * Existing instances will be kept if the implementation classes are unchanged,
  82.171 -     * so there is "stability" in doing this provided some parent loaders are the same
  82.172 -     * as the previous ones.
  82.173 -     * @since 3.35
  82.174 -     * @see ServiceProvider
  82.175 -     */
  82.176 -    public static Lookup metaInfServices(ClassLoader classLoader) {
  82.177 -        return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N
  82.178 -    }
  82.179 -
  82.180 -    /** Returns a lookup that behaves exactly like {@link #metaInfServices(ClassLoader)}
  82.181 -     * except that it does not read data from <code>META-INF/services/</code>, but instead
  82.182 -     * from the specified prefix.
  82.183 -     * @param classLoader class loader to use for loading
  82.184 -     * @param prefix prefix to prepend to the class name when searching
  82.185 -     * @since 7.9
  82.186 -     */
  82.187 -    public static Lookup metaInfServices(ClassLoader classLoader, String prefix) {
  82.188 -        return new MetaInfServicesLookup(classLoader, prefix);
  82.189 -    }
  82.190 -    
  82.191 -    /** Creates a <q>named</q> lookup.
  82.192 -     * It is a lookup identified by a given path.
  82.193 -     * Two lookups with the same path should have the same content.
  82.194 -     * <p>It is expected that each <q>named</q> lookup
  82.195 -     * will contain a superset of what would be created by:
  82.196 -     * <code>{@linkplain #metaInfServices(ClassLoader,String) metaInfServices}(theRightLoader, "META-INF/namedservices/" + path + "/")</code>
  82.197 -     *
  82.198 -     * <p class="nonnormative">Various environments can add their own
  82.199 -     * extensions to its content. As such
  82.200 -     * {@link Lookups#forPath(java.lang.String)} can combine lookups
  82.201 -     * from several sources. In current NetBeans Runtime Container, two lookups are used:
  82.202 -     * </p>
  82.203 -     * <ul class="nonnormative">
  82.204 -     * <li><code>Lookups.metaInfServices("META-INF/namedservices/" + path)</code></li>
  82.205 -     * <li><code>org.openide.loaders.FolderLookup(path)</code></li>
  82.206 -     * </ul>
  82.207 -     * <p class="nonnormative">
  82.208 -     * Please note that these lookups differ in the way they inspect sub-folders.
  82.209 -     * The first lookup just returns instances from the given path, ignoring
  82.210 -     * sub-folders, the second one retrieves instances from the whole sub-tree.
  82.211 -     * </p>
  82.212 -     * <p>
  82.213 -     * Read more about the <a href="../doc-files/api.html#folderlookup">usage of this method</a>.
  82.214 -     * 
  82.215 -     * @param path the path identifying the lookup, e.g. <code>Projects/Actions</code>
  82.216 -     * @return lookup associated with this path
  82.217 -     * @since 7.9
  82.218 -     */
  82.219 -    public static Lookup forPath(String path) {
  82.220 -        return NamedServicesProvider.find(path);
  82.221 -    }
  82.222 -    
  82.223 -    /** Creates a lookup that wraps another one and filters out instances
  82.224 -     * of specified classes. If you have a lookup and
  82.225 -     * you want to remove all instances of ActionMap you can use:
  82.226 -     * <pre>
  82.227 -     * l = Lookups.exclude(lookup, ActionMap.class);
  82.228 -     * </pre>
  82.229 -     * Then anybody who asks for <code>l.lookup(ActionMap.class)</code> or
  82.230 -     * subclass will get <code>null</code>. Even if the original lookup contains the
  82.231 -     * value.
  82.232 -     * To create empty lookup (well, just an example, otherwise use {@link Lookup#EMPTY}) one could use:
  82.233 -     * <pre>
  82.234 -     * Lookup.exclude(anyLookup, Object.class);
  82.235 -     * </pre>
  82.236 -     * as any instance in any lookup is of type Object and thus would be excluded.
  82.237 -     * <p>
  82.238 -     * The complete behavior can be described as <code>classes</code> being
  82.239 -     * a barrier. For an object not to be excluded, there has to be an inheritance
  82.240 -     * path between the queried class and the actual class of the instance,
  82.241 -     * that is not blocked by any of the excluded classes:
  82.242 -     * <pre>
  82.243 -     * interface A {}
  82.244 -     * interface B {}
  82.245 -     * class C implements A, B {}
  82.246 -     * Object c = new C();
  82.247 -     * Lookup l1 = Lookups.singleton(c);
  82.248 -     * Lookup l2 = Lookups.exclude(l1, A.class);
  82.249 -     * assertNull("A is directly excluded", l2.lookup(A.class));
  82.250 -     * assertEquals("Returns C as A.class is not between B and C", c, l2.lookup(B.class));
  82.251 -     * </pre>
  82.252 -     * For more info check the
  82.253 -     * <a href="http://hg.netbeans.org/main-golden/annotate/4883eaeda744/openide.util/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java">
  82.254 -     * excluding lookup tests</a> and the discussion in issue
  82.255 -     * <a href="http://openide.netbeans.org/issues/show_bug.cgi?id=53058">53058</a>.
  82.256 -     *
  82.257 -     * @param lookup the original lookup that should be filtered
  82.258 -     * @param classes array of classes those instances should be excluded
  82.259 -     * @since 5.4
  82.260 -     */
  82.261 -    public static Lookup exclude(Lookup lookup, Class... classes) {
  82.262 -        return new ExcludingLookup(lookup, classes);
  82.263 -    }
  82.264 -
  82.265 -    /** Creates <code>Lookup.Item</code> representing the instance passed in.
  82.266 -     *
  82.267 -     * @param instance the object for which Lookup.Item should be creted
  82.268 -     * @param id unique identification of the object, for details see {@link org.openide.util.Lookup.Item#getId},
  82.269 -     * can be <code>null</code>
  82.270 -     * @return lookup item representing instance
  82.271 -     * @since 4.8
  82.272 -     */
  82.273 -    public static <T> Lookup.Item<T> lookupItem(T instance, String id) {
  82.274 -        return new LookupItem<T>(instance, id);
  82.275 -    }
  82.276 -
  82.277 -    private static class LookupItem<T> extends Lookup.Item<T> {
  82.278 -        private String id;
  82.279 -        private T instance;
  82.280 -
  82.281 -        public LookupItem(T instance) {
  82.282 -            this(instance, null);
  82.283 -        }
  82.284 -
  82.285 -        public LookupItem(T instance, String id) {
  82.286 -            this.id = id;
  82.287 -            this.instance = instance;
  82.288 -        }
  82.289 -
  82.290 -        public String getDisplayName() {
  82.291 -            return getId();
  82.292 -        }
  82.293 -
  82.294 -        public String getId() {
  82.295 -            return (id == null) ? instance.toString() : id;
  82.296 -        }
  82.297 -
  82.298 -        public T getInstance() {
  82.299 -            return instance;
  82.300 -        }
  82.301 -
  82.302 -        @SuppressWarnings("unchecked")
  82.303 -        public Class<? extends T> getType() {
  82.304 -            return (Class<? extends T>)instance.getClass();
  82.305 -        }
  82.306 -
  82.307 -        public @Override boolean equals(Object object) {
  82.308 -            if (object instanceof LookupItem) {
  82.309 -                return instance == ((LookupItem) object).getInstance();
  82.310 -            }
  82.311 -
  82.312 -            return false;
  82.313 -        }
  82.314 -
  82.315 -        public @Override int hashCode() {
  82.316 -            return instance.hashCode();
  82.317 -        }
  82.318 -    }
  82.319 -     // End of LookupItem class
  82.320 -}
    83.1 --- a/openide.util/src/org/openide/util/lookup/MetaInfServicesLookup.java	Sat Oct 31 15:06:58 2009 +0100
    83.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.3 @@ -1,560 +0,0 @@
    83.4 -/*
    83.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    83.6 - *
    83.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    83.8 - *
    83.9 - * The contents of this file are subject to the terms of either the GNU
   83.10 - * General Public License Version 2 only ("GPL") or the Common
   83.11 - * Development and Distribution License("CDDL") (collectively, the
   83.12 - * "License"). You may not use this file except in compliance with the
   83.13 - * License. You can obtain a copy of the License at
   83.14 - * http://www.netbeans.org/cddl-gplv2.html
   83.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   83.16 - * specific language governing permissions and limitations under the
   83.17 - * License.  When distributing the software, include this License Header
   83.18 - * Notice in each file and include the License file at
   83.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   83.20 - * particular file as subject to the "Classpath" exception as provided
   83.21 - * by Sun in the GPL Version 2 section of the License file that
   83.22 - * accompanied this code. If applicable, add the following below the
   83.23 - * License Header, with the fields enclosed by brackets [] replaced by
   83.24 - * your own identifying information:
   83.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   83.26 - *
   83.27 - * Contributor(s):
   83.28 - *
   83.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   83.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   83.31 - * Microsystems, Inc. All Rights Reserved.
   83.32 - *
   83.33 - * If you wish your version of this file to be governed by only the CDDL
   83.34 - * or only the GPL Version 2, indicate your decision by adding
   83.35 - * "[Contributor] elects to include this software in this distribution
   83.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   83.37 - * single choice of license, a recipient has the option to distribute
   83.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   83.39 - * to extend the choice of license to its licensees as provided above.
   83.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   83.41 - * Version 2 license, then the option applies only if the new code is
   83.42 - * made subject to such option by the copyright holder.
   83.43 - */
   83.44 -
   83.45 -package org.openide.util.lookup;
   83.46 -
   83.47 -import java.io.BufferedReader;
   83.48 -import java.io.IOException;
   83.49 -import java.io.InputStream;
   83.50 -import java.io.InputStreamReader;
   83.51 -import java.lang.ref.Reference;
   83.52 -import java.lang.ref.WeakReference;
   83.53 -import java.lang.reflect.Method;
   83.54 -import java.net.URL;
   83.55 -import java.util.ArrayList;
   83.56 -import java.util.Collection;
   83.57 -import java.util.Enumeration;
   83.58 -import java.util.HashSet;
   83.59 -import java.util.LinkedHashSet;
   83.60 -import java.util.List;
   83.61 -import java.util.Map;
   83.62 -import java.util.WeakHashMap;
   83.63 -import java.util.concurrent.Executor;
   83.64 -import java.util.logging.Level;
   83.65 -import java.util.logging.Logger;
   83.66 -import org.openide.util.Lookup;
   83.67 -import org.openide.util.RequestProcessor;
   83.68 -
   83.69 -/**
   83.70 - * @author Jaroslav Tulach, Jesse Glick
   83.71 - * @see Lookups#metaInfServices(ClassLoader,String)
   83.72 - * @see "#14722"
   83.73 - */
   83.74 -final class MetaInfServicesLookup extends AbstractLookup {
   83.75 -
   83.76 -    private static final Logger LOGGER = Logger.getLogger(MetaInfServicesLookup.class.getName());
   83.77 -    static final Executor RP = new RequestProcessor(MetaInfServicesLookup.class.getName(), 1);
   83.78 -    private static int knownInstancesCount;
   83.79 -    private static final List<Reference<Object>> knownInstances;
   83.80 -    static {
   83.81 -        knownInstances = new ArrayList<Reference<Object>>();
   83.82 -        for (int i = 0; i < 512; i++) {
   83.83 -            knownInstances.add(null);
   83.84 -        }
   83.85 -    }
   83.86 -
   83.87 -    /** A set of all requested classes.
   83.88 -     * Note that classes that we actually succeeded on can never be removed
   83.89 -     * from here because we hold a strong reference to the loader.
   83.90 -     * However we also hold classes which are definitely not loadable by
   83.91 -     * our loader.
   83.92 -     */
   83.93 -    private final Map<Class,Object> classes = new WeakHashMap<Class,Object>();
   83.94 -
   83.95 -    /** class loader to use */
   83.96 -    private final ClassLoader loader;
   83.97 -    /** prefix to prepend */
   83.98 -    private final String prefix;
   83.99 -
  83.100 -    /** Create a lookup reading from a specified classloader.
  83.101 -     */
  83.102 -    public MetaInfServicesLookup(ClassLoader loader, String prefix) {
  83.103 -        this.loader = loader;
  83.104 -        this.prefix = prefix;
  83.105 -
  83.106 -        LOGGER.log(Level.FINE, "Created: {0}", this);
  83.107 -    }
  83.108 -
  83.109 -    @Override
  83.110 -    public String toString() {
  83.111 -        return "MetaInfServicesLookup[" + loader + "]"; // NOI18N
  83.112 -    }
  83.113 -
  83.114 -    /* Tries to load appropriate resources from manifest files.
  83.115 -     */
  83.116 -    @Override
  83.117 -    protected final void beforeLookup(Lookup.Template t) {
  83.118 -        Class c = t.getType();
  83.119 -
  83.120 -        Collection<AbstractLookup.Pair<?>> toAdd = null;
  83.121 -        synchronized (this) {
  83.122 -            if (classes.get(c) == null) { // NOI18N
  83.123 -                toAdd = new ArrayList<Pair<?>>();
  83.124 -            } else {
  83.125 -                // ok, nothing needs to be done
  83.126 -                return;
  83.127 -            }
  83.128 -        }
  83.129 -        if (toAdd != null) {
  83.130 -            search(c, toAdd);
  83.131 -        }
  83.132 -        synchronized (this) {
  83.133 -            if (classes.put(c, "") == null) { // NOI18N
  83.134 -                // Added new class, search for it.
  83.135 -                LinkedHashSet<AbstractLookup.Pair<?>> arr = getPairsAsLHS();
  83.136 -                arr.addAll(toAdd);
  83.137 -                setPairs(arr, RP);
  83.138 -            }
  83.139 -        }
  83.140 -    }
  83.141 -
  83.142 -    /** Finds all pairs and adds them to the collection.
  83.143 -     *
  83.144 -     * @param clazz class to find
  83.145 -     * @param result collection to add Pair to
  83.146 -     */
  83.147 -    private void search(Class<?> clazz, Collection<AbstractLookup.Pair<?>> result) {
  83.148 -        if (LOGGER.isLoggable(Level.FINER)) {
  83.149 -            LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this);
  83.150 -        }
  83.151 -
  83.152 -        String res = prefix + clazz.getName(); // NOI18N
  83.153 -        Enumeration<URL> en;
  83.154 -
  83.155 -        try {
  83.156 -            en = loader.getResources(res);
  83.157 -        } catch (IOException ioe) {
  83.158 -            // do not use ErrorManager because we are in the startup code
  83.159 -            // and ErrorManager might not be ready
  83.160 -            ioe.printStackTrace();
  83.161 -
  83.162 -            return;
  83.163 -        }
  83.164 -
  83.165 -        // Do not create multiple instances in case more than one JAR
  83.166 -        // has the same entry in it (and they load to the same class).
  83.167 -        // Probably would not happen, assuming JARs only list classes
  83.168 -        // they own, but just in case...
  83.169 -        List<Item> foundClasses = new ArrayList<Item>();
  83.170 -        Collection<Class> removeClasses = new ArrayList<Class>();
  83.171 -
  83.172 -        boolean foundOne = false;
  83.173 -
  83.174 -        while (en.hasMoreElements()) {
  83.175 -            if (!foundOne) {
  83.176 -                foundOne = true;
  83.177 -
  83.178 -                // Double-check that in fact we can load the *interface* class.
  83.179 -                // For example, say class I is defined in two JARs, J1 and J2.
  83.180 -                // There is also an implementation M1 defined in J1, and another
  83.181 -                // implementation M2 defined in J2.
  83.182 -                // Classloaders C1 and C2 are made from J1 and J2.
  83.183 -                // A MetaInfServicesLookup is made from C1. Then the user asks to
  83.184 -                // lookup I as loaded from C2. J1 has the services line and lists
  83.185 -                // M1, and we can in fact make it. However it is not of the desired
  83.186 -                // type to be looked up. Don't do this check, which could be expensive,
  83.187 -                // unless we expect to be getting some results, however.
  83.188 -                Class realMcCoy = null;
  83.189 -
  83.190 -                try {
  83.191 -                    realMcCoy = loader.loadClass(clazz.getName());
  83.192 -                } catch (ClassNotFoundException cnfe) {
  83.193 -                    // our loader does not know about it, OK
  83.194 -                }
  83.195 -
  83.196 -                if (realMcCoy != clazz) {
  83.197 -                    // Either the interface class is not available at all in our loader,
  83.198 -                    // or it is not the same version as we expected. Don't provide results.
  83.199 -                    if (LOGGER.isLoggable(Level.WARNING)) {
  83.200 -                        if (realMcCoy != null) {
  83.201 -                            LOGGER.log(Level.WARNING,
  83.202 -                                clazz.getName() + " is not the real McCoy! Actually found it in " +
  83.203 -                                realMcCoy.getClassLoader()
  83.204 -                            ); // NOI18N
  83.205 -                        } else {
  83.206 -                            LOGGER.log(Level.WARNING, clazz.getName() + " could not be found in " + loader); // NOI18N
  83.207 -                        }
  83.208 -                    }
  83.209 -
  83.210 -                    return;
  83.211 -                }
  83.212 -            }
  83.213 -
  83.214 -            URL url = en.nextElement();
  83.215 -            Item currentItem = null;
  83.216 -
  83.217 -            try {
  83.218 -                InputStream is = url.openStream();
  83.219 -
  83.220 -                try {
  83.221 -                    BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N
  83.222 -
  83.223 -                    while (true) {
  83.224 -                        String line = reader.readLine();
  83.225 -
  83.226 -                        if (line == null) {
  83.227 -                            break;
  83.228 -                        }
  83.229 -
  83.230 -                        line = line.trim();
  83.231 -
  83.232 -                        // is it position attribute?
  83.233 -                        if (line.startsWith("#position=")) {
  83.234 -                            if (currentItem == null) {
  83.235 -                                LOGGER.log(Level.WARNING, "Found line '{0}' in {1} but there is no item to associate it with", new Object[] {line, url});
  83.236 -                                continue;
  83.237 -                            }
  83.238 -
  83.239 -                            try {
  83.240 -                                currentItem.position = Integer.parseInt(line.substring(10));
  83.241 -                            } catch (NumberFormatException e) {
  83.242 -                                // do not use ErrorManager because we are in the startup code
  83.243 -                                // and ErrorManager might not be ready
  83.244 -                                e.printStackTrace();
  83.245 -                            }
  83.246 -                        }
  83.247 -
  83.248 -                        if (currentItem != null) {
  83.249 -                            insertItem(currentItem, foundClasses);
  83.250 -                            currentItem = null;
  83.251 -                        }
  83.252 -
  83.253 -                        // Ignore blank lines and comments.
  83.254 -                        if (line.length() == 0) {
  83.255 -                            continue;
  83.256 -                        }
  83.257 -
  83.258 -                        boolean remove = false;
  83.259 -
  83.260 -                        if (line.charAt(0) == '#') {
  83.261 -                            if ((line.length() == 1) || (line.charAt(1) != '-')) {
  83.262 -                                continue;
  83.263 -                            }
  83.264 -
  83.265 -                            // line starting with #- is a sign to remove that class from lookup
  83.266 -                            remove = true;
  83.267 -                            line = line.substring(2);
  83.268 -                        }
  83.269 -
  83.270 -                        Class inst = null;
  83.271 -
  83.272 -                        try {
  83.273 -                            // Most lines are fully-qualified class names.
  83.274 -                            inst = Class.forName(line, false, loader);
  83.275 -                        } catch (ClassNotFoundException cnfe) {
  83.276 -                            if (remove) {
  83.277 -                                // if we are removing somthing and the something
  83.278 -                                // cannot be found it is ok to do nothing
  83.279 -                                continue;
  83.280 -                            } else {
  83.281 -                                // but if we are not removing just rethrow
  83.282 -                                throw cnfe;
  83.283 -                            }
  83.284 -                        }
  83.285 -
  83.286 -                        if (!clazz.isAssignableFrom(inst)) {
  83.287 -                            throw new ClassNotFoundException(clazzToString(inst) + " not a subclass of " + clazzToString(clazz)); // NOI18N
  83.288 -                        }
  83.289 -
  83.290 -                        if (remove) {
  83.291 -                            removeClasses.add(inst);
  83.292 -                        } else {
  83.293 -                            // create new item here, but do not put it into
  83.294 -                            // foundClasses array yet because following line
  83.295 -                            // might specify its position
  83.296 -                            currentItem = new Item();
  83.297 -                            currentItem.clazz = inst;
  83.298 -                        }
  83.299 -                    }
  83.300 -
  83.301 -                    if (currentItem != null) {
  83.302 -                        insertItem(currentItem, foundClasses);
  83.303 -                        currentItem = null;
  83.304 -                    }
  83.305 -                } finally {
  83.306 -                    is.close();
  83.307 -                }
  83.308 -            } catch (ClassNotFoundException ex) {
  83.309 -                LOGGER.log(Level.WARNING, null, ex);
  83.310 -            } catch (IOException ex) {
  83.311 -                LOGGER.log(Level.WARNING, null, ex);
  83.312 -            }
  83.313 -        }
  83.314 -
  83.315 -        LOGGER.log(Level.FINER, "Found impls of {0}: {1} and removed: {2} from: {3}", new Object[] {clazz.getName(), foundClasses, removeClasses, this});
  83.316 -
  83.317 -        foundClasses.removeAll(removeClasses);
  83.318 -
  83.319 -        for (Item item : foundClasses) {
  83.320 -            if (removeClasses.contains(item.clazz)) {
  83.321 -                continue;
  83.322 -            }
  83.323 -
  83.324 -            result.add(new P(item.clazz));
  83.325 -        }
  83.326 -    }
  83.327 -    private static String clazzToString(Class clazz) {
  83.328 -        return clazz.getName() + "@" + clazz.getClassLoader() + ":" + clazz.getProtectionDomain().getCodeSource().getLocation(); // NOI18N
  83.329 -    }
  83.330 -
  83.331 -    /**
  83.332 -     * Insert item to the list according to item.position value.
  83.333 -     */
  83.334 -    private void insertItem(Item item, List<Item> list) {
  83.335 -        // no position? -> add it to the end
  83.336 -        if (item.position == -1) {
  83.337 -            list.add(item);
  83.338 -
  83.339 -            return;
  83.340 -        }
  83.341 -
  83.342 -        int index = -1;
  83.343 -        for (Item i : list) {
  83.344 -            index++;
  83.345 -
  83.346 -            if (i.position == -1) {
  83.347 -                list.add(index, item);
  83.348 -
  83.349 -                return;
  83.350 -            } else {
  83.351 -                if (i.position > item.position) {
  83.352 -                    list.add(index, item);
  83.353 -
  83.354 -                    return;
  83.355 -                }
  83.356 -            }
  83.357 -        }
  83.358 -
  83.359 -        list.add(item);
  83.360 -    }
  83.361 -
  83.362 -    private static class Item {
  83.363 -        private Class clazz;
  83.364 -        private int position = -1;
  83.365 -        @Override
  83.366 -        public String toString() {
  83.367 -            return "MetaInfServicesLookup.Item[" + clazz.getName() + "]"; // NOI18N
  83.368 -        }
  83.369 -    }
  83.370 -
  83.371 -    /** Pair that holds name of a class and maybe the instance.
  83.372 -     */
  83.373 -    private static final class P extends AbstractLookup.Pair<Object> {
  83.374 -        /** May be one of three things:
  83.375 -         * 1. The implementation class which was named in the services file.
  83.376 -         * 2. An instance of it.
  83.377 -         * 3. Null, if creation of the instance resulted in an error.
  83.378 -         */
  83.379 -        private Object object;
  83.380 -
  83.381 -        public P(Class<?> clazz) {
  83.382 -            this.object = clazz;
  83.383 -        }
  83.384 -
  83.385 -        /** Finds the class.
  83.386 -         */
  83.387 -        private Class<? extends Object> clazz() {
  83.388 -            Object o = object;
  83.389 -
  83.390 -            if (o instanceof Class) {
  83.391 -                return (Class<? extends Object>) o;
  83.392 -            } else if (o != null) {
  83.393 -                return o.getClass();
  83.394 -            } else {
  83.395 -                // Broken.
  83.396 -                return Object.class;
  83.397 -            }
  83.398 -        }
  83.399 -
  83.400 -        @Override
  83.401 -        public boolean equals(Object o) {
  83.402 -            if (o instanceof P) {
  83.403 -                return ((P) o).clazz().equals(clazz());
  83.404 -            }
  83.405 -
  83.406 -            return false;
  83.407 -        }
  83.408 -
  83.409 -        @Override
  83.410 -        public int hashCode() {
  83.411 -            return clazz().hashCode();
  83.412 -        }
  83.413 -
  83.414 -        protected boolean instanceOf(Class<?> c) {
  83.415 -            return c.isAssignableFrom(clazz());
  83.416 -        }
  83.417 -
  83.418 -        public Class<?> getType() {
  83.419 -            return clazz();
  83.420 -        }
  83.421 -
  83.422 -        public Object getInstance() {
  83.423 -            Object o = object; // keeping local copy to avoid another
  83.424 -
  83.425 -            // thread to modify it under my hands
  83.426 -            if (o instanceof Class) {
  83.427 -                synchronized (o) { // o is Class and we will not create 
  83.428 -                                   // 2 instances of the same class
  83.429 -
  83.430 -                    try {
  83.431 -                        Class<?> c = ((Class) o);
  83.432 -                        o = null;
  83.433 -
  83.434 -                        synchronized (knownInstances) { // guards only the static cache
  83.435 -                            int size = knownInstances.size();
  83.436 -                            int index = c.hashCode() % size;
  83.437 -                            for (int i = 0; i < size; i++) {
  83.438 -                                Reference<Object> ref = knownInstances.get(index);
  83.439 -                                Object obj = ref == null ? null : ref.get();
  83.440 -                                if (obj == null) {
  83.441 -                                    break;
  83.442 -                                }
  83.443 -                                if (c == obj.getClass()) {
  83.444 -                                    o = obj;
  83.445 -                                    break;
  83.446 -                                }
  83.447 -                                if (++index == size) {
  83.448 -                                    index = 0;
  83.449 -                                }
  83.450 -                            }
  83.451 -                        }
  83.452 -
  83.453 -                        if (o == null) {
  83.454 -                            o = createInstance(c);
  83.455 -
  83.456 -                            synchronized (knownInstances) { // guards only the static cache
  83.457 -                                hashPut(o);
  83.458 -
  83.459 -                                int size = knownInstances.size();
  83.460 -                                if (knownInstancesCount > size * 2 / 3) {
  83.461 -                                    LOGGER.log(Level.CONFIG, "Cache of size {0} is 2/3 full. Rehashing.", size);
  83.462 -                                    HashSet<Reference<Object>> all = new HashSet<Reference<Object>>();
  83.463 -                                    all.addAll(knownInstances);
  83.464 -                                    for (int i = 0; i < size; i++) {
  83.465 -                                        knownInstances.set(i, null);
  83.466 -                                    }
  83.467 -                                    for (int i = 0; i < size; i++) {
  83.468 -                                        knownInstances.add(null);
  83.469 -                                    }
  83.470 -                                    knownInstancesCount = 0;
  83.471 -                                    for (Reference<Object> r : all) {
  83.472 -                                        if (r == null) {
  83.473 -                                            continue;
  83.474 -                                        }
  83.475 -                                        Object instance = r.get();
  83.476 -                                        if (instance == null) {
  83.477 -                                            continue;
  83.478 -                                        }
  83.479 -                                        hashPut(instance);
  83.480 -                                    }
  83.481 -                                }
  83.482 -
  83.483 -                            }
  83.484 -                        }
  83.485 -
  83.486 -                        // Do not assign to instance var unless there is a complete synch
  83.487 -                        // block between the newInstance and this line. Otherwise we could
  83.488 -                        // be assigning a half-constructed instance that another thread
  83.489 -                        // could see and return immediately.
  83.490 -                        object = o;
  83.491 -                    } catch (Exception ex) {
  83.492 -                        LOGGER.log(Level.WARNING, "Cannot create " + object, ex);
  83.493 -                        object = null;
  83.494 -                    } catch (ExceptionInInitializerError x) { // #174055
  83.495 -                        LOGGER.log(Level.WARNING, "Cannot create " + object, x);
  83.496 -                        object = null;
  83.497 -                    }
  83.498 -                }
  83.499 -            }
  83.500 -
  83.501 -            return object;
  83.502 -        }
  83.503 -
  83.504 -        public String getDisplayName() {
  83.505 -            return clazz().getName();
  83.506 -        }
  83.507 -
  83.508 -        public String getId() {
  83.509 -            return clazz().getName();
  83.510 -        }
  83.511 -
  83.512 -        protected boolean creatorOf(Object obj) {
  83.513 -            return obj == object;
  83.514 -        }
  83.515 -
  83.516 -        private static void hashPut(Object o) {
  83.517 -            Class<?> c = o.getClass();
  83.518 -            int size = knownInstances.size();
  83.519 -            int index = c.hashCode() % size;
  83.520 -            for (int i = 0; i < size; i++) {
  83.521 -                Reference<Object> ref = knownInstances.get(index);
  83.522 -                Object obj = ref == null ? null : ref.get();
  83.523 -                if (obj == null) {
  83.524 -                    knownInstances.set(index, new WeakReference<Object>(o));
  83.525 -                    knownInstancesCount++;
  83.526 -                    break;
  83.527 -                }
  83.528 -                if (++index == size) {
  83.529 -                    index = 0;
  83.530 -                }
  83.531 -            }
  83.532 -        }
  83.533 -
  83.534 -        private static boolean findSharedClassObjectSkip;
  83.535 -        private static Method findSharedClassObject;
  83.536 -        /** Basically does c.newInstance(), however the method is complicated
  83.537 -         * with a special behaviour for old and almost obsoleted NetBeans
  83.538 -         * class: SharedClassObject.
  83.539 -         */
  83.540 -        private static Object createInstance(Class<?> c) throws InstantiationException, IllegalAccessException {
  83.541 -            if (!findSharedClassObjectSkip) {
  83.542 -                try {
  83.543 -                    if (findSharedClassObject == null) {
  83.544 -                        Class<?> sco;
  83.545 -                        try {
  83.546 -                            sco = Class.forName("org.openide.util.SharedClassObject"); // NOI18N
  83.547 -                        } catch (ClassNotFoundException ex) {
  83.548 -                            findSharedClassObjectSkip = true;
  83.549 -                            return c.newInstance();
  83.550 -                        }
  83.551 -                        findSharedClassObject = sco.getMethod("findObject", Class.class, boolean.class);
  83.552 -                    }
  83.553 -                    if (findSharedClassObject.getReturnType().isAssignableFrom(c)) {
  83.554 -                        return findSharedClassObject.invoke(null, c, true);
  83.555 -                    }
  83.556 -                } catch (Exception problem) {
  83.557 -                    throw (InstantiationException)new InstantiationException(problem.getMessage()).initCause(problem);
  83.558 -                }
  83.559 -            }
  83.560 -            return c.newInstance();
  83.561 -        }
  83.562 -    }
  83.563 -}
    84.1 --- a/openide.util/src/org/openide/util/lookup/ProxyLookup.java	Sat Oct 31 15:06:58 2009 +0100
    84.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.3 @@ -1,969 +0,0 @@
    84.4 -/*
    84.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    84.6 - *
    84.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    84.8 - *
    84.9 - * The contents of this file are subject to the terms of either the GNU
   84.10 - * General Public License Version 2 only ("GPL") or the Common
   84.11 - * Development and Distribution License("CDDL") (collectively, the
   84.12 - * "License"). You may not use this file except in compliance with the
   84.13 - * License. You can obtain a copy of the License at
   84.14 - * http://www.netbeans.org/cddl-gplv2.html
   84.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   84.16 - * specific language governing permissions and limitations under the
   84.17 - * License.  When distributing the software, include this License Header
   84.18 - * Notice in each file and include the License file at
   84.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   84.20 - * particular file as subject to the "Classpath" exception as provided
   84.21 - * by Sun in the GPL Version 2 section of the License file that
   84.22 - * accompanied this code. If applicable, add the following below the
   84.23 - * License Header, with the fields enclosed by brackets [] replaced by
   84.24 - * your own identifying information:
   84.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   84.26 - *
   84.27 - * Contributor(s):
   84.28 - *
   84.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   84.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   84.31 - * Microsystems, Inc. All Rights Reserved.
   84.32 - *
   84.33 - * If you wish your version of this file to be governed by only the CDDL
   84.34 - * or only the GPL Version 2, indicate your decision by adding
   84.35 - * "[Contributor] elects to include this software in this distribution
   84.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   84.37 - * single choice of license, a recipient has the option to distribute
   84.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   84.39 - * to extend the choice of license to its licensees as provided above.
   84.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   84.41 - * Version 2 license, then the option applies only if the new code is
   84.42 - * made subject to such option by the copyright holder.
   84.43 - */
   84.44 -
   84.45 -package org.openide.util.lookup;
   84.46 -
   84.47 -import java.lang.ref.Reference;
   84.48 -import java.lang.ref.WeakReference;
   84.49 -import java.util.ArrayList;
   84.50 -import java.util.Arrays;
   84.51 -import java.util.Collection;
   84.52 -import java.util.Collections;
   84.53 -import java.util.HashMap;
   84.54 -import java.util.HashSet;
   84.55 -import java.util.IdentityHashMap;
   84.56 -import java.util.Iterator;
   84.57 -import java.util.List;
   84.58 -import java.util.Map;
   84.59 -import java.util.Map.Entry;
   84.60 -import java.util.Set;
   84.61 -import java.util.concurrent.Executor;
   84.62 -import javax.swing.event.EventListenerList;
   84.63 -import org.openide.util.Lookup;
   84.64 -import org.openide.util.LookupEvent;
   84.65 -import org.openide.util.LookupListener;
   84.66 -
   84.67 -/** Implementation of lookup that can delegate to others.
   84.68 - *
   84.69 - * @author  Jaroslav Tulach
   84.70 - * @since 1.9
   84.71 - */
   84.72 -public class ProxyLookup extends Lookup {
   84.73 -    /** data representing the state of the lookup */
   84.74 -    private ImmutableInternalData data;
   84.75 -
   84.76 -    /** Create a proxy to some other lookups.
   84.77 -     * @param lookups the initial delegates
   84.78 -     */
   84.79 -    public ProxyLookup(Lookup... lookups) {
   84.80 -        data = ImmutableInternalData.EMPTY.setLookupsNoFire(lookups, true);
   84.81 -    }
   84.82 -
   84.83 -    /**
   84.84 -     * Create a lookup initially proxying to no others.
   84.85 -     * Permits serializable subclasses.
   84.86 -     * @since 3.27
   84.87 -     */
   84.88 -    protected ProxyLookup() {
   84.89 -        data = ImmutableInternalData.EMPTY;
   84.90 -    }
   84.91 -
   84.92 -    @Override
   84.93 -    public synchronized String toString() {
   84.94 -        return "ProxyLookup(class=" + getClass() + ")->" + Arrays.asList(getData().getLookups(false)); // NOI18N
   84.95 -    }
   84.96 -
   84.97 -    /** Getter for the delegates.
   84.98 -    * @return the array of lookups we delegate to
   84.99 -    * @since 1.19
  84.100 -    */
  84.101 -    protected final Lookup[] getLookups() {
  84.102 -        synchronized (ProxyLookup.this) {
  84.103 -            return getData().getLookups(true);
  84.104 -        }
  84.105 -    }
  84.106 -
  84.107 -    private Set<Lookup> identityHashSet(Collection<Lookup> current) {
  84.108 -        Map<Lookup,Void> map = new IdentityHashMap<Lookup, Void>();
  84.109 -        for (Lookup lookup : current) {
  84.110 -            map.put(lookup, null);
  84.111 -        }
  84.112 -        return map.keySet();
  84.113 -    }
  84.114 -    
  84.115 -    /**
  84.116 -     * Changes the delegates.
  84.117 -     *
  84.118 -     * @param lookups the new lookups to delegate to
  84.119 -     * @since 1.19 protected
  84.120 -     */
  84.121 -    protected final void setLookups(Lookup... lookups) {
  84.122 -        setLookups(null, lookups);
  84.123 -    }
  84.124 -    
  84.125 -    /**
  84.126 -     * Changes the delegates immediatelly, notifies the listeners in provided
  84.127 -     * executor, potentially later.
  84.128 -     *
  84.129 -     * @param lookups the new lookups to delegate to
  84.130 -     * @param notifyIn executor to deliver the notification to listeners or null
  84.131 -     * @since 7.16
  84.132 -     */
  84.133 -    protected final void setLookups(Executor notifyIn, Lookup... lookups) {
  84.134 -        Collection<Reference<R>> arr;
  84.135 -        Set<Lookup> newL;
  84.136 -        Set<Lookup> current;
  84.137 -        Lookup[] old;
  84.138 -        
  84.139 -        Map<Result,LookupListener> toRemove = new IdentityHashMap<Lookup.Result, LookupListener>();
  84.140 -        Map<Result,LookupListener> toAdd = new IdentityHashMap<Lookup.Result, LookupListener>();
  84.141 -        
  84.142 -        ImmutableInternalData orig;
  84.143 -        synchronized (ProxyLookup.this) {
  84.144 -            orig = getData();
  84.145 -            ImmutableInternalData newData = getData().setLookupsNoFire(lookups, false);
  84.146 -            if (newData == getData()) {
  84.147 -                return;
  84.148 -            }
  84.149 -            arr = setData(newData, lookups, toAdd, toRemove);
  84.150 -        }
  84.151 -        
  84.152 -        // better to do this later than in synchronized block
  84.153 -        for (Map.Entry<Result, LookupListener> e : toRemove.entrySet()) {
  84.154 -            e.getKey().removeLookupListener(e.getValue());
  84.155 -        }
  84.156 -        for (Map.Entry<Result, LookupListener> e : toAdd.entrySet()) {
  84.157 -            e.getKey().addLookupListener(e.getValue());
  84.158 -        }
  84.159 -
  84.160 -
  84.161 -        // this cannot be done from the synchronized block
  84.162 -        final ArrayList<Object> evAndListeners = new ArrayList<Object>();
  84.163 -        for (Reference<R> ref : arr) {
  84.164 -            R<?> r = ref.get();
  84.165 -            if (r != null) {
  84.166 -                r.collectFires(evAndListeners);
  84.167 -            }
  84.168 -        }
  84.169 -        
  84.170 -        class Notify implements Runnable {
  84.171 -            public void run() {
  84.172 -                Iterator it = evAndListeners.iterator();
  84.173 -                while (it.hasNext()) {
  84.174 -                    LookupEvent ev = (LookupEvent)it.next();
  84.175 -                    LookupListener l = (LookupListener)it.next();
  84.176 -                    l.resultChanged(ev);
  84.177 -                }
  84.178 -            }
  84.179 -        }
  84.180 -        Notify n = new Notify();
  84.181 -        if (notifyIn == null) {
  84.182 -            n.run();
  84.183 -        } else {
  84.184 -            notifyIn.execute(n);
  84.185 -        }
  84.186 -    }
  84.187 -
  84.188 -    /** Notifies subclasses that a query is about to be processed.
  84.189 -     * Subclasses can update its state before the actual processing
  84.190 -     * begins. It is allowed to call <code>setLookups</code> method
  84.191 -     * to change/update the set of objects the proxy delegates to.
  84.192 -     *
  84.193 -     * @param template the template of the query
  84.194 -     * @since 1.31
  84.195 -     */
  84.196 -    protected void beforeLookup(Template<?> template) {
  84.197 -    }
  84.198 -
  84.199 -    public final <T> T lookup(Class<T> clazz) {
  84.200 -        beforeLookup(new Template<T>(clazz));
  84.201 -
  84.202 -        Lookup[] tmpLkps;
  84.203 -        synchronized (ProxyLookup.this) {
  84.204 -            tmpLkps = getData().getLookups(false);
  84.205 -        }
  84.206 -
  84.207 -        for (int i = 0; i < tmpLkps.length; i++) {
  84.208 -            T o = tmpLkps[i].lookup(clazz);
  84.209 -
  84.210 -            if (o != null) {
  84.211 -                return o;
  84.212 -            }
  84.213 -        }
  84.214 -
  84.215 -        return null;
  84.216 -    }
  84.217 -
  84.218 -    @Override
  84.219 -    public final <T> Item<T> lookupItem(Template<T> template) {
  84.220 -        beforeLookup(template);
  84.221 -
  84.222 -        Lookup[] tmpLkps; 
  84.223 -        synchronized (ProxyLookup.this) {
  84.224 -            tmpLkps = getData().getLookups(false);
  84.225 -        }
  84.226 -
  84.227 -        for (int i = 0; i < tmpLkps.length; i++) {
  84.228 -            Item<T> o = tmpLkps[i].lookupItem(template);
  84.229 -
  84.230 -            if (o != null) {
  84.231 -                return o;
  84.232 -            }
  84.233 -        }
  84.234 -
  84.235 -        return null;
  84.236 -    }
  84.237 -
  84.238 -    @SuppressWarnings("unchecked")
  84.239 -    private static <T> R<T> convertResult(R r) {
  84.240 -        return (R<T>)r;
  84.241 -    }
  84.242 -
  84.243 -    public final <T> Result<T> lookup(Lookup.Template<T> template) {
  84.244 -        synchronized (ProxyLookup.this) {
  84.245 -            ImmutableInternalData[] res = { null };
  84.246 -            R<T> newR = getData().findResult(this, res, template);
  84.247 -            setData(res[0], getData().getLookups(false), null, null);
  84.248 -            return newR;
  84.249 -        }
  84.250 -    }
  84.251 -
  84.252 -    /** Unregisters a template from the has map.
  84.253 -     */
  84.254 -    private final void unregisterTemplate(Template<?> template) {
  84.255 -        synchronized (ProxyLookup.this) {
  84.256 -            ImmutableInternalData id = getData();
  84.257 -            if (id == null) {
  84.258 -                return;
  84.259 -            }
  84.260 -            setData(id.removeTemplate(this, template), getData().getLookups(false), null, null);
  84.261 -        }
  84.262 -    }
  84.263 -
  84.264 -    private ImmutableInternalData getData() {
  84.265 -        assert Thread.holdsLock(this);
  84.266 -        return data;
  84.267 -    }
  84.268 -
  84.269 -    private Collection<Reference<R>> setData(
  84.270 -        ImmutableInternalData newData, Lookup[] current, 
  84.271 -        Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
  84.272 -    ) {
  84.273 -        assert Thread.holdsLock(ProxyLookup.this);
  84.274 -        assert newData != null;
  84.275 -        
  84.276 -        ImmutableInternalData previous = this.getData();
  84.277 -        
  84.278 -        if (previous == newData) {
  84.279 -            return Collections.emptyList();
  84.280 -        }
  84.281 -
  84.282 -        if (newData.isEmpty()) {
  84.283 -            this.setData(newData);
  84.284 -            // no affected results => exit
  84.285 -            return Collections.emptyList();
  84.286 -        }
  84.287 -
  84.288 -        Collection<Reference<R>> arr = newData.references();
  84.289 -
  84.290 -        Set<Lookup> removed = identityHashSet(previous.getLookupsList());
  84.291 -        Set<Lookup> currentSet = identityHashSet(Arrays.asList(current));
  84.292 -        Set<Lookup> newL = identityHashSet(currentSet);
  84.293 -        removed.removeAll(currentSet); // current contains just those lookups that have disappeared
  84.294 -        newL.removeAll(previous.getLookupsList()); // really new lookups
  84.295 -
  84.296 -        for (Reference<R> ref : arr) {
  84.297 -            R<?> r = ref.get();
  84.298 -            if (r != null) {
  84.299 -                r.lookupChange(newData, current, previous, newL, removed, toAdd, toRemove);
  84.300 -                if (this.getData() != previous) {
  84.301 -                    // the data were changed by an re-entrant call
  84.302 -                    // skip any other change processing, as it is not needed
  84.303 -                    // anymore
  84.304 -                }
  84.305 -            }
  84.306 -        }
  84.307 -                for (Reference<R> ref : arr) {
  84.308 -            R<?> r = ref.get();
  84.309 -            if (r != null) {
  84.310 -                r.data = newData;
  84.311 -            }
  84.312 -        }
  84.313 -        this.setData(newData);
  84.314 -        return arr;
  84.315 -    }
  84.316 -
  84.317 -    private void setData(ImmutableInternalData data) {
  84.318 -        this.data = data;
  84.319 -    }
  84.320 -
  84.321 -    /** Result of a lookup request. Allows access to single object
  84.322 -     * that was found (not too useful) and also to all objects found
  84.323 -     * (more useful).
  84.324 -     */
  84.325 -    private static final class R<T> extends WaitableResult<T> {
  84.326 -        /** weak listener & result */
  84.327 -        private final WeakResult<T> weakL;
  84.328 -        
  84.329 -        /** list of listeners added */
  84.330 -        private javax.swing.event.EventListenerList listeners;
  84.331 -
  84.332 -        /** collection of Objects */
  84.333 -        private Collection[] cache;
  84.334 -
  84.335 -        
  84.336 -        /** associated lookup */
  84.337 -        private ImmutableInternalData data;
  84.338 -
  84.339 -        /** Constructor.
  84.340 -         */
  84.341 -        public R(ProxyLookup proxy, Lookup.Template<T> t) {
  84.342 -            this.weakL = new WeakResult<T>(proxy, this, t);
  84.343 -        }
  84.344 -        
  84.345 -        private ProxyLookup proxy() {
  84.346 -            return weakL.result.proxy;
  84.347 -        }
  84.348 -
  84.349 -        @SuppressWarnings("unchecked")
  84.350 -        private Result<T>[] newResults(int len) {
  84.351 -            return new Result[len];
  84.352 -        }
  84.353 -        
  84.354 -        @Override
  84.355 -        protected void finalize() {
  84.356 -            weakL.result.run();
  84.357 -        }
  84.358 -
  84.359 -        /** initializes the results
  84.360 -         */
  84.361 -        private Result<T>[] initResults() {
  84.362 -            BIG_LOOP: for (;;) {
  84.363 -                Lookup[] myLkps;
  84.364 -                ImmutableInternalData current;
  84.365 -                synchronized (proxy()) {
  84.366 -                    if (weakL.getResults() != null) {
  84.367 -                        return weakL.getResults();
  84.368 -                    }
  84.369 -                    myLkps = data.getLookups(false);
  84.370 -                    current = data;
  84.371 -                }
  84.372 -
  84.373 -                Result<T>[] arr = newResults(myLkps.length);
  84.374 -
  84.375 -                for (int i = 0; i < arr.length; i++) {
  84.376 -                    arr[i] = myLkps[i].lookup(weakL.result.template);
  84.377 -                }
  84.378 -
  84.379 -                synchronized (proxy()) {
  84.380 -                    if (current != data) {
  84.381 -                        continue;
  84.382 -                    }
  84.383 -                    
  84.384 -                    Lookup[] currentLkps = data.getLookups(false);
  84.385 -                    if (currentLkps.length != myLkps.length) {
  84.386 -                        continue BIG_LOOP;
  84.387 -                    }
  84.388 -                    for (int i = 0; i < currentLkps.length; i++) {
  84.389 -                        if (currentLkps[i] != myLkps[i]) {
  84.390 -                            continue BIG_LOOP;
  84.391 -                        }
  84.392 -                    }
  84.393 -                    
  84.394 -                    // some other thread might compute the result mean while. 
  84.395 -                    // if not finish the computation yourself
  84.396 -                    if (weakL.getResults() != null) {
  84.397 -                        return weakL.getResults();
  84.398 -                    }
  84.399 -
  84.400 -                    for (int i = 0; i < arr.length; i++) {
  84.401 -                        arr[i].addLookupListener(weakL);
  84.402 -                    }
  84.403 -
  84.404 -                    weakL.setResults(arr);
  84.405 -
  84.406 -                    return arr;
  84.407 -                }
  84.408 -            }
  84.409 -        }
  84.410 -
  84.411 -        /** Called when there is a change in the list of proxied lookups.
  84.412 -         * @param added set of added lookups
  84.413 -         * @param remove set of removed lookups
  84.414 -         * @param current array of current lookups
  84.415 -         */
  84.416 -        final void lookupChange(
  84.417 -            ImmutableInternalData newData, Lookup[] current, ImmutableInternalData oldData,
  84.418 -            Set<Lookup> added, Set<Lookup> removed,
  84.419 -            Map<Result,LookupListener> toAdd, Map<Result,LookupListener> toRemove
  84.420 -        ) {
  84.421 -            if (weakL.getResults() == null) {
  84.422 -                // not computed yet, do not need to do anything
  84.423 -                return;
  84.424 -            }
  84.425 -
  84.426 -            Lookup[] old = oldData.getLookups(false);
  84.427 -
  84.428 -            // map (Lookup, Lookup.Result)
  84.429 -            Map<Lookup,Result<T>> map = new IdentityHashMap<Lookup,Result<T>>(old.length * 2);
  84.430 -
  84.431 -            for (int i = 0; i < old.length; i++) {
  84.432 -                if (removed.contains(old[i])) {
  84.433 -                    // removed lookup
  84.434 -                    if (toRemove != null) {
  84.435 -                        toRemove.put(weakL.getResults()[i], weakL);
  84.436 -                    }
  84.437 -                } else {
  84.438 -                    // remember the association
  84.439 -                    map.put(old[i], weakL.getResults()[i]);
  84.440 -                }
  84.441 -            }
  84.442 -
  84.443 -            Lookup.Result<T>[] arr = newResults(current.length);
  84.444 -
  84.445 -            for (int i = 0; i < current.length; i++) {
  84.446 -                if (added.contains(current[i])) {
  84.447 -                    // new lookup
  84.448 -                    arr[i] = current[i].lookup(weakL.result.template);
  84.449 -                    if (toAdd != null) {
  84.450 -                        toAdd.put(arr[i], weakL);
  84.451 -                    }
  84.452 -                } else {
  84.453 -                    // old lookup
  84.454 -                    arr[i] = map.get(current[i]);
  84.455 -
  84.456 -                    if (arr[i] == null) {
  84.457 -                        // assert
  84.458 -                        throw new IllegalStateException();
  84.459 -                    }
  84.460 -                }
  84.461 -            }
  84.462 -
  84.463 -            // remember the new results
  84.464 -            weakL.setResults(arr);
  84.465 -        }
  84.466 -
  84.467 -        /** Just delegates.
  84.468 -         */
  84.469 -        public void addLookupListener(LookupListener l) {
  84.470 -            synchronized (proxy()) {
  84.471 -                if (listeners == null) {
  84.472 -                    listeners = new EventListenerList();
  84.473 -                }
  84.474 -            }
  84.475 -
  84.476 -            listeners.add(LookupListener.class, l);
  84.477 -        }
  84.478 -
  84.479 -        /** Just delegates.
  84.480 -         */
  84.481 -        public void removeLookupListener(LookupListener l) {
  84.482 -            if (listeners != null) {
  84.483 -                listeners.remove(LookupListener.class, l);
  84.484 -            }
  84.485 -        }
  84.486 -
  84.487 -        /** Access to all instances in the result.
  84.488 -         * @return collection of all instances
  84.489 -         */
  84.490 -        @SuppressWarnings("unchecked")
  84.491 -        public java.util.Collection<T> allInstances() {
  84.492 -            return computeResult(0);
  84.493 -        }
  84.494 -
  84.495 -        /** Classes of all results. Set of the most concreate classes
  84.496 -         * that are registered in the system.
  84.497 -         * @return set of Class objects
  84.498 -         */
  84.499 -        @SuppressWarnings("unchecked")
  84.500 -        @Override
  84.501 -        public java.util.Set<Class<? extends T>> allClasses() {
  84.502 -            return (java.util.Set<Class<? extends T>>) computeResult(1);
  84.503 -        }
  84.504 -
  84.505 -        /** All registered items. The collection of all pairs of
  84.506 -         * ii and their classes.
  84.507 -         * @return collection of Lookup.Item
  84.508 -         */
  84.509 -        @SuppressWarnings("unchecked")
  84.510 -        @Override
  84.511 -        public java.util.Collection<? extends Item<T>> allItems() {
  84.512 -            return computeResult(2);
  84.513 -        }
  84.514 -
  84.515 -        /** Computes results from proxied lookups.
  84.516 -         * @param indexToCache 0 = allInstances, 1 = allClasses, 2 = allItems
  84.517 -         * @return the collection or set of the objects
  84.518 -         */
  84.519 -        private java.util.Collection computeResult(int indexToCache) {
  84.520 -            // results to use
  84.521 -            Lookup.Result<T>[] arr = myBeforeLookup();
  84.522 -
  84.523 -            // if the call to beforeLookup resulted in deletion of caches
  84.524 -            synchronized (proxy()) {
  84.525 -                if (getCache() != null) {
  84.526 -                    Collection result = getCache()[indexToCache];
  84.527 -                    if (result != null) {
  84.528 -                        return result;
  84.529 -                    }
  84.530 -                }
  84.531 -            }
  84.532 -
  84.533 -            // initialize the collection to hold result
  84.534 -            Collection<Object> compute;
  84.535 -            Collection<Object> ret;
  84.536 -
  84.537 -            if (indexToCache == 1) {
  84.538 -                HashSet<Object> s = new HashSet<Object>();
  84.539 -                compute = s;
  84.540 -                ret = Collections.unmodifiableSet(s);
  84.541 -            } else {
  84.542 -                List<Object> l = new ArrayList<Object>(arr.length * 2);
  84.543 -                compute = l;
  84.544 -                ret = Collections.unmodifiableList(l);
  84.545 -            }
  84.546 -
  84.547 -            // fill the collection
  84.548 -            for (int i = 0; i < arr.length; i++) {
  84.549 -                switch (indexToCache) {
  84.550 -                case 0:
  84.551 -                    compute.addAll(arr[i].allInstances());
  84.552 -                    break;
  84.553 -                case 1:
  84.554 -                    compute.addAll(arr[i].allClasses());
  84.555 -                    break;
  84.556 -                case 2:
  84.557 -                    compute.addAll(arr[i].allItems());
  84.558 -                    break;
  84.559 -                default:
  84.560 -                    assert false : "Wrong index: " + indexToCache;
  84.561 -                }
  84.562 -            }
  84.563 -            
  84.564 -            
  84.565 -
  84.566 -            synchronized (proxy()) {
  84.567 -                if (getCache() == null) {
  84.568 -                    // initialize the cache to indicate this result is in use
  84.569 -                    setCache(new Collection[3]);
  84.570 -                }
  84.571 -                
  84.572 -                if (arr == weakL.getResults()) {
  84.573 -                    // updates the results, if the results have not been
  84.574 -                    // changed during the computation of allInstances
  84.575 -                    getCache()[indexToCache] = ret;
  84.576 -                }
  84.577 -            }
  84.578 -
  84.579 -            return ret;
  84.580 -        }
  84.581 -
  84.582 -        /** When the result changes, fire the event.
  84.583 -         */
  84.584 -        public void resultChanged(LookupEvent ev) {
  84.585 -            collectFires(null);
  84.586 -        }
  84.587 -        
  84.588 -        protected void collectFires(Collection<Object> evAndListeners) {
  84.589 -            // clear cached instances
  84.590 -            Collection oldItems;
  84.591 -            Collection oldInstances;
  84.592 -            synchronized (proxy()) {
  84.593 -                if (getCache() == null) {
  84.594 -                    // nobody queried the result yet
  84.595 -                    return;
  84.596 -                }
  84.597 -                oldInstances = getCache()[0];
  84.598 -                oldItems = getCache()[2];
  84.599 -                
  84.600 -
  84.601 -                if (listeners == null || listeners.getListenerCount() == 0) {
  84.602 -                    // clear the cache
  84.603 -                    setCache(new Collection[3]);
  84.604 -                    return;
  84.605 -                }
  84.606 -                
  84.607 -                // ignore events if they arrive as a result of call to allItems
  84.608 -                // or allInstances, bellow...
  84.609 -                setCache(null);
  84.610 -            }
  84.611 -
  84.612 -            boolean modified = true;
  84.613 -
  84.614 -            if (oldItems != null) {
  84.615 -                Collection newItems = allItems();
  84.616 -                if (oldItems.equals(newItems)) {
  84.617 -                    modified = false;
  84.618 -                }
  84.619 -            } else {
  84.620 -                if (oldInstances != null) {
  84.621 -                    Collection newInstances = allInstances();
  84.622 -                    if (oldInstances.equals(newInstances)) {
  84.623 -                        modified = false;
  84.624 -                    }
  84.625 -                } else {
  84.626 -                    synchronized (proxy()) {
  84.627 -                        if (getCache() == null) {
  84.628 -                            // we have to initialize the cache
  84.629 -                            // to show that the result has been initialized
  84.630 -                            setCache(new Collection[3]);
  84.631 -                        }
  84.632 -                    }
  84.633 -                }
  84.634 -            }
  84.635 -            
  84.636 -            if (modified) {
  84.637 -                LookupEvent ev = new LookupEvent(this);
  84.638 -                AbstractLookup.notifyListeners(listeners.getListenerList(), ev, evAndListeners);
  84.639 -            }
  84.640 -        }
  84.641 -
  84.642 -        /** Implementation of my before lookup.
  84.643 -         * @return results to work on.
  84.644 -         */
  84.645 -        private Lookup.Result<T>[] myBeforeLookup() {
  84.646 -            Template<T> template = weakL.result.template;
  84.647 -            
  84.648 -            proxy().beforeLookup(template);
  84.649 -
  84.650 -            Lookup.Result<T>[] arr = initResults();
  84.651 -
  84.652 -            // invoke update on the results
  84.653 -            for (int i = 0; i < arr.length; i++) {
  84.654 -                if (arr[i] instanceof WaitableResult) {
  84.655 -                    WaitableResult w = (WaitableResult) arr[i];
  84.656 -                    w.beforeLookup(template);
  84.657 -                }
  84.658 -            }
  84.659 -
  84.660 -            return arr;
  84.661 -        }
  84.662 -
  84.663 -        /** Used by proxy results to synchronize before lookup.
  84.664 -         */
  84.665 -        protected void beforeLookup(Lookup.Template t) {
  84.666 -            if (t.getType() == weakL.result.template.getType()) {
  84.667 -                myBeforeLookup();
  84.668 -            }
  84.669 -        }
  84.670 -
  84.671 -        private Collection[] getCache() {
  84.672 -            return cache;
  84.673 -        }
  84.674 -
  84.675 -        private void setCache(Collection[] cache) {
  84.676 -            assert Thread.holdsLock(proxy());
  84.677 -            this.cache = cache;
  84.678 -        }
  84.679 -    }
  84.680 -    private static final class WeakRef<T> extends WeakReference<R> implements Runnable {
  84.681 -        final WeakResult<T> result;
  84.682 -        final ProxyLookup proxy;
  84.683 -        final Template<T> template;
  84.684 -        
  84.685 -        public WeakRef(R r, WeakResult<T> result, ProxyLookup proxy, Template<T> template) {
  84.686 -            super(r);
  84.687 -            this.result = result;
  84.688 -            this.template = template;
  84.689 -            this.proxy = proxy;
  84.690 -        }
  84.691 -
  84.692 -        public void run() {
  84.693 -            result.removeListeners();
  84.694 -            proxy.unregisterTemplate(template);
  84.695 -        }
  84.696 -    }
  84.697 -    
  84.698 -    
  84.699 -    private static final class WeakResult<T> extends WaitableResult<T> implements LookupListener, Runnable {
  84.700 -        /** all results */
  84.701 -        private Lookup.Result<T>[] results;
  84.702 -        private final WeakRef<T> result;
  84.703 -        
  84.704 -        public WeakResult(ProxyLookup proxy, R r, Template<T> t) {
  84.705 -            this.result = new WeakRef<T>(r, this, proxy, t);
  84.706 -        }
  84.707 -        
  84.708 -        final void removeListeners() {
  84.709 -            Lookup.Result<T>[] arr = this.getResults();
  84.710 -            if (arr == null) {
  84.711 -                return;
  84.712 -            }
  84.713 -
  84.714 -            for(int i = 0; i < arr.length; i++) {
  84.715 -                arr[i].removeLookupListener(this);
  84.716 -            }
  84.717 -        }
  84.718 -
  84.719 -        protected void beforeLookup(Lookup.Template t) {
  84.720 -            R r = result.get();
  84.721 -            if (r != null) {
  84.722 -                r.beforeLookup(t);
  84.723 -            } else {
  84.724 -                removeListeners();
  84.725 -            }
  84.726 -        }
  84.727 -
  84.728 -        protected void collectFires(Collection<Object> evAndListeners) {
  84.729 -            R<?> r = result.get();
  84.730 -            if (r != null) {
  84.731 -                r.collectFires(evAndListeners);
  84.732 -            } else {
  84.733 -                removeListeners();
  84.734 -            }
  84.735 -        }
  84.736 -
  84.737 -        public void addLookupListener(LookupListener l) {
  84.738 -            assert false;
  84.739 -        }
  84.740 -
  84.741 -        public void removeLookupListener(LookupListener l) {
  84.742 -            assert false;
  84.743 -        }
  84.744 -
  84.745 -        public Collection<T> allInstances() {
  84.746 -            assert false;
  84.747 -            return null;
  84.748 -        }
  84.749 -
  84.750 -        public void resultChanged(LookupEvent ev) {
  84.751 -            R r = result.get();
  84.752 -            if (r != null) {
  84.753 -                r.resultChanged(ev);
  84.754 -            } else {
  84.755 -                removeListeners();
  84.756 -            }
  84.757 -        }
  84.758 -
  84.759 -        @Override
  84.760 -        public Collection<? extends Item<T>> allItems() {
  84.761 -            assert false;
  84.762 -            return null;
  84.763 -        }
  84.764 -
  84.765 -        @Override
  84.766 -        public Set<Class<? extends T>> allClasses() {
  84.767 -            assert false;
  84.768 -            return null;
  84.769 -        }
  84.770 -
  84.771 -        public void run() {
  84.772 -            removeListeners();
  84.773 -        }
  84.774 -
  84.775 -        private Lookup.Result<T>[] getResults() {
  84.776 -            return results;
  84.777 -        }
  84.778 -
  84.779 -        private void setResults(Lookup.Result<T>[] results) {
  84.780 -            this.results = results;
  84.781 -        }
  84.782 -    } // end of WeakResult
  84.783 -    
  84.784 -    static abstract class ImmutableInternalData extends Object {
  84.785 -        static final ImmutableInternalData EMPTY = new EmptyInternalData();
  84.786 -        static final Lookup[] EMPTY_ARR = new Lookup[0];
  84.787 -
  84.788 -        
  84.789 -        protected ImmutableInternalData() {
  84.790 -        }
  84.791 -        
  84.792 -        public static ImmutableInternalData create(Object lkp, Map<Template, Reference<R>> results) {
  84.793 -            if (results.size() == 0 && lkp == EMPTY_ARR) {
  84.794 -                return EMPTY;
  84.795 -            }
  84.796 -            if (results.size() == 1) {
  84.797 -                Entry<Template,Reference<R>> e = results.entrySet().iterator().next();
  84.798 -                return new SingleInternalData(lkp, e.getKey(), e.getValue());
  84.799 -            }
  84.800 -            
  84.801 -            return new RealInternalData(lkp, results);
  84.802 -        }
  84.803 -
  84.804 -        protected abstract boolean isEmpty();
  84.805 -        protected abstract Map<Template, Reference<R>> getResults();
  84.806 -        protected abstract Object getRawLookups();
  84.807 -
  84.808 -        final Collection<Reference<R>> references() {
  84.809 -            return getResults().values();
  84.810 -        }
  84.811 -        
  84.812 -        final <T> ImmutableInternalData removeTemplate(ProxyLookup proxy, Template<T> template) {
  84.813 -            if (getResults().containsKey(template)) {
  84.814 -                HashMap<Template,Reference<R>> c = new HashMap<Template, Reference<ProxyLookup.R>>(getResults());
  84.815 -                Reference<R> ref = c.remove(template);
  84.816 -                if (ref != null && ref.get() != null) {
  84.817 -                    // seems like there is a reference to a result for this template
  84.818 -                    // thta is still alive
  84.819 -                    return this;
  84.820 -                }
  84.821 -                return create(getRawLookups(), c);
  84.822 -            } else {
  84.823 -                return this;
  84.824 -            }
  84.825 -        }
  84.826 -        
  84.827 -        <T> R<T> findResult(ProxyLookup proxy, ImmutableInternalData[] newData, Template<T> template) {
  84.828 -            assert Thread.holdsLock(proxy);
  84.829 -            
  84.830 -            Map<Template,Reference<R>> map = getResults();
  84.831 -            
  84.832 -            Reference<R> ref = map.get(template);
  84.833 -            R r = (ref == null) ? null : ref.get();
  84.834 -
  84.835 -            if (r != null) {
  84.836 -                newData[0] = this;
  84.837 -                return convertResult(r);
  84.838 -            }
  84.839 -            
  84.840 -            HashMap<Template, Reference<R>> res = new HashMap<Template, Reference<R>>(map);
  84.841 -            R<T> newR = new R<T>(proxy, template);
  84.842 -            res.put(template, new java.lang.ref.SoftReference<R>(newR));
  84.843 -            newR.data = newData[0] = create(getRawLookups(), res);
  84.844 -            return newR;
  84.845 -        }
  84.846 -        final ImmutableInternalData setLookupsNoFire(Lookup[] lookups, boolean skipCheck) {
  84.847 -            Object l;
  84.848 -            
  84.849 -            if (!skipCheck) {
  84.850 -                Lookup[] previous = getLookups(false);
  84.851 -                if (previous == lookups) {
  84.852 -                    return this;
  84.853 -                }
  84.854 -            
  84.855 -                if (previous.length == lookups.length) {
  84.856 -                    int same = 0;
  84.857 -                    for (int i = 0; i < previous.length; i++) {
  84.858 -                        if (lookups[i] != previous[i]) {
  84.859 -                            break;
  84.860 -                        }
  84.861 -                        same++;
  84.862 -                    }
  84.863 -                    if (same == previous.length) {
  84.864 -                        return this;
  84.865 -                    }
  84.866 -                }
  84.867 -            }
  84.868 -            
  84.869 -            if (lookups.length == 1) {
  84.870 -                l = lookups[0];
  84.871 -                assert l != null : "Cannot assign null delegate";
  84.872 -            } else {
  84.873 -                if (lookups.length == 0) {
  84.874 -                    l = EMPTY_ARR;
  84.875 -                } else {
  84.876 -                    l = lookups.clone();
  84.877 -                }
  84.878 -            }
  84.879 -            
  84.880 -            if (isEmpty() && l == EMPTY_ARR) {
  84.881 -                return this;
  84.882 -            }
  84.883 -            
  84.884 -            return create(l, getResults());
  84.885 -        }
  84.886 -        final Lookup[] getLookups(boolean clone) {
  84.887 -            Object l = this.getRawLookups();
  84.888 -            if (l instanceof Lookup) {
  84.889 -                return new Lookup[] { (Lookup)l };
  84.890 -            } else {
  84.891 -                Lookup[] arr = (Lookup[])l;
  84.892 -                if (clone) {
  84.893 -                    arr = arr.clone();
  84.894 -                }
  84.895 -                return arr;
  84.896 -            }
  84.897 -        }
  84.898 -        final List<Lookup> getLookupsList() {
  84.899 -            return Arrays.asList(getLookups(false));            
  84.900 -        }
  84.901 -
  84.902 -    } // end of ImmutableInternalData
  84.903 -    
  84.904 -    private static final class SingleInternalData extends ImmutableInternalData {
  84.905 -        /** lookups to delegate to (either Lookup or array of Lookups) */
  84.906 -        private final Object lookups;
  84.907 -        private final Template template;
  84.908 -        private final Reference<ProxyLookup.R> result;
  84.909 -                
  84.910 -        public SingleInternalData(Object lookups, Template<?> template, Reference<ProxyLookup.R> result) {
  84.911 -            this.lookups = lookups;
  84.912 -            this.template = template;
  84.913 -            this.result = result;
  84.914 -        }
  84.915 -
  84.916 -        protected final boolean isEmpty() {
  84.917 -            return false;
  84.918 -        }
  84.919 -
  84.920 -        protected Map<Template, Reference<R>> getResults() {
  84.921 -            return Collections.singletonMap(template, result);
  84.922 -        }
  84.923 -        
  84.924 -        protected Object getRawLookups() {
  84.925 -            return lookups;
  84.926 -        }
  84.927 -    }
  84.928 -    private static final class RealInternalData extends ImmutableInternalData {
  84.929 -        /** lookups to delegate to (either Lookup or array of Lookups) */
  84.930 -        private final Object lookups;
  84.931 -
  84.932 -        /** map of templates to currently active results */
  84.933 -        private final Map<Template,Reference<R>> results;
  84.934 -
  84.935 -        public RealInternalData(Object lookups, Map<Template, Reference<ProxyLookup.R>> results) {
  84.936 -            this.results = results;
  84.937 -            this.lookups = lookups;
  84.938 -        }
  84.939 -
  84.940 -        protected final boolean isEmpty() {
  84.941 -            return false;
  84.942 -        }
  84.943 -
  84.944 -        protected Map<Template, Reference<R>> getResults() {
  84.945 -            boolean strict = false;
  84.946 -            assert strict = true;
  84.947 -            return strict ? Collections.unmodifiableMap(results) : results;
  84.948 -        }
  84.949 -        
  84.950 -        protected Object getRawLookups() {
  84.951 -            return lookups;
  84.952 -        }
  84.953 -    }
  84.954 -    
  84.955 -    private static final class EmptyInternalData extends ImmutableInternalData {
  84.956 -        EmptyInternalData() {
  84.957 -        }
  84.958 -
  84.959 -        protected final boolean isEmpty() {
  84.960 -            return true;
  84.961 -        }
  84.962 -
  84.963 -        protected Map<Template, Reference<R>> getResults() {
  84.964 -            return Collections.emptyMap();
  84.965 -        }
  84.966 -
  84.967 -        @Override
  84.968 -        protected Object getRawLookups() {
  84.969 -            return EMPTY_ARR;
  84.970 -        }
  84.971 -    } // end of EmptyInternalData
  84.972 -}
    85.1 --- a/openide.util/src/org/openide/util/lookup/ServiceProvider.java	Sat Oct 31 15:06:58 2009 +0100
    85.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.3 @@ -1,102 +0,0 @@
    85.4 -/*
    85.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    85.6 - *
    85.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
    85.8 - *
    85.9 - * The contents of this file are subject to the terms of either the GNU
   85.10 - * General Public License Version 2 only ("GPL") or the Common
   85.11 - * Development and Distribution License("CDDL") (collectively, the
   85.12 - * "License"). You may not use this file except in compliance with the
   85.13 - * License. You can obtain a copy of the License at
   85.14 - * http://www.netbeans.org/cddl-gplv2.html
   85.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   85.16 - * specific language governing permissions and limitations under the
   85.17 - * License.  When distributing the software, include this License Header
   85.18 - * Notice in each file and include the License file at
   85.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   85.20 - * particular file as subject to the "Classpath" exception as provided
   85.21 - * by Sun in the GPL Version 2 section of the License file that
   85.22 - * accompanied this code. If applicable, add the following below the
   85.23 - * License Header, with the fields enclosed by brackets [] replaced by
   85.24 - * your own identifying information:
   85.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   85.26 - *
   85.27 - * If you wish your version of this file to be governed by only the CDDL
   85.28 - * or only the GPL Version 2, indicate your decision by adding
   85.29 - * "[Contributor] elects to include this software in this distribution
   85.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   85.31 - * single choice of license, a recipient has the option to distribute
   85.32 - * your version of this file under either the CDDL, the GPL Version 2 or
   85.33 - * to extend the choice of license to its licensees as provided above.
   85.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   85.35 - * Version 2 license, then the option applies only if the new code is
   85.36 - * made subject to such option by the copyright holder.
   85.37 - *
   85.38 - * Contributor(s):
   85.39 - *
   85.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   85.41 - */
   85.42 -
   85.43 -package org.openide.util.lookup;
   85.44 -
   85.45 -import java.lang.annotation.ElementType;
   85.46 -import java.lang.annotation.Retention;
   85.47 -import java.lang.annotation.RetentionPolicy;
   85.48 -import java.lang.annotation.Target;
   85.49 -import org.openide.util.Lookup;
   85.50 -
   85.51 -/**
   85.52 - * Declarative registration of a singleton service provider.
   85.53 - * By marking an implementation class with this annotation,
   85.54 - * you automatically register that implementation, normally in {@link Lookup#getDefault}.
   85.55 - * The class must be public and have a public no-argument constructor.
   85.56 - * <p>Example of usage:
   85.57 - * <pre>
   85.58 - * package my.module;
   85.59 - * import org.netbeans.spi.whatever.Thing;
   85.60 - * import org.openide.util.lookup.ServiceProvider;
   85.61 - * &#64;ServiceProvider(service=Thing.class)
   85.62 - * public class MyThing implements Thing {...}
   85.63 - * </pre>
   85.64 - * <p>would result in a resource file <code>META-INF/services/org.netbeans.spi.whatever.Thing</code>
   85.65 - * containing the single line of text: <code>my.module.MyThing</code>
   85.66 - * @see Lookups#metaInfServices(ClassLoader)
   85.67 - * @since org.openide.util 7.20
   85.68 - */
   85.69 -@Retention(RetentionPolicy.SOURCE)
   85.70 -@Target(ElementType.TYPE)
   85.71 -public @interface ServiceProvider {
   85.72 -
   85.73 -    /**
   85.74 -     * The interface (or abstract class) to register this implementation under.
   85.75 -     * It is an error if the implementation class is not in fact assignable to the interface.
   85.76 -     * <p>If you need to register one class under multiple interfaces, use {@link ServiceProviders}.
   85.77 -     * <p>Requests to look up the specified interface should result in this implementation.
   85.78 -     * Requests for any other types may or may not result in this implementation even if the
   85.79 -     * implementation is assignable to those types.
   85.80 -     */
   85.81 -    Class<?> service();
   85.82 -
   85.83 -    /**
   85.84 -     * An optional position in which to register this service relative to others.
   85.85 -     * Lower-numbered services are returned in the lookup result first.
   85.86 -     * Services with no specified position are returned last.
   85.87 -     */
   85.88 -    int position() default Integer.MAX_VALUE;
   85.89 -
   85.90 -    /**
   85.91 -     * An optional list of implementations (given as fully-qualified class names) which this implementation supersedes.
   85.92 -     * If specified, those implementations will not be loaded even if they were registered.
   85.93 -     * Useful on occasion to cancel a generic implementation and replace it with a more advanced one.
   85.94 -     */
   85.95 -    String[] supersedes() default {};
   85.96 -
   85.97 -    /**
   85.98 -     * An optional path to register this implementation in.
   85.99 -     * For example, <code>Projects/sometype/Nodes</code> could be used.
  85.100 -     * This style of registration would be recognized by {@link Lookups#forPath}
  85.101 -     * rather than {@link Lookup#getDefault}.
  85.102 -     */
  85.103 -    String path() default "";
  85.104 -
  85.105 -}
    86.1 --- a/openide.util/src/org/openide/util/lookup/ServiceProviders.java	Sat Oct 31 15:06:58 2009 +0100
    86.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.3 @@ -1,60 +0,0 @@
    86.4 -/*
    86.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    86.6 - *
    86.7 - * Copyright 2008 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 2008 Sun Microsystems, Inc.
   86.41 - */
   86.42 -
   86.43 -package org.openide.util.lookup;
   86.44 -
   86.45 -import java.lang.annotation.ElementType;
   86.46 -import java.lang.annotation.Retention;
   86.47 -import java.lang.annotation.RetentionPolicy;
   86.48 -import java.lang.annotation.Target;
   86.49 -
   86.50 -/**
   86.51 - * Similar to {@link ServiceProvider} but permits multiple registrations of one class.
   86.52 - * @since org.openide.util 7.20
   86.53 - */
   86.54 -@Retention(RetentionPolicy.SOURCE)
   86.55 -@Target(ElementType.TYPE)
   86.56 -public @interface ServiceProviders {
   86.57 -
   86.58 -    /**
   86.59 -     * List of service provider registrations.
   86.60 -     */
   86.61 -    ServiceProvider[] value();
   86.62 -
   86.63 -}
    87.1 --- a/openide.util/src/org/openide/util/lookup/SimpleLookup.java	Sat Oct 31 15:06:58 2009 +0100
    87.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.3 @@ -1,250 +0,0 @@
    87.4 -/*
    87.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    87.6 - *
    87.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
    87.8 - *
    87.9 - * The contents of this file are subject to the terms of either the GNU
   87.10 - * General Public License Version 2 only ("GPL") or the Common
   87.11 - * Development and Distribution License("CDDL") (collectively, the
   87.12 - * "License"). You may not use this file except in compliance with the
   87.13 - * License. You can obtain a copy of the License at
   87.14 - * http://www.netbeans.org/cddl-gplv2.html
   87.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   87.16 - * specific language governing permissions and limitations under the
   87.17 - * License.  When distributing the software, include this License Header
   87.18 - * Notice in each file and include the License file at
   87.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   87.20 - * particular file as subject to the "Classpath" exception as provided
   87.21 - * by Sun in the GPL Version 2 section of the License file that
   87.22 - * accompanied this code. If applicable, add the following below the
   87.23 - * License Header, with the fields enclosed by brackets [] replaced by
   87.24 - * your own identifying information:
   87.25 - * "Portions Copyrighted [year] [name of copyright owner]"
   87.26 - *
   87.27 - * Contributor(s):
   87.28 - *
   87.29 - * The Original Software is NetBeans. The Initial Developer of the Original
   87.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   87.31 - * Microsystems, Inc. All Rights Reserved.
   87.32 - *
   87.33 - * If you wish your version of this file to be governed by only the CDDL
   87.34 - * or only the GPL Version 2, indicate your decision by adding
   87.35 - * "[Contributor] elects to include this software in this distribution
   87.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   87.37 - * single choice of license, a recipient has the option to distribute
   87.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   87.39 - * to extend the choice of license to its licensees as provided above.
   87.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   87.41 - * Version 2 license, then the option applies only if the new code is
   87.42 - * made subject to such option by the copyright holder.
   87.43 - */
   87.44 -package org.openide.util.lookup;
   87.45 -
   87.46 -import org.openide.util.Lookup;
   87.47 -import org.openide.util.LookupListener;
   87.48 -
   87.49 -import java.util.*;
   87.50 -
   87.51 -
   87.52 -/**
   87.53 - * Simple lookup implementation. It can be used to create temporary lookups
   87.54 - * that do not change over time. The result stores references to all objects
   87.55 - * passed in the constructor. Those objecst are the only ones returned as
   87.56 - * result.
   87.57 - * @author David Strupl
   87.58 - */
   87.59 -class SimpleLookup extends org.openide.util.Lookup {
   87.60 -    /** This variable is initialized in constructor and thus null
   87.61 -     * value is not allowed as its value. */
   87.62 -    private Collection<Item<?>> allItems;
   87.63 -
   87.64 -    /**
   87.65 -     * Creates new Result object with supplied instances parameter.
   87.66 -     * @param instances to be used to return from the lookup
   87.67 -     */
   87.68 -    SimpleLookup(Collection<Object> instances) {
   87.69 -        allItems = new ArrayList<Item<?>>(instances.size());
   87.70 -
   87.71 -        for (Iterator i = instances.iterator(); i.hasNext();) {
   87.72 -            allItems.add(new InstanceContent.SimpleItem<Object>(i.next()));
   87.73 -        }
   87.74 -    }
   87.75 -
   87.76 -    <T,R> SimpleLookup(Collection<T> keys, InstanceContent.Convertor<? super T,R> conv) {
   87.77 -        allItems = new ArrayList<Item<?>>(keys.size());
   87.78 -
   87.79 -        for (T item : keys) {
   87.80 -            allItems.add(new InstanceContent.ConvertingItem<T,R>(item, conv));
   87.81 -        }
   87.82 -    }
   87.83 -
   87.84 -    public String toString() {
   87.85 -        return "SimpleLookup" + lookup(new Template<Object>(Object.class)).allInstances();
   87.86 -    }
   87.87 -
   87.88 -    public <T> Result<T> lookup(Template<T> template) {
   87.89 -        if (template == null) {
   87.90 -            throw new NullPointerException();
   87.91 -        }
   87.92 -
   87.93 -        return new SimpleResult<T>(template);
   87.94 -    }
   87.95 -
   87.96 -    public <T> T lookup(Class<T> clazz) {
   87.97 -        for (Iterator i = allItems.iterator(); i.hasNext();) {
   87.98 -            Object o = i.next();
   87.99 -
  87.100 -            if (o instanceof AbstractLookup.Pair) {
  87.101 -                AbstractLookup.Pair<?> p = (AbstractLookup.Pair<?>)o;
  87.102 -                if (p.instanceOf(clazz)) {
  87.103 -                    Object ret = p.getInstance();
  87.104 -                    if (clazz.isInstance(ret)) {
  87.105 -                        return clazz.cast(ret);
  87.106 -                    }
  87.107 -                }
  87.108 -            }
  87.109 -        }
  87.110 -        return null;
  87.111 -    }
  87.112 -
  87.113 -    /** A method that defines matching between Item and Template.
  87.114 -     * @param item the item to match
  87.115 -     * @return true if item matches the template requirements, false if not
  87.116 -     */
  87.117 -    private static boolean matches(Template<?> t, AbstractLookup.Pair<?> item) {
  87.118 -        if (!AbstractLookup.matches(t, item, true)) {
  87.119 -            return false;
  87.120 -        }
  87.121 -
  87.122 -        Class<?> type = t.getType();
  87.123 -
  87.124 -        if ((type != null) && !type.isAssignableFrom(item.getType())) {
  87.125 -            return false;
  87.126 -        }
  87.127 -
  87.128 -        return true;
  87.129 -    }
  87.130 -
  87.131 -    /**
  87.132 -     * Result used in SimpleLookup. It holds a reference to the collection
  87.133 -     * passed in constructor. As the contents of this lookup result never
  87.134 -     * changes the addLookupListener and removeLookupListener are empty.
  87.135 -     */
  87.136 -    private class SimpleResult<T> extends Lookup.Result<T> {
  87.137 -        /** can be null and is initialized lazily */
  87.138 -        private Set<Class<? extends T>> classes;
  87.139 -
  87.140 -        /** can be null and is initialized lazily */
  87.141 -        private Collection<? extends Item<T>> items;
  87.142 -
  87.143 -        /** Template used for this result. It is never null.*/
  87.144 -        private Template<T> template;
  87.145 -
  87.146 -        /** can be null and is initialized lazily */
  87.147 -        private Collection<T> results;
  87.148 -
  87.149 -        /** Just remembers the supplied argument in variable template.*/
  87.150 -        SimpleResult(Template<T> template) {
  87.151 -            this.template = template;
  87.152 -        }
  87.153 -
  87.154 -        /**
  87.155 -         * Intentionally does nothing because the lookup does not change
  87.156 -         * and no notification is needed.
  87.157 -         */
  87.158 -        public void addLookupListener(LookupListener l) {
  87.159 -        }
  87.160 -
  87.161 -        /**
  87.162 -         * Intentionally does nothing because the lookup does not change
  87.163 -         * and no notification is needed.
  87.164 -         */
  87.165 -        public void removeLookupListener(LookupListener l) {
  87.166 -        }
  87.167 -
  87.168 -        /**
  87.169 -         * Lazy initializes the results collection. Uses a call to allItems
  87.170 -         * to obtain the instances.
  87.171 -         */
  87.172 -        public java.util.Collection<? extends T> allInstances() {
  87.173 -            synchronized (this) {
  87.174 -                if (results != null) {
  87.175 -                    return results;
  87.176 -                }
  87.177 -            }
  87.178 -
  87.179 -
  87.180 -            Collection<T> res = new ArrayList<T>(allItems.size());
  87.181 -
  87.182 -            for (Item<T> item : allItems()) {
  87.183 -                res.add(item.getInstance());
  87.184 -            }
  87.185 -
  87.186 -            synchronized (this) {
  87.187 -                results = Collections.unmodifiableCollection(res);
  87.188 -            }
  87.189 -
  87.190 -            return results;
  87.191 -        }
  87.192 -
  87.193 -        /**
  87.194 -         * Lazy initializes variable classes. Uses a call to allItems to
  87.195 -         * compute the result.
  87.196 -         */
  87.197 -        public Set<Class<? extends T>> allClasses() {
  87.198 -            synchronized (this) {
  87.199 -                if (classes != null) {
  87.200 -                    return classes;
  87.201 -                }
  87.202 -            }
  87.203 -
  87.204 -            Set<Class<? extends T>> res = new HashSet<Class<? extends T>>();
  87.205 -
  87.206 -            for (Item<T> item : allItems()) {
  87.207 -                res.add(item.getType());
  87.208 -            }
  87.209 -
  87.210 -            synchronized (this) {
  87.211 -                classes = Collections.unmodifiableSet(res);
  87.212 -            }
  87.213 -
  87.214 -            return classes;
  87.215 -        }
  87.216 -
  87.217 -        /**
  87.218 -         * Lazy initializes variable items. Creates an item for each
  87.219 -         * element in the instances collection. It puts either SimpleItem
  87.220 -         * or ConvertingItem to the collection.
  87.221 -         */
  87.222 -        public Collection<? extends Item<T>> allItems() {
  87.223 -            synchronized (this) {
  87.224 -                if (items != null) {
  87.225 -                    return items;
  87.226 -                }
  87.227 -            }
  87.228 -
  87.229 -            Collection<Item<T>> res = new ArrayList<Item<T>>(allItems.size());
  87.230 -
  87.231 -            for (Iterator<Item<?>> i = allItems.iterator(); i.hasNext();) {
  87.232 -                Item<?> o = i.next();
  87.233 -
  87.234 -                if (o instanceof AbstractLookup.Pair) {
  87.235 -                    if (matches(template, (AbstractLookup.Pair) o)) {
  87.236 -                        res.add(cast(o));
  87.237 -                    }
  87.238 -                }
  87.239 -            }
  87.240 -
  87.241 -            synchronized (this) {
  87.242 -                items = Collections.unmodifiableCollection(res);
  87.243 -            }
  87.244 -
  87.245 -            return items;
  87.246 -        }
  87.247 -
  87.248 -        @SuppressWarnings("unchecked")
  87.249 -        private Item<T> cast(Item<?> i) {
  87.250 -            return (Item<T>)i;
  87.251 -        }
  87.252 -    }
  87.253 -}
    88.1 --- a/openide.util/src/org/openide/util/lookup/SimpleProxyLookup.java	Sat Oct 31 15:06:58 2009 +0100
    88.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.3 @@ -1,359 +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. Portions Copyright 1997-2006 Sun
   88.31 - * Microsystems, Inc. All Rights Reserved.
   88.32 - *
   88.33 - * If you wish your version of this file to be governed by only the CDDL
   88.34 - * or only the GPL Version 2, indicate your decision by adding
   88.35 - * "[Contributor] elects to include this software in this distribution
   88.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   88.37 - * single choice of license, a recipient has the option to distribute
   88.38 - * your version of this file under either the CDDL, the GPL Version 2 or
   88.39 - * to extend the choice of license to its licensees as provided above.
   88.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   88.41 - * Version 2 license, then the option applies only if the new code is
   88.42 - * made subject to such option by the copyright holder.
   88.43 - */
   88.44 -package org.openide.util.lookup;
   88.45 -
   88.46 -import java.lang.ref.Reference;
   88.47 -import java.lang.ref.WeakReference;
   88.48 -import org.openide.util.Lookup;
   88.49 -import org.openide.util.LookupEvent;
   88.50 -import org.openide.util.LookupListener;
   88.51 -
   88.52 -import java.util.*;
   88.53 -
   88.54 -
   88.55 -/**
   88.56 - * Simple proxy lookup. Keeps reference to a lookup it delegates to and
   88.57 - * forwards all requests.
   88.58 - *
   88.59 - * @author Jaroslav Tulach
   88.60 - */
   88.61 -final class SimpleProxyLookup extends org.openide.util.Lookup {
   88.62 -    /** the provider to check for the status */
   88.63 -    private Provider provider;
   88.64 -
   88.65 -    /** the lookup we currently delegate to */
   88.66 -    private Lookup delegate;
   88.67 -
   88.68 -    /** map of all templates to Reference (results) associated to this lookup */
   88.69 -    private WeakHashMap<Template<?>,Reference<ProxyResult<?>>> results;
   88.70 -
   88.71 -    /**
   88.72 -     * @param provider provider to delegate to
   88.73 -     */
   88.74 -    SimpleProxyLookup(Provider provider) {
   88.75 -        this.provider = provider;
   88.76 -    }
   88.77 -
   88.78 -    /** Checks whether we still delegate to the same lookup */
   88.79 -    private Lookup checkLookup() {
   88.80 -        Lookup l = provider.getLookup();
   88.81 -
   88.82 -        // iterator over Reference (ProxyResult)
   88.83 -        Iterator<Reference<ProxyResult<?>>> toCheck = null;
   88.84 -
   88.85 -        synchronized (this) {
   88.86 -            if (l != delegate) {
   88.87 -                this.delegate = l;
   88.88 -
   88.89 -                if (results != null) {
   88.90 -                    toCheck = new ArrayList<Reference<ProxyResult<?>>>(results.values()).iterator();
   88.91 -                }
   88.92 -            }
   88.93 -        }
   88.94 -
   88.95 -        if (toCheck != null) {
   88.96 -            // update
   88.97 -            ArrayList<Object> evAndListeners = new ArrayList<Object>();
   88.98 -            for (Iterator<Reference<ProxyResult<?>>> it = toCheck; it.hasNext(); ) {
   88.99 -                java.lang.ref.Reference<ProxyResult<?>> ref = it.next();
  88.100 -                if (ref == null) {
  88.101 -                    continue;
  88.102 -                }
  88.103 -
  88.104 -                ProxyResult<?> p = ref.get();
  88.105 -
  88.106 -                if (p != null && p.updateLookup(l)) {
  88.107 -                    p.collectFires(evAndListeners);
  88.108 -                }
  88.109 -            }
  88.110 -            
  88.111 -            for (Iterator it = evAndListeners.iterator(); it.hasNext(); ) {
  88.112 -                LookupEvent ev = (LookupEvent)it.next();
  88.113 -                LookupListener ll = (LookupListener)it.next();
  88.114 -                ll.resultChanged(ev);
  88.115 -            }
  88.116 -        }
  88.117 -
  88.118 -        return delegate;
  88.119 -    }
  88.120 -
  88.121 -    @SuppressWarnings("unchecked")
  88.122 -    private static <T> ProxyResult<T> cast(ProxyResult<?> p) {
  88.123 -        return (ProxyResult<T>)p;
  88.124 -    }
  88.125 -
  88.126 -    public <T> Result<T> lookup(Template<T> template) {
  88.127 -        synchronized (this) {
  88.128 -            if (results == null) {
  88.129 -                results = new WeakHashMap<Template<?>,Reference<ProxyResult<?>>>();
  88.130 -            } else {
  88.131 -                Reference<ProxyResult<?>> ref = results.get(template);
  88.132 -
  88.133 -                if (ref != null) {
  88.134 -                    ProxyResult<?> p = ref.get();
  88.135 -
  88.136 -                    if (p != null) {
  88.137 -                        return cast(p);
  88.138 -                    }
  88.139 -                }
  88.140 -            }
  88.141 -
  88.142 -            ProxyResult<T> p = new ProxyResult<T>(template);
  88.143 -            Reference<ProxyResult<?>> ref = new WeakReference<ProxyResult<?>>(p);
  88.144 -            results.put(template, ref);
  88.145 -
  88.146 -            return p;
  88.147 -        }
  88.148 -    }
  88.149 -
  88.150 -    public <T> T lookup(Class<T> clazz) {
  88.151 -        if (clazz == null) {
  88.152 -            checkLookup();
  88.153 -            return null;
  88.154 -        }
  88.155 -        return checkLookup().lookup(clazz);
  88.156 -    }
  88.157 -
  88.158 -    public <T> Item<T> lookupItem(Template<T> template) {
  88.159 -        return checkLookup().lookupItem(template);
  88.160 -    }
  88.161 -
  88.162 -    /**
  88.163 -     * Result used in SimpleLookup. It holds a reference to the collection
  88.164 -     * passed in constructor. As the contents of this lookup result never
  88.165 -     * changes the addLookupListener and removeLookupListener are empty.
  88.166 -     */
  88.167 -    private final class ProxyResult<T> extends WaitableResult<T> implements LookupListener {
  88.168 -        /** Template used for this result. It is never null.*/
  88.169 -        private Template<T> template;
  88.170 -
  88.171 -        /** result to delegate to */
  88.172 -        private Lookup.Result<T> delegate;
  88.173 -
  88.174 -        /** listeners set */
  88.175 -        private javax.swing.event.EventListenerList listeners;
  88.176 -        private LookupListener lastListener;
  88.177 -
  88.178 -        /** Just remembers the supplied argument in variable template.*/
  88.179 -        ProxyResult(Template<T> template) {
  88.180 -            this.template = template;
  88.181 -        }
  88.182 -
  88.183 -        /** Checks state of the result
  88.184 -         */
  88.185 -        private Result<T> checkResult() {
  88.186 -            updateLookup(checkLookup());
  88.187 -
  88.188 -            return this.delegate;
  88.189 -        }
  88.190 -
  88.191 -        /** Updates the state of the lookup.
  88.192 -         * @return true if the lookup really changed
  88.193 -         */
  88.194 -        public boolean updateLookup(Lookup l) {
  88.195 -            Collection<? extends Item<T>> oldPairs = (delegate != null) ? delegate.allItems() : null;
  88.196 -
  88.197 -            LookupListener removedListener;
  88.198 -
  88.199 -            synchronized (this) {
  88.200 -                if ((delegate != null) && (lastListener != null)) {
  88.201 -                    removedListener = lastListener;
  88.202 -                    delegate.removeLookupListener(lastListener);
  88.203 -                } else {
  88.204 -                    removedListener = null;
  88.205 -                }
  88.206 -            }
  88.207 -
  88.208 -            // cannot call to foreign code 
  88.209 -            Lookup.Result<T> res = l.lookup(template);
  88.210 -
  88.211 -            synchronized (this) {
  88.212 -                if (removedListener == lastListener) {
  88.213 -                    delegate = res;
  88.214 -                    lastListener = new WeakResult<T>(this, delegate);
  88.215 -                    delegate.addLookupListener(lastListener);
  88.216 -                }
  88.217 -            }
  88.218 -
  88.219 -            if (oldPairs == null) {
  88.220 -                // nobody knows about a change
  88.221 -                return false;
  88.222 -            }
  88.223 -
  88.224 -            Collection<? extends Item<T>> newPairs = delegate.allItems();
  88.225 -
  88.226 -            // See #34961 for explanation.
  88.227 -            if (!(oldPairs instanceof List)) {
  88.228 -                if (oldPairs == Collections.EMPTY_SET) {
  88.229 -                    // avoid allocation
  88.230 -                    oldPairs = Collections.emptyList();
  88.231 -                } else {
  88.232 -                    oldPairs = new ArrayList<Item<T>>(oldPairs);
  88.233 -                }
  88.234 -            }
  88.235 -
  88.236 -            if (!(newPairs instanceof List)) {
  88.237 -                newPairs = new ArrayList<Item<T>>(newPairs);
  88.238 -            }
  88.239 -
  88.240 -            return !oldPairs.equals(newPairs);
  88.241 -        }
  88.242 -
  88.243 -        public synchronized void addLookupListener(LookupListener l) {
  88.244 -            if (listeners == null) {
  88.245 -                listeners = new javax.swing.event.EventListenerList();
  88.246 -            }
  88.247 -
  88.248 -            listeners.add(LookupListener.class, l);
  88.249 -        }
  88.250 -
  88.251 -        public synchronized void removeLookupListener(LookupListener l) {
  88.252 -            if (listeners != null) {
  88.253 -                listeners.remove(LookupListener.class, l);
  88.254 -            }
  88.255 -        }
  88.256 -
  88.257 -        public java.util.Collection<? extends T> allInstances() {
  88.258 -            return checkResult().allInstances();
  88.259 -        }
  88.260 -
  88.261 -        public Set<Class<? extends T>> allClasses() {
  88.262 -            return checkResult().allClasses();
  88.263 -        }
  88.264 -
  88.265 -        public Collection<? extends Item<T>> allItems() {
  88.266 -            return checkResult().allItems();
  88.267 -        }
  88.268 -
  88.269 -        protected void beforeLookup(Lookup.Template t) {
  88.270 -            Lookup.Result r = checkResult();
  88.271 -
  88.272 -            if (r instanceof WaitableResult) {
  88.273 -                ((WaitableResult) r).beforeLookup(t);
  88.274 -            }
  88.275 -        }
  88.276 -
  88.277 -        /** A change in lookup occured.
  88.278 -         * @param ev event describing the change
  88.279 -         *
  88.280 -         */
  88.281 -        public void resultChanged(LookupEvent anEvent) {
  88.282 -            collectFires(null);
  88.283 -        } 
  88.284 -        
  88.285 -        protected void collectFires(Collection<Object> evAndListeners) {
  88.286 -            javax.swing.event.EventListenerList l = this.listeners;
  88.287 -
  88.288 -            if (l == null) {
  88.289 -                return;
  88.290 -            }
  88.291 -
  88.292 -            Object[] listeners = l.getListenerList();
  88.293 -
  88.294 -            if (listeners.length == 0) {
  88.295 -                return;
  88.296 -            }
  88.297 -
  88.298 -            LookupEvent ev = new LookupEvent(this);
  88.299 -            AbstractLookup.notifyListeners(listeners, ev, evAndListeners);
  88.300 -        }
  88.301 -    }
  88.302 -     // end of ProxyResult
  88.303 -    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
  88.304 -        private Lookup.Result source;
  88.305 -        private Reference<ProxyResult<T>> result;
  88.306 -        
  88.307 -        public WeakResult(ProxyResult<T> r, Lookup.Result<T> s) {
  88.308 -            this.result = new WeakReference<ProxyResult<T>>(r);
  88.309 -            this.source = s;
  88.310 -        }
  88.311 -        
  88.312 -        protected void beforeLookup(Lookup.Template t) {
  88.313 -            ProxyResult r = (ProxyResult)result.get();
  88.314 -            if (r != null) {
  88.315 -                r.beforeLookup(t);
  88.316 -            } else {
  88.317 -                source.removeLookupListener(this);
  88.318 -            }
  88.319 -        }
  88.320 -
  88.321 -        protected void collectFires(Collection<Object> evAndListeners) {
  88.322 -            ProxyResult<T> r = result.get();
  88.323 -            if (r != null) {
  88.324 -                r.collectFires(evAndListeners);
  88.325 -            } else {
  88.326 -                source.removeLookupListener(this);
  88.327 -            }
  88.328 -        }
  88.329 -
  88.330 -        public void addLookupListener(LookupListener l) {
  88.331 -            assert false;
  88.332 -        }
  88.333 -
  88.334 -        public void removeLookupListener(LookupListener l) {
  88.335 -            assert false;
  88.336 -        }
  88.337 -
  88.338 -        public Collection<T> allInstances() {
  88.339 -            assert false;
  88.340 -            return null;
  88.341 -        }
  88.342 -
  88.343 -        public void resultChanged(LookupEvent ev) {
  88.344 -            ProxyResult r = (ProxyResult)result.get();
  88.345 -            if (r != null) {
  88.346 -                r.resultChanged(ev);
  88.347 -            } else {
  88.348 -                source.removeLookupListener(this);
  88.349 -            }
  88.350 -        }
  88.351 -
  88.352 -        public Collection<? extends Item<T>> allItems() {
  88.353 -            assert false;
  88.354 -            return null;
  88.355 -        }
  88.356 -
  88.357 -        public Set<Class<? extends T>> allClasses() {
  88.358 -            assert false;
  88.359 -            return null;
  88.360 -        }
  88.361 -    } // end of WeakResult
  88.362 -}
    89.1 --- a/openide.util/src/org/openide/util/lookup/SingletonLookup.java	Sat Oct 31 15:06:58 2009 +0100
    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.openide.util.lookup;
   89.44 -
   89.45 -import java.util.Collection;
   89.46 -import java.util.Collections;
   89.47 -import java.util.Set;
   89.48 -import org.openide.util.Lookup;
   89.49 -import org.openide.util.LookupListener;
   89.50 -
   89.51 -/**
   89.52 - * Unmodifiable lookup that contains just one fixed object.
   89.53 - *
   89.54 - * @author Marian Petras
   89.55 - */
   89.56 -class SingletonLookup extends Lookup {
   89.57 -
   89.58 -    private final Object objectToLookup;
   89.59 -    private final String id;
   89.60 -
   89.61 -    SingletonLookup(Object objectToLookup) {
   89.62 -        this(objectToLookup, null);
   89.63 -    }
   89.64 -
   89.65 -    SingletonLookup(Object objectToLookup, String id) {
   89.66 -        if (objectToLookup == null) {
   89.67 -            throw new IllegalArgumentException("null");                 //NOI18N
   89.68 -        }
   89.69 -
   89.70 -        this.objectToLookup = objectToLookup;
   89.71 -        this.id = id;
   89.72 -    }
   89.73 -
   89.74 -    @Override
   89.75 -    public <T> T lookup(Class<T> clazz) {
   89.76 -        if (clazz == null) {
   89.77 -            throw new IllegalArgumentException("null");                 //NOI18N
   89.78 -        }
   89.79 -
   89.80 -        return (clazz.isInstance(objectToLookup))
   89.81 -               ? clazz.cast(objectToLookup)
   89.82 -               : null;
   89.83 -    }
   89.84 -
   89.85 -    @Override
   89.86 -    public <T> Result<T> lookup(Template<T> template) {
   89.87 -        if (template == null) {
   89.88 -            throw new IllegalArgumentException("null");                 //NOI18N
   89.89 -        }
   89.90 -
   89.91 -        Lookup.Item<T> item = lookupItem(template);
   89.92 -        if (item != null) {
   89.93 -            return new SingletonResult<T>(item);
   89.94 -        } else {
   89.95 -            return Lookup.EMPTY.lookup(template);
   89.96 -        }
   89.97 -    }
   89.98 -
   89.99 -    @Override
  89.100 -    public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
  89.101 -        if (clazz == null) {
  89.102 -            throw new IllegalArgumentException("null");                 //NOI18N
  89.103 -        }
  89.104 -
  89.105 -        return (clazz.isInstance(objectToLookup))
  89.106 -               ? Collections.singletonList(clazz.cast(objectToLookup))
  89.107 -               : Collections.<T>emptyList();
  89.108 -    }
  89.109 -
  89.110 -    @Override
  89.111 -    @SuppressWarnings("unchecked")
  89.112 -    public <T> Item<T> lookupItem(Template<T> template) {
  89.113 -        if (template == null) {
  89.114 -            throw new IllegalArgumentException("null");                 //NOI18N
  89.115 -        }
  89.116 -
  89.117 -        String templateId = template.getId();
  89.118 -        if ((templateId != null) && !templateId.equals(id)) {
  89.119 -            return null;
  89.120 -        }
  89.121 -
  89.122 -        Object templateInst = template.getInstance();
  89.123 -        if ((templateInst != null) && (objectToLookup != templateInst)) {
  89.124 -            return null;
  89.125 -        }
  89.126 -
  89.127 -        Class<T> clazz = template.getType();
  89.128 -        if ((clazz != null) && !clazz.isInstance(objectToLookup)) {
  89.129 -            return null;
  89.130 -        }
  89.131 -
  89.132 -        Lookup.Item<T> item;
  89.133 -        if (clazz != null) {
  89.134 -            item = Lookups.lookupItem(clazz.cast(objectToLookup), id);
  89.135 -        } else {
  89.136 -            item = Lookups.lookupItem((T) objectToLookup, id);
  89.137 -        }
  89.138 -        return item;
  89.139 -    }
  89.140 -
  89.141 -    static class SingletonResult<T> extends Lookup.Result<T> {
  89.142 -
  89.143 -        private final Lookup.Item<T> item;
  89.144 -
  89.145 -        SingletonResult(Lookup.Item<T> item) {
  89.146 -            this.item = item;
  89.147 -        }
  89.148 -
  89.149 -        @Override
  89.150 -        public void addLookupListener(LookupListener l) {
  89.151 -            // this result never changes - no need to register a listener
  89.152 -        }
  89.153 -
  89.154 -        @Override
  89.155 -        public void removeLookupListener(LookupListener l) {
  89.156 -            // this result never changes - no need to register a listener
  89.157 -        }
  89.158 -
  89.159 -        @Override
  89.160 -        public Set<Class<? extends T>> allClasses() {
  89.161 -            return Collections.<Class<? extends T>>singleton(item.getType());
  89.162 -        }
  89.163 -
  89.164 -        @Override
  89.165 -        public Collection<? extends Item<T>> allItems() {
  89.166 -            return Collections.singletonList(item);
  89.167 -        }
  89.168 -
  89.169 -        @Override
  89.170 -        public Collection<? extends T> allInstances() {
  89.171 -            return Collections.singletonList(item.getInstance());
  89.172 -        }
  89.173 -
  89.174 -    }
  89.175 -
  89.176 -}
    90.1 --- a/openide.util/src/org/openide/util/lookup/WaitableResult.java	Sat Oct 31 15:06:58 2009 +0100
    90.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.3 @@ -1,62 +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 -package org.openide.util.lookup;
   90.45 -
   90.46 -import java.util.Collection;
   90.47 -import org.openide.util.Lookup;
   90.48 -
   90.49 -
   90.50 -/** A special subclass of lookup that is able to wait before queries.
   90.51 - *
   90.52 - * @author  Jaroslav Tulach
   90.53 - */
   90.54 -abstract class WaitableResult<T> extends Lookup.Result<T> {
   90.55 -    /** Used by proxy results to synchronize before lookup.
   90.56 -     */
   90.57 -    protected abstract void beforeLookup(Lookup.Template t);
   90.58 -
   90.59 -    /** Needed to group notification of outside the package listeners
   90.60 -     * after all AbstractLookup and ProxyLookups have been updated.
   90.61 -     * @param evAndListeners LookupEvent, LookupListener, LookupEvent, LookupListener, etc.
   90.62 -     */
   90.63 -    protected abstract void collectFires(Collection<Object> evAndListeners);
   90.64 -     
   90.65 -}
    91.1 --- a/openide.util/src/org/openide/util/lookup/doc-files/index.html	Sat Oct 31 15:06:58 2009 +0100
    91.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.3 @@ -1,208 +0,0 @@
    91.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    91.5 -<!--
    91.6 -   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    91.7 -   -
    91.8 -   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    91.9 -   -
   91.10 -   - The contents of this file are subject to the terms of either the GNU
   91.11 -   - General Public License Version 2 only ("GPL") or the Common
   91.12 -   - Development and Distribution License("CDDL") (collectively, the
   91.13 -   - "License"). You may not use this file except in compliance with the
   91.14 -   - License. You can obtain a copy of the License at
   91.15 -   - http://www.netbeans.org/cddl-gplv2.html
   91.16 -   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   91.17 -   - specific language governing permissions and limitations under the
   91.18 -   - License.  When distributing the software, include this License Header
   91.19 -   - Notice in each file and include the License file at
   91.20 -   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   91.21 -   - particular file as subject to the "Classpath" exception as provided
   91.22 -   - by Sun in the GPL Version 2 section of the License file that
   91.23 -   - accompanied this code. If applicable, add the following below the
   91.24 -   - License Header, with the fields enclosed by brackets [] replaced by
   91.25 -   - your own identifying information:
   91.26 -   - "Portions Copyrighted [year] [name of copyright owner]"
   91.27 -   -
   91.28 -   - Contributor(s):
   91.29 -   -
   91.30 -   - The Original Software is NetBeans. The Initial Developer of the Original
   91.31 -   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   91.32 -   - Microsystems, Inc. All Rights Reserved.
   91.33 -   -
   91.34 -   - If you wish your version of this file to be governed by only the CDDL
   91.35 -   - or only the GPL Version 2, indicate your decision by adding
   91.36 -   - "[Contributor] elects to include this software in this distribution
   91.37 -   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   91.38 -   - single choice of license, a recipient has the option to distribute
   91.39 -   - your version of this file under either the CDDL, the GPL Version 2 or
   91.40 -   - to extend the choice of license to its licensees as provided above.
   91.41 -   - However, if you add GPL Version 2 code and therefore, elected the GPL
   91.42 -   - Version 2 license, then the option applies only if the new code is
   91.43 -   - made subject to such option by the copyright holder.
   91.44 -  -->
   91.45 -<HTML>
   91.46 -<HEAD>
   91.47 -<TITLE>Lookup Library</TITLE>
   91.48 -<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
   91.49 -</HEAD>
   91.50 -<BODY>
   91.51 -
   91.52 -<P>
   91.53 -
   91.54 -This is the home page of the <em>lookup library</em> implementation, which 
   91.55 -is intended to solve a general problem that every <cite>component-based system</CITE>
   91.56 -has had to face: how different components <b>register</b> to the system 
   91.57 -and how other parts of the system can <b>look</b> them <b>up</B>. 
   91.58 -<P>
   91.59 -There already are libraries trying to solve this problem, usually by querying for 
   91.60 -an interface and finding its appropriate implementaion. The most famous is 
   91.61 -<A href="http://www.jini.org/">Jini</A>, the platform for development of
   91.62 -distributed network services. Our library does something similar, but tries 
   91.63 -to stay small and easy
   91.64 -to use. The NetBeans <em>Lookup
   91.65 -Library</EM>'s main focus is a modular application consisting of independent modules
   91.66 -that want to communicate with each other. It does not try to solve networking or
   91.67 -legacy application integration. It is simple but powerful.
   91.68 -
   91.69 -<H2>Why would you want to use it?</H2>
   91.70 -
   91.71 -A well-written modular program separates <em>development</EM>
   91.72 -and <em>deployment</EM>.
   91.73 -There are many situations where a component needs some functionality but
   91.74 -does not actually care about the implementation. It is up to the <em>system
   91.75 -adminstrator</em> that deploys (installs) the application to decide which 
   91.76 -implementation to use.
   91.77 -<P>
   91.78 -The most simple and most often used method for allowing other implementations
   91.79 -to be plugged in is the <em>system property</em> pattern:
   91.80 -
   91.81 -<pre>
   91.82 -    <font class="keyword">public</font> <font class="type">Toolkit</font> <font class="function-name">getDefaultToolkit</font> () {
   91.83 -        java.awt.<font class="type">Toolkit</font> <font class="variable-name">t</font> = <font class="constant">null</font>;
   91.84 -        <font class="type">String</font> <font class="variable-name">classname</font> = System.getProperty (<font class="string">"java.awt.Toolkit"</font>);
   91.85 -        <font class="keyword">if</font> (classname != <font class="constant">null</font>) {
   91.86 -            <font class="keyword">try</font> {
   91.87 -                <font class="type">Class</font> <font class="variable-name">c</font> = Class.forName (classname);
   91.88 -                t = (java.awt.<font class="type">Toolkit</font>)c.newInstance ();
   91.89 -            } <font class="keyword">catch</font> (<font class="type">Exception</font> <font class="variable-name">ex</font>) {
   91.90 -                System.out.println (<font class="string">"Cannot initialize toolkit: "</font> + classname);
   91.91 -                ex.printStackTrace ();
   91.92 -            }
   91.93 -        }
   91.94 -        <font class="comment">// fallback </font>
   91.95 -        <font class="keyword">if</font> (t == <font class="constant">null</font>) {
   91.96 -            t = <font class="keyword">new</font> <font class="type">GenericAWTToolkit</font> ();
   91.97 -        }
   91.98 -    }
   91.99 -</pre>
  91.100 -
  91.101 -    
  91.102 -The idea is simple. The <em>deployer</em> can start the Java VM with the flag
  91.103 -<code>-Djava.awt.Toolkit=org.myorg.MyToolkit</code> where the <code>MyToolkit</code>
  91.104 -is his class with default constructor and the code in the <code>getDefaultToolkit</CODE>
  91.105 -method will instantiate the class and use it.
  91.106 -<P>
  91.107 -In principle this is general enough of a solution and works well, except that writing the 
  91.108 -code above is error prone and it also requires passing the arguments to the virtual machine. 
  91.109 -It would be much nicer if the registation could be done just by putting a JAR file with the <code>MyToolkit</code> class
  91.110 -into the application classpath.
  91.111 -<P>
  91.112 -Actually this has been realized also by the JDK development team and addressed in
  91.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>. 
  91.114 -The <code>MyToolkit</code> could be registered by adding a file 
  91.115 -<code>/META-INF/services/java.awt.Toolkit</code> with one line
  91.116 -<code>org.myorg.MyToolkit</code> into the JAR file that contains the
  91.117 -<code>MyToolkit</CODE> implementation. The code in <code>getDefaultToolkit</CODE>
  91.118 -will scan all JAR files in classpath and search for that file,
  91.119 -create an instance of <code>MyToolkit</code> and use it. 
  91.120 -The deployer can influence which toolkit will be created by 
  91.121 -adding the right JAR files into the classpath.
  91.122 -<P>
  91.123 -Of course the code to access the <code>META-INF/services/</code> files is even
  91.124 -more error prone than the <em>property pattern</EM>.  And this is exactly the
  91.125 -place where the <em>lookup library</em> can help. It provides an implementation of
  91.126 -the search algorithm with an easy interface. Just write:
  91.127 -<pre>
  91.128 -    <font class="keyword">import</font> <font class="type">java.awt.Toolkit</font>;
  91.129 -    <font class="keyword">import</font> <font class="type">org.openide.util.Lookup;</font>;
  91.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>);
  91.131 -</PRE>
  91.132 -and if the JAR with <code>MyToolkit</CODE> is in the class path, the simple call 
  91.133 -above will do the rest.
  91.134 -<P>
  91.135 -So whenever one writes an application divided into several independent modules (jar files)
  91.136 -that are being developed and deployed independently, there is a need for registering
  91.137 -and discovering components. First of all, a set of interfaces can be defined to enable 
  91.138 -inter-module communication (like the abstract class <code>java.awt.Toolkit</CODE>).
  91.139 -After that a set of modules providing implementation can written (<code>MyToolkit</code> and other concurent implementations)
  91.140 -and after that, whenever a module trying to utilitize the functionality wants to access
  91.141 -the <code>Toolkit</code> via lookup, the real implementation is returned.
  91.142 -<P>
  91.143 -It is the responsibility of lookup to find a suitable implementation of the
  91.144 -requested service and return an object implementing the service. This is the
  91.145 -the basic functionality and while the library provides you with a little bit
  91.146 -more, even this simple usage might be extremaly useful: the client code knows
  91.147 -nothing about the implementation and the implementation can be switched in
  91.148 -deployment time by simply replacing one implementation jar with other. There
  91.149 -is no code change required.
  91.150 -
  91.151 -<H2> Local lookup usage </H2>
  91.152 -The example in previous paragraph demostrated the usage of lookup as a global
  91.153 -registry (by using the <CODE>Lookup.getDefault()</CODE> call). One can also
  91.154 -consider another scenario where the lookup can help.
  91.155 -<P>
  91.156 -Let's switch hats to be an API designer for a while. The goal is to introduce a
  91.157 -new object into the system. But you either are not sure yet what all the roles
  91.158 -of the new object will be or you (more importantly) want to be able to add (or
  91.159 -change) roles of the object dynamically. So why not to introduce following
  91.160 -method to the object's interface:
  91.161 -<pre>
  91.162 -<font class="keyword">public class </FONT> <font class="type">MorphingObject</FONT> {
  91.163 -    <font class="keyword">public</FONT> <font class="type"><a href="@TOP@org/openide/util/Lookup.html">Lookup</A></FONT> getLookup() {
  91.164 -        <font class="keyword">return</FONT> <font class="variable-name">myLookup;</FONT>
  91.165 -    }
  91.166 -    ...
  91.167 -}
  91.168 -</pre>
  91.169 -By exposing the method getLookup you can attach different functionality to the
  91.170 -MorphingObject at runtime and whoever gets a reference to your object can ask it
  91.171 -whether the object supports a given interface like this:
  91.172 -<pre>
  91.173 -<font class="type">MorphingObject</FONT> <font class="variable-name">morph</FONT> = ...
  91.174 -<font class="type">AnInterface</font> <font class="variable-name">impl</font> = (<font
  91.175 -class="type">AnInterface</font>)morph.getLookup().<a
  91.176 -href="@TOP@org/openide/util/Lookup.html#lookup(java.lang.Class)">lookup</a>(AnInterface.<font class="keyword">class</font>);
  91.177 -<font class="keyword">if</font> (impl == <font class="constant">null</font>) {
  91.178 -    <font class="keyword">return;</font><font class="comment">/* AnInterface not supported now! */</font>
  91.179 -}
  91.180 -impl.useIt();
  91.181 -</PRE>
  91.182 -
  91.183 -<H2>Additional functionality</H2>
  91.184 -The NetBeans lookup library also provides:
  91.185 -<UL>
  91.186 -<LI>Support for dynamically changing the lookup content.</LI>
  91.187 -<LI>The ability to return multiple results.</LI>
  91.188 -<LI>Notification of changes. After retrieving the result, the client can attach a
  91.189 -listener and be notified when the result of the lookup is changed.</LI>
  91.190 -<LI>Lazy initialization of the implementation. The implementation objects are
  91.191 -initialized only after someone asks for them. Even the implementation classes
  91.192 -are not loaded if they are not going to be used! </LI>
  91.193 -</UL>
  91.194 -
  91.195 -<H2>Further information</H2>
  91.196 -<UL>
  91.197 -  <LI><A HREF="lookup-api.html">Lookup Library APIs</A> for those writing the client code.
  91.198 -Specifying the query, getting the result and listenning on changes.</LI>
  91.199 -  <LI><A HREF="lookup-spi.html">Lookup Library SPIs</A> for those writing the
  91.200 -implementaion code and registering it with lookup. Includes also writing own
  91.201 -lookup implementation.</LI>
  91.202 -  <LI>Download <A HREF="http://www.netbeans.org/">NetBeans platform</A> which
  91.203 -contains <code>org-openide-util.jar</code></LI>
  91.204 -    <A HREF="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/lookup/">
  91.205 -    implementation package (org.openide.util.lookup) </A>
  91.206 -    + classes Lookup, LookupEvent, LookupListener in
  91.207 -    <A href="http://hg.netbeans.org/main-golden/file/tip/openide.util/src/org/openide/util/">util package</A></LI>
  91.208 -  <li><a href="http://www.martinfowler.com/articles/injection.html">Inversion of Control Containers and the Dependency Injection pattern</a> (Martin Fowler)</li>
  91.209 -</UL>
  91.210 -</BODY>
  91.211 -</HTML>
    92.1 --- a/openide.util/src/org/openide/util/lookup/doc-files/lookup-api.html	Sat Oct 31 15:06:58 2009 +0100
    92.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.3 @@ -1,188 +0,0 @@
    92.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    92.5 -<!--
    92.6 -   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    92.7 -   -
    92.8 -   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    92.9 -   -
   92.10 -   - The contents of this file are subject to the terms of either the GNU
   92.11 -   - General Public License Version 2 only ("GPL") or the Common
   92.12 -   - Development and Distribution License("CDDL") (collectively, the
   92.13 -   - "License"). You may not use this file except in compliance with the
   92.14 -   - License. You can obtain a copy of the License at
   92.15 -   - http://www.netbeans.org/cddl-gplv2.html
   92.16 -   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   92.17 -   - specific language governing permissions and limitations under the
   92.18 -   - License.  When distributing the software, include this License Header
   92.19 -   - Notice in each file and include the License file at
   92.20 -   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   92.21 -   - particular file as subject to the "Classpath" exception as provided
   92.22 -   - by Sun in the GPL Version 2 section of the License file that
   92.23 -   - accompanied this code. If applicable, add the following below the
   92.24 -   - License Header, with the fields enclosed by brackets [] replaced by
   92.25 -   - your own identifying information:
   92.26 -   - "Portions Copyrighted [year] [name of copyright owner]"
   92.27 -   -
   92.28 -   - Contributor(s):
   92.29 -   -
   92.30 -   - The Original Software is NetBeans. The Initial Developer of the Original
   92.31 -   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   92.32 -   - Microsystems, Inc. All Rights Reserved.
   92.33 -   -
   92.34 -   - If you wish your version of this file to be governed by only the CDDL
   92.35 -   - or only the GPL Version 2, indicate your decision by adding
   92.36 -   - "[Contributor] elects to include this software in this distribution
   92.37 -   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   92.38 -   - single choice of license, a recipient has the option to distribute
   92.39 -   - your version of this file under either the CDDL, the GPL Version 2 or
   92.40 -   - to extend the choice of license to its licensees as provided above.
   92.41 -   - However, if you add GPL Version 2 code and therefore, elected the GPL
   92.42 -   - Version 2 license, then the option applies only if the new code is
   92.43 -   - made subject to such option by the copyright holder.
   92.44 -  -->
   92.45 -<HTML>
   92.46 -<HEAD>
   92.47 -<TITLE>Lookup Library API</TITLE>
   92.48 -<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
   92.49 -</HEAD>
   92.50 -<BODY>
   92.51 -<H1>Lookup library API</H1>
   92.52 -<p>
   92.53 -This document describes usage of the API provided by the Lookup Library. In this
   92.54 -document we assume that someone has already provided us with a lookup
   92.55 -implementation (for those seeking how to write a lookup implementation please
   92.56 -check <A href="lookup-spi.html">the SPI document</A>).
   92.57 -
   92.58 -<H2> Getting the lookup </H2>
   92.59 -
   92.60 -The first question you might ask is this: how can I get hold of a
   92.61 -lookup instance? There are basically two ways how you can get it.
   92.62 -
   92.63 -<H3> Global lookup </H3>
   92.64 -As you can see in the
   92.65 -
   92.66 -<a href="@TOP@org/openide/util/Lookup.html">Lookup</a>
   92.67 -
   92.68 -Javadoc there is a static method
   92.69 -
   92.70 -<pre><a href="@TOP@org/openide/util/Lookup.html#getDefault()">public static Lookup getDefault()</a></pre>
   92.71 -
   92.72 -The object returned from this method is
   92.73 -a global lookup that can serve as a central place for registering services.
   92.74 -The default implementation is a lookup that implements
   92.75 -<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">
   92.76 -the JDK JAR services</A>
   92.77 -mechanism and delegates to <samp>META-INF/services/name.of.Class</samp> files.
   92.78 -<P>
   92.79 -If you want to add your class to this lookup just create a file in your
   92.80 -jar file under the <code>META-INF</code> directory (e.g. <samp>META-INF/services/com.my.APIClass</samp>)
   92.81 -and let the file contain only one line of text
   92.82 -
   92.83 -<pre>com.foo.impl.ImplOfTheAPI</pre>
   92.84 -
   92.85 -<p>(This is more easily done using the <code>@ServiceProvider</code> annotation.)</p>
   92.86 -
   92.87 -The following code will return you a newly created instance of
   92.88 -<code>com.foo.impl.ImplOfTheAPI</code>:
   92.89 -
   92.90 -<PRE>
   92.91 -   <font class="keyword">import</FONT> org.openide.util.Lookup;
   92.92 -   return Lookup.getDefault().lookup(com.my.APIClass.class);
   92.93 -</PRE>
   92.94 -
   92.95 -<H3> Local lookup </H3>
   92.96 -
   92.97 -This is just a reminder that whenever you find a method called getLookup
   92.98 -or similar returning a lookup instance, the provided lookup is <EM>not</EM> the
   92.99 -general lookup described in the previous paragraph. Rather, it is a private lookup
  92.100 -implementation that is usually bound to the object you invoked the method on.
  92.101 -
  92.102 -<H2> Use of Lookup.Template and Lookup.Result </H2>
  92.103 -
  92.104 -There are more ways how you can ask lookup besides the variant with one class
  92.105 -parameter. If you want more functionality, you have to implement the interface
  92.106 -Lookup.Template and pass an instance of such object to the lookup call.
  92.107 -<p>
  92.108 -<EM>Note:</EM> If you use Lookup.Template, the object returned from the lookup is
  92.109 -<EM>not</EM> the object you are looking for but rather a result object
  92.110 -(Lookup.Result). You can call methods on such a result object to get the actual
  92.111 -results.
  92.112 -<p>
  92.113 -Let's examine following example:
  92.114 -
  92.115 -<pre>
  92.116 -        <font class="keyword">import</FONT> org.openide.util.Lookup;
  92.117 -
  92.118 -        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
  92.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>);
  92.120 -        Lookup.<font class="type">Result</font> <font class="variable-name">result</font> = lookup.lookup(template);
  92.121 -        <font class="type">Collection</font> <font class="variable-name">c</font> = result.allInstances();
  92.122 -        <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = c.iterator(); i.hasNext(); ) {
  92.123 -            <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
  92.124 -            s.callMyService();
  92.125 -        }
  92.126 -</pre>
  92.127 -
  92.128 -In this example the call to method lookup(...) returns immediately because the
  92.129 -result object can be constructed even without real results. The first time you
  92.130 -ask for the result object by calling r.allInstances(), the lookup has to supply you
  92.131 -the real results and this method can block until the required data are really
  92.132 -available.
  92.133 -<p>
  92.134 -If you are not interested in all objects as in the previous example, you can use the
  92.135 -template to ask for one resulting object (wrapped in special Item instance):
  92.136 -<pre>
  92.137 -        <font class="keyword">import</FONT> org.openide.util.Lookup;
  92.138 -
  92.139 -        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
  92.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>);
  92.141 -        Lookup.<font class="type">Item</font> <font class="variable-name">item</font> = lookup.lookupItem(template);
  92.142 -        <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)item.getInstance();
  92.143 -        s.callMyService();
  92.144 -</pre>
  92.145 -
  92.146 -Again, the Item object can construct the real instance only if you call
  92.147 -getInstance. The item can be useful even without calling getInstance - you can get
  92.148 -its display name or an unique id. You can use this information, for example, for
  92.149 -constructing menu items without the need to instantiate (or even load!)
  92.150 -the class implementing the functionality. Only when the real functionality is
  92.151 -needed (e.g. the user has selected the menu item) you can call getInstance
  92.152 -and call the real meat of the implementation.
  92.153 -
  92.154 -<H2> Listenning on lookup changes </H2>
  92.155 -There is one additional piece of functionality bound to the Lookup.Result object worth
  92.156 -mentioning: you can attach a listener to it and be informed about any changes in
  92.157 -the lookup. This might be extremly usefull when the lookup dynamically changes
  92.158 -(from other threads). The listener can keep state of your object up-to-date even
  92.159 -in cases where the lookup changes asynchronously.
  92.160 -<p>
  92.161 -So here is some sample code using the listenner:
  92.162 -
  92.163 -<pre>
  92.164 -        <font class="keyword">import</FONT> org.openide.util.Lookup;
  92.165 -        <font class="keyword">import</FONT> org.openide.util.LookupListener;
  92.166 -        <font class="keyword">import</FONT> org.openide.util.LookupEvent;
  92.167 -
  92.168 -        <font class="type">Lookup</font> <font class="variable-name">lookup</font> = ...;
  92.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>);
  92.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);
  92.171 -        result.addLookupListener(<font class="keyword">new</font> <font class="type">LookupListener</font>() {
  92.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>) {
  92.173 -                reaction(result);
  92.174 -            }
  92.175 -        });
  92.176 -        reaction(result);
  92.177 -    }
  92.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>) {
  92.179 -        <font class="keyword">for</font> (<font class="type">Iterator</font> <font class="variable-name">i</font> = r.allInstances().iterator(); i.hasNext(); ) {
  92.180 -            <font class="type">MyService</font> <font class="variable-name">s</font> = (<font class="type">MyService</font>)i.next();
  92.181 -            s.callMyService();
  92.182 -        }
  92.183 -    }
  92.184 -</pre>
  92.185 -
  92.186 -Please note that we first attach a listener and then call the reaction method.
  92.187 -This ensures that we always get the newest possible state. Also you must be
  92.188 -careful in the reaction method since it can be called from two different
  92.189 -threads simultaneously (your code has to be prepared for this).
  92.190 -</BODY>
  92.191 -</HTML>
    93.1 --- a/openide.util/src/org/openide/util/lookup/doc-files/lookup-spi.html	Sat Oct 31 15:06:58 2009 +0100
    93.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.3 @@ -1,147 +0,0 @@
    93.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    93.5 -<!--
    93.6 -   - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    93.7 -   -
    93.8 -   - Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    93.9 -   -
   93.10 -   - The contents of this file are subject to the terms of either the GNU
   93.11 -   - General Public License Version 2 only ("GPL") or the Common
   93.12 -   - Development and Distribution License("CDDL") (collectively, the
   93.13 -   - "License"). You may not use this file except in compliance with the
   93.14 -   - License. You can obtain a copy of the License at
   93.15 -   - http://www.netbeans.org/cddl-gplv2.html
   93.16 -   - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   93.17 -   - specific language governing permissions and limitations under the
   93.18 -   - License.  When distributing the software, include this License Header
   93.19 -   - Notice in each file and include the License file at
   93.20 -   - nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   93.21 -   - particular file as subject to the "Classpath" exception as provided
   93.22 -   - by Sun in the GPL Version 2 section of the License file that
   93.23 -   - accompanied this code. If applicable, add the following below the
   93.24 -   - License Header, with the fields enclosed by brackets [] replaced by
   93.25 -   - your own identifying information:
   93.26 -   - "Portions Copyrighted [year] [name of copyright owner]"
   93.27 -   -
   93.28 -   - Contributor(s):
   93.29 -   -
   93.30 -   - The Original Software is NetBeans. The Initial Developer of the Original
   93.31 -   - Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   93.32 -   - Microsystems, Inc. All Rights Reserved.
   93.33 -   -
   93.34 -   - If you wish your version of this file to be governed by only the CDDL
   93.35 -   - or only the GPL Version 2, indicate your decision by adding
   93.36 -   - "[Contributor] elects to include this software in this distribution
   93.37 -   - under the [CDDL or GPL Version 2] license." If you do not indicate a
   93.38 -   - single choice of license, a recipient has the option to distribute
   93.39 -   - your version of this file under either the CDDL, the GPL Version 2 or
   93.40 -   - to extend the choice of license to its licensees as provided above.
   93.41 -   - However, if you add GPL Version 2 code and therefore, elected the GPL
   93.42 -   - Version 2 license, then the option applies only if the new code is
   93.43 -   - made subject to such option by the copyright holder.
   93.44 -  -->
   93.45 -<HTML>
   93.46 -<HEAD>
   93.47 -<TITLE>Lookup Library SPI</TITLE>
   93.48 -<link rel="Stylesheet" href="@TOP@/prose.css" type="text/css" title="NetBeans Open APIs Style">
   93.49 -</HEAD>
   93.50 -<BODY>
   93.51 -<H1>Lookup library SPI</H1>
   93.52 -This document describe usage of the SPI provided by the Lookup Library
   93.53 -(for those seeking how to use lookup instance please
   93.54 -check <A href="lookup-api.html">the API document</A>).
   93.55 -<p>
   93.56 -By using the SPI you can create lookups that can be used by the users of the
   93.57 -Lookup API. While the Lookup API consists of a couple of classes in the package
   93.58 -<em>org.openide.util.*</EM>,
   93.59 -the SPI has its own package <em>org.openide.util.lookup.*</EM>.
   93.60 -
   93.61 -<H2> Simple lookups </H2>
   93.62 -Let us start with the simplest case. You have decided that your newly created
   93.63 -object will provide an API in the form of a getLookup() method. You have to
   93.64 -return a functional lookup from this call. You can use static methods in class
   93.65 -<a href="@TOP@org/openide/util/lookup/Lookups.html">
   93.66 -<code>Lookups</code></A> to create a lookup for you. If you want only one
   93.67 -object to be returned, just call 
   93.68 -<a href="@TOP@org/openide/util/lookup/Lookups.html#singleton(java.lang.Object)">
   93.69 -<code>Lookups.singleton(x)</code></A> where x is the object to be 
   93.70 -returned by the lookup. Or if you want to supply more objects, use a call to the method
   93.71 -<a href="@TOP@org/openide/util/lookup/Lookups.html#fixed(java.lang.Object...)">
   93.72 -<code>fixed(Object []x)</CODE></A>.
   93.73 -<EM> Note: </EM> The lookups returned from methods <code>singleton(...)</code> and
   93.74 -<code>fixed(...)</code> do <EM>
   93.75 -not </EM> support dynamic changes and attaching listeners. Their content is
   93.76 -fixed from the time you call the creating method.
   93.77 -
   93.78 -<H2> ProxyLookup </H2>
   93.79 -There can be situations where you get a lookup object from someone else and you
   93.80 -want your lookup to return exactly the instances from the original lookup plus
   93.81 -your own results. Here the class ProxyLookup comes into the play.
   93.82 -<p>
   93.83 -You simply create a new lookup like this:
   93.84 -
   93.85 -<pre>
   93.86 -    <font class="keyword">import</FONT> org.openide.util.Lookup;
   93.87 -    <font class="keyword">import</FONT> org.openide.util.lookup.*;
   93.88 -
   93.89 -    <font class="type">Lookup</font> <font class="variable-name">lookup1</font> = ...;
   93.90 -
   93.91 -    <font class="type">Lookup</font> <font class="variable-name">lookup2</font> = Lookups.singleton(MyService.<font class="keyword">class</font>);
   93.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 });
   93.93 -</pre>
   93.94 -
   93.95 -<H2> AbstractLookup </H2>
   93.96 -<!-- This paragraph originally copied from
   93.97 -@TOP@org/openide/doc-files/services-api.html#lookup-impl
   93.98 --->
   93.99 -
  93.100 -<p>The most powerful way to provide a lookup is to directly define
  93.101 -what instances and items it should provide, by subclassing. For this,
  93.102 -
  93.103 -<a href="@TOP@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 -<p>The simplest way to use <code>AbstractLookup</code> is to use its
  93.108 -public constructor (in which case you need not subclass it). Here you
  93.109 -provide an
  93.110 -
  93.111 -<a href="@TOP@org/openide/util/lookup/AbstractLookup.Content.html"><code>AbstractLookup.Content</code></a>
  93.112 -
  93.113 -object which you have created and hold on to privately, and which
  93.114 -keeps track of instances and permits them to be registered and
  93.115 -deregistered. Often
  93.116 -
  93.117 -<a href="@TOP@org/openide/util/lookup/InstanceContent.html"><code>InstanceContent</code></a>
  93.118 -
  93.119 -is used as the content implementation. To add something to the lookup,
  93.120 -simply use
  93.121 -
  93.122 -<a href="@TOP@org/openide/util/lookup/InstanceContent.html#add(java.lang.Object)"><code>add(Object)</code></a>
  93.123 -
  93.124 -(and <code>remove(Object)</code> for the reverse). These may be called
  93.125 -at any time and will update the set of registered instances (firing
  93.126 -result changes as needed).
  93.127 -
  93.128 -<pre>
  93.129 -    <font class="keyword">import</FONT> org.openide.util.lookup.*;
  93.130 -    <font class="type">InstanceContent</font> <font class="variable-name">ic</font> = <font class="keyword">new</font> <font class="type">InstanceContent</font> ();
  93.131 -    ic.add(firstObject);
  93.132 -    <font class="keyword">return</font> <font class="keyword">new</font> <font class="type">AbstractLookup</font> (ic);
  93.133 -</pre>
  93.134 -
  93.135 -<p>In case it is expensive to actually compute the object in the
  93.136 -lookup, but there is some cheap "key" which can easily generate it,
  93.137 -you may instead register the key by passing in an
  93.138 -
  93.139 -<a href="@TOP@org/openide/util/lookup/InstanceContent.Convertor.html"><code>InstanceContent.Convertor</code></a>.
  93.140 -
  93.141 -This convertor translates the key to the real instance that the lookup
  93.142 -client sees, if and when needed. For example, if you have a long list
  93.143 -of class names and wish to register default instances of each class,
  93.144 -you might actually register the class name as the key, and supply a
  93.145 -convertor which really loads the class and instantiates it. This makes
  93.146 -it easy to set up the lookup, but nothing is really loaded until
  93.147 -someone asks for it.
  93.148 -
  93.149 -</BODY>
  93.150 -</HTML>
    94.1 --- a/openide.util/src/org/openide/util/lookup/package.html	Sat Oct 31 15:06:58 2009 +0100
    94.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.3 @@ -1,48 +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 -
   94.10 -The contents of this file are subject to the terms of either the GNU
   94.11 -General Public License Version 2 only ("GPL") or the Common
   94.12 -Development and Distribution License("CDDL") (collectively, the
   94.13 -"License"). You may not use this file except in compliance with the
   94.14 -License. You can obtain a copy of the License at
   94.15 -http://www.netbeans.org/cddl-gplv2.html
   94.16 -or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   94.17 -specific language governing permissions and limitations under the
   94.18 -License.  When distributing the software, include this License Header
   94.19 -Notice in each file and include the License file at
   94.20 -nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   94.21 -particular file as subject to the "Classpath" exception as provided
   94.22 -by Sun in the GPL Version 2 section of the License file that
   94.23 -accompanied this code. If applicable, add the following below the
   94.24 -License Header, with the fields enclosed by brackets [] replaced by
   94.25 -your own identifying information:
   94.26 -"Portions Copyrighted [year] [name of copyright owner]"
   94.27 -
   94.28 -Contributor(s):
   94.29 -
   94.30 -The Original Software is NetBeans. The Initial Developer of the Original
   94.31 -Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   94.32 -Microsystems, Inc. All Rights Reserved.
   94.33 -
   94.34 -If you wish your version of this file to be governed by only the CDDL
   94.35 -or only the GPL Version 2, indicate your decision by adding
   94.36 -"[Contributor] elects to include this software in this distribution
   94.37 -under the [CDDL or GPL Version 2] license." If you do not indicate a
   94.38 -single choice of license, a recipient has the option to distribute
   94.39 -your version of this file under either the CDDL, the GPL Version 2 or
   94.40 -to extend the choice of license to its licensees as provided above.
   94.41 -However, if you add GPL Version 2 code and therefore, elected the GPL
   94.42 -Version 2 license, then the option applies only if the new code is
   94.43 -made subject to such option by the copyright holder.
   94.44 --->
   94.45 -
   94.46 -<html>
   94.47 -<body>
   94.48 -Support classes for the Registration and {@link org.openide.util.Lookup} extension mechanism.
   94.49 -Read more: <a href="doc-files/index.html">Lookup Library</a>
   94.50 -</body>
   94.51 -</html>
    95.1 --- a/openide.util/test/unit/src/org/bar/Comparator2.java	Sat Oct 31 15:06:58 2009 +0100
    95.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.3 @@ -1,7 +0,0 @@
    95.4 -
    95.5 -package org.bar;
    95.6 -
    95.7 -public class Comparator2 implements java.util.Comparator {
    95.8 -    public int compare(Object o1, Object o2) {return 0;}
    95.9 -    public boolean equals(Object obj) {return true;}
   95.10 -}
    96.1 --- a/openide.util/test/unit/src/org/bar/Comparator3.java	Sat Oct 31 15:06:58 2009 +0100
    96.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.3 @@ -1,7 +0,0 @@
    96.4 -
    96.5 -package org.bar;
    96.6 -
    96.7 -public class Comparator3 implements java.util.Comparator {
    96.8 -    public int compare(Object o1, Object o2) {return 0;}
    96.9 -    public boolean equals(Object obj) {return true;}
   96.10 -}
    97.1 --- a/openide.util/test/unit/src/org/bar/Implementation2.java	Sat Oct 31 15:06:58 2009 +0100
    97.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.3 @@ -1,3 +0,0 @@
    97.4 -package org.bar;
    97.5 -import org.foo.Interface;
    97.6 -public class Implementation2 implements Interface {}
    98.1 --- a/openide.util/test/unit/src/org/bar/Iterator2.java	Sat Oct 31 15:06:58 2009 +0100
    98.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.3 @@ -1,11 +0,0 @@
    98.4 -
    98.5 -package org.bar;
    98.6 -
    98.7 -public class Iterator2 implements java.util.Iterator {
    98.8 -    public boolean hasNext() {return false;}
    98.9 -    
   98.10 -    public Object next() {return null;}
   98.11 -    
   98.12 -    public void remove() {}
   98.13 -   
   98.14 -}
    99.1 --- a/openide.util/test/unit/src/org/foo/Interface.java	Sat Oct 31 15:06:58 2009 +0100
    99.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.3 @@ -1,2 +0,0 @@
    99.4 -package org.foo;
    99.5 -public interface Interface {}
   100.1 --- a/openide.util/test/unit/src/org/foo/impl/Comparator1.java	Sat Oct 31 15:06:58 2009 +0100
   100.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.3 @@ -1,7 +0,0 @@
   100.4 -
   100.5 -package org.foo.impl;
   100.6 -
   100.7 -public class Comparator1 implements java.util.Comparator {
   100.8 -    public int compare(Object o1, Object o2) {return 0;}
   100.9 -    public boolean equals(Object obj) {return true;}
  100.10 -}
   101.1 --- a/openide.util/test/unit/src/org/foo/impl/Implementation1.java	Sat Oct 31 15:06:58 2009 +0100
   101.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.3 @@ -1,3 +0,0 @@
   101.4 -package org.foo.impl;
   101.5 -import org.foo.Interface;
   101.6 -public class Implementation1 implements Interface {}
   102.1 --- a/openide.util/test/unit/src/org/foo/impl/Iterator1.java	Sat Oct 31 15:06:58 2009 +0100
   102.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.3 @@ -1,11 +0,0 @@
   102.4 -
   102.5 -package org.foo.impl;
   102.6 -
   102.7 -public class Iterator1 implements java.util.Iterator {
   102.8 -    public boolean hasNext() {return false;}
   102.9 -    
  102.10 -    public Object next() {return null;}
  102.11 -    
  102.12 -    public void remove() {}
  102.13 -   
  102.14 -}
   103.1 --- a/openide.util/test/unit/src/org/foo/impl/Runnable1.java	Sat Oct 31 15:06:58 2009 +0100
   103.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.3 @@ -1,6 +0,0 @@
   103.4 -
   103.5 -package org.foo.impl;
   103.6 -
   103.7 -public class Runnable1 implements Runnable {
   103.8 -   public void run () {}
   103.9 -}
   104.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupArrayStorageTest.java	Sat Oct 31 15:06:58 2009 +0100
   104.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.3 @@ -1,120 +0,0 @@
   104.4 -/*
   104.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   104.6 - *
   104.7 - * Copyright 1997-2009 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 - * Contributor(s):
  104.28 - *
  104.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  104.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  104.31 - * Microsystems, Inc. All Rights Reserved.
  104.32 - *
  104.33 - * If you wish your version of this file to be governed by only the CDDL
  104.34 - * or only the GPL Version 2, indicate your decision by adding
  104.35 - * "[Contributor] elects to include this software in this distribution
  104.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  104.37 - * single choice of license, a recipient has the option to distribute
  104.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  104.39 - * to extend the choice of license to its licensees as provided above.
  104.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  104.41 - * Version 2 license, then the option applies only if the new code is
  104.42 - * made subject to such option by the copyright holder.
  104.43 - */
  104.44 -
  104.45 -package org.openide.util.lookup;
  104.46 -
  104.47 -import junit.framework.*;
  104.48 -import org.netbeans.junit.*;
  104.49 -import org.openide.util.Lookup;
  104.50 -
  104.51 -public class AbstractLookupArrayStorageTest extends AbstractLookupBaseHid {
  104.52 -    public AbstractLookupArrayStorageTest(java.lang.String testName) {
  104.53 -        super(testName, null);
  104.54 -    }
  104.55 -
  104.56 -    public static TestSuite suite () {
  104.57 -        NbTestSuite suite = new NbTestSuite ();
  104.58 -        suite.addTest (new PL (2));
  104.59 -        suite.addTest (new AL (1));
  104.60 -        suite.addTest (new AL (-1));
  104.61 -        suite.addTest (new PL (-1));
  104.62 -        suite.addTest (new AL (5));
  104.63 -        suite.addTest (new PL (3));
  104.64 -        suite.addTest (new AL (2000));
  104.65 -        suite.addTest (new PL (2000));
  104.66 -        return suite;
  104.67 -    }
  104.68 -
  104.69 -    static final class AL extends ArrayTestSuite {
  104.70 -        public AL (int trash) {
  104.71 -            super (trash);
  104.72 -        }
  104.73 -        
  104.74 -        public Lookup createLookup (Lookup lookup) {
  104.75 -            return lookup;
  104.76 -        }
  104.77 -        
  104.78 -        public void clearCaches () {
  104.79 -        }
  104.80 -        
  104.81 -    }
  104.82 -    
  104.83 -    static final class PL extends ArrayTestSuite {
  104.84 -        public PL (int trash) {
  104.85 -            super (trash);
  104.86 -        }
  104.87 -        
  104.88 -        public Lookup createLookup (Lookup lookup) {
  104.89 -            return  new ProxyLookup (new Lookup[] { lookup });
  104.90 -        }
  104.91 -        
  104.92 -        public void clearCaches () {
  104.93 -        }
  104.94 -        
  104.95 -    }
  104.96 -    
  104.97 -    private static abstract class ArrayTestSuite extends NbTestSuite 
  104.98 -    implements AbstractLookupBaseHid.Impl {
  104.99 -        private int trash;
 104.100 -        
 104.101 -        public ArrayTestSuite (int trash) {
 104.102 -            super (AbstractLookupArrayStorageTest.class);
 104.103 -            this.trash = trash;
 104.104 -            
 104.105 -            int cnt = this.countTestCases();
 104.106 -            for (int i = 0; i < cnt; i++) {
 104.107 -                Object o = this.testAt (i);
 104.108 -                AbstractLookupBaseHid t = (AbstractLookupBaseHid)o;
 104.109 -                t.impl = this;
 104.110 -            }
 104.111 -        }
 104.112 -        
 104.113 -        public Lookup createInstancesLookup (InstanceContent ic) {
 104.114 -            if (trash == -1) {
 104.115 -                return new AbstractLookup (ic, new ArrayStorage ());
 104.116 -            } else {
 104.117 -                return new AbstractLookup (ic, new ArrayStorage (new Integer (trash)));
 104.118 -            }
 104.119 -        }
 104.120 -        
 104.121 -        
 104.122 -    }
 104.123 -}
   105.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupAsynchExecutorTest.java	Sat Oct 31 15:06:58 2009 +0100
   105.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.3 @@ -1,108 +0,0 @@
   105.4 -/*
   105.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   105.6 - *
   105.7 - * Copyright 1997-2009 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 - * Contributor(s):
  105.28 - *
  105.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  105.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  105.31 - * Microsystems, Inc. All Rights Reserved.
  105.32 - *
  105.33 - * If you wish your version of this file to be governed by only the CDDL
  105.34 - * or only the GPL Version 2, indicate your decision by adding
  105.35 - * "[Contributor] elects to include this software in this distribution
  105.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  105.37 - * single choice of license, a recipient has the option to distribute
  105.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  105.39 - * to extend the choice of license to its licensees as provided above.
  105.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  105.41 - * Version 2 license, then the option applies only if the new code is
  105.42 - * made subject to such option by the copyright holder.
  105.43 - */
  105.44 -
  105.45 -package org.openide.util.lookup;
  105.46 -
  105.47 -import java.util.ArrayList;
  105.48 -import java.util.List;
  105.49 -import java.util.concurrent.Executor;
  105.50 -import org.netbeans.junit.NbTestCase;
  105.51 -import org.openide.util.Lookup;
  105.52 -import org.openide.util.LookupEvent;
  105.53 -import org.openide.util.LookupListener;
  105.54 -
  105.55 -public class AbstractLookupAsynchExecutorTest extends NbTestCase implements Executor {
  105.56 -    private List<Runnable> toRun = new ArrayList<Runnable>();
  105.57 -
  105.58 -
  105.59 -    public AbstractLookupAsynchExecutorTest(java.lang.String testName) {
  105.60 -        super(testName);
  105.61 -    }
  105.62 -
  105.63 -    public void testCanProxyLookupHaveWrongResults() {
  105.64 -        final InstanceContent ic = new InstanceContent(this);
  105.65 -        final AbstractLookup lookup = new AbstractLookup(ic);
  105.66 -
  105.67 -        class L implements LookupListener {
  105.68 -            ProxyLookup pl;
  105.69 -            Lookup.Result<String> original;
  105.70 -            Lookup.Result<String> wrapped;
  105.71 -            boolean ok;
  105.72 -
  105.73 -            public void test() {
  105.74 -                pl = new ProxyLookup(lookup);
  105.75 -                original = lookup.lookupResult(String.class);
  105.76 -
  105.77 -                original.addLookupListener(this);
  105.78 -
  105.79 -                wrapped = pl.lookupResult(String.class);
  105.80 -
  105.81 -                assertEquals("Original empty", 0, original.allInstances().size());
  105.82 -                assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
  105.83 -
  105.84 -                ic.add("Hello!");
  105.85 -            }
  105.86 -
  105.87 -            public void resultChanged(LookupEvent ev) {
  105.88 -                ok = true;
  105.89 -                assertContainsHello();
  105.90 -            }
  105.91 -
  105.92 -            public void assertContainsHello() {
  105.93 -                assertEquals("Original has hello", 1, original.allInstances().size());
  105.94 -                assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
  105.95 -            }
  105.96 -
  105.97 -        }
  105.98 -        L listener = new L();
  105.99 -        listener.test();
 105.100 -        listener.assertContainsHello();
 105.101 -        for (Runnable r : toRun) {
 105.102 -            r.run();
 105.103 -        }
 105.104 -        assertTrue("Listener called", listener.ok);
 105.105 -    }
 105.106 -
 105.107 -    public void execute(Runnable command) {
 105.108 -        toRun.add(command);
 105.109 -    }
 105.110 -
 105.111 -}
   106.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java	Sat Oct 31 15:06:58 2009 +0100
   106.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.3 @@ -1,2088 +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 -
  106.45 -package org.openide.util.lookup;
  106.46 -
  106.47 -import java.io.ByteArrayInputStream;
  106.48 -import java.io.ByteArrayOutputStream;
  106.49 -import java.io.ObjectInputStream;
  106.50 -import java.io.ObjectOutputStream;
  106.51 -import java.io.Serializable;
  106.52 -import java.lang.ref.WeakReference;
  106.53 -import java.lang.ref.Reference;
  106.54 -import java.util.ArrayList;
  106.55 -import java.util.Arrays;
  106.56 -import java.util.Collection;
  106.57 -import java.util.Collections;
  106.58 -import java.util.Iterator;
  106.59 -import java.util.LinkedList;
  106.60 -import java.util.List;
  106.61 -import java.util.concurrent.Executors;
  106.62 -import java.util.concurrent.TimeUnit;
  106.63 -import javax.swing.ActionMap;
  106.64 -import javax.swing.InputMap;
  106.65 -import org.netbeans.junit.NbTestCase;
  106.66 -import org.openide.util.Lookup;
  106.67 -import org.openide.util.Lookup.Template;
  106.68 -import org.openide.util.LookupEvent;
  106.69 -import org.openide.util.LookupListener;
  106.70 -
  106.71 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  106.72 -public class AbstractLookupBaseHid extends NbTestCase {
  106.73 -    private static AbstractLookupBaseHid running;
  106.74 -
  106.75 -    /** instance content to work with */
  106.76 -    InstanceContent ic;
  106.77 -    /** the lookup to work on */
  106.78 -    protected Lookup instanceLookup;
  106.79 -    /** the lookup created to work with */
  106.80 -    private Lookup lookup;
  106.81 -    /** implementation of methods that can influence the behaviour */
  106.82 -    Impl impl;
  106.83 -    
  106.84 -    protected AbstractLookupBaseHid(String testName, Impl impl) {
  106.85 -        super(testName);
  106.86 -        if (impl == null && (this instanceof Impl)) {
  106.87 -            impl = (Impl)this;
  106.88 -        }
  106.89 -        this.impl = impl;
  106.90 -    }
  106.91 -    
  106.92 -    protected @Override void setUp() {
  106.93 -        this.ic = new InstanceContent ();
  106.94 -        
  106.95 -        beforeActualTest(getName());
  106.96 -        
  106.97 -        this.instanceLookup = createInstancesLookup (ic);
  106.98 -        this.lookup = createLookup (instanceLookup);
  106.99 -        running = this;
 106.100 -    }        
 106.101 -    
 106.102 -    protected @Override void tearDown() {
 106.103 -        running = null;
 106.104 -    }
 106.105 -    
 106.106 -    /** The methods to influence test behaviour */
 106.107 -    public static interface Impl {
 106.108 -        /** Creates the initial abstract lookup.
 106.109 -         */
 106.110 -        public Lookup createInstancesLookup (InstanceContent ic);
 106.111 -        /** Creates an lookup for given lookup. This class just returns 
 106.112 -         * the object passed in, but subclasses can be different.
 106.113 -         * @param lookup in lookup
 106.114 -         * @return a lookup to use
 106.115 -         */
 106.116 -        public Lookup createLookup (Lookup lookup);
 106.117 -        
 106.118 -        /** If the impl has any caches that would prevent the system
 106.119 -         * to not garbage collect correctly, then clear them now.
 106.120 -         */
 106.121 -        public void clearCaches ();
 106.122 -    }
 106.123 -    
 106.124 -    private Lookup createInstancesLookup (InstanceContent ic) {
 106.125 -        return impl.createInstancesLookup (ic);
 106.126 -    }
 106.127 -    
 106.128 -    private Lookup createLookup (Lookup lookup) {
 106.129 -        return impl.createLookup (lookup);
 106.130 -    }
 106.131 -    
 106.132 -    /** instances that we register */
 106.133 -    private static Object[] INSTANCES = new Object[] {
 106.134 -        new Integer (10), 
 106.135 -        new Object ()
 106.136 -    };
 106.137 -    
 106.138 -    /** Test if first is really first.
 106.139 -     */
 106.140 -    public void testFirst () {
 106.141 -        Integer i1 = 1;
 106.142 -        Integer i2 = 2;
 106.143 -        
 106.144 -        ic.add (i1);
 106.145 -        ic.add (i2);
 106.146 -        
 106.147 -        Integer found = lookup.lookup(Integer.class);
 106.148 -        if (found != i1) {
 106.149 -            fail ("First object is not first: " + found + " != " + i1);
 106.150 -        }
 106.151 -        
 106.152 -        List<Integer> list = new ArrayList<Integer>();
 106.153 -        list.add (i2);
 106.154 -        list.add (i1);
 106.155 -        ic.set (list, null);
 106.156 -        
 106.157 -        found = lookup.lookup (Integer.class);
 106.158 -        if (found != i2) {
 106.159 -            fail ("Second object is not first after reorder: " + found + " != " + i2);
 106.160 -        }
 106.161 -        
 106.162 -    }
 106.163 -
 106.164 -    public void testToString() {
 106.165 -        String txt = lookup.toString();
 106.166 -        assertNotNull("Something is there", txt);
 106.167 -        assertTrue("Something2: " + txt, txt.length() > 0);
 106.168 -    }
 106.169 -
 106.170 -
 106.171 -    /** Tests ordering of items in the lookup.
 106.172 -    */
 106.173 -    public void testOrder () {
 106.174 -        addInstances (INSTANCES);
 106.175 -
 106.176 -        if (INSTANCES[0] != lookup.lookup (INSTANCES[0].getClass ())) {
 106.177 -            fail ("First object in intances not found");
 106.178 -        }
 106.179 -
 106.180 -        Iterator<?> all = lookup.lookupAll(Object.class).iterator();
 106.181 -        checkIterator ("Difference between instances added and found", all, Arrays.asList (INSTANCES));
 106.182 -    }
 106.183 -    
 106.184 -    /** Checks the reorder of items in lookup reflects the result.
 106.185 -     * Testing both classes and interfaces, because they are often treated
 106.186 -     * especially.
 106.187 -     */
 106.188 -    public void testReorder () {
 106.189 -        String s1 = "s2";
 106.190 -        String s2 = "s1";
 106.191 -        Runnable r1 = new Runnable () {
 106.192 -            public void run () {}
 106.193 -        };
 106.194 -        Runnable r2 = new Runnable () {
 106.195 -            public void run () {}
 106.196 -        };
 106.197 -        List<Object> l = new ArrayList<Object>();
 106.198 -
 106.199 -        l.add (s1);
 106.200 -        l.add (s2);
 106.201 -        l.add (r1);
 106.202 -        l.add (r2);
 106.203 -        ic.set (l, null);
 106.204 -     
 106.205 -        assertEquals ("s1 is found", s1, lookup.lookup (String.class));
 106.206 -        assertEquals ("r1 is found", r1, lookup.lookup (Runnable.class));
 106.207 -        
 106.208 -        Collections.reverse (l);
 106.209 -        
 106.210 -        ic.set (l, null);
 106.211 -        
 106.212 -        assertEquals ("s2 is found", s2, lookup.lookup (String.class));
 106.213 -        assertEquals ("r2 is found", r2, lookup.lookup (Runnable.class));
 106.214 -    }
 106.215 -    
 106.216 -    /** Tries to set empty collection to the lookup.
 106.217 -     */
 106.218 -    public void testSetEmpty () {
 106.219 -        ic.add ("A serializable string");
 106.220 -        lookup.lookup (Serializable.class);
 106.221 -        
 106.222 -        ic.set (Collections.emptyList(), null);
 106.223 -    }
 106.224 -    
 106.225 -    /** Tests a more complex reorder on nodes.
 106.226 -     */
 106.227 -    public void testComplexReorder () {
 106.228 -        Integer i1 = 1;
 106.229 -        Long i2 = 2L;
 106.230 -        
 106.231 -        List<Object> l = new ArrayList<Object>();
 106.232 -        l.add (i1);
 106.233 -        l.add (i2);
 106.234 -        ic.set (l, null);
 106.235 -        
 106.236 -        assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
 106.237 -        assertEquals ("Find long", i2, lookup.lookup (Long.class));
 106.238 -        assertEquals ("Find number", i1, lookup.lookup (Number.class));
 106.239 -        
 106.240 -        Collections.reverse (l);
 106.241 -        
 106.242 -        ic.set (l, null);
 106.243 -        
 106.244 -        assertEquals ("Find integer", i1, lookup.lookup (Integer.class));
 106.245 -        assertEquals ("Find long", i2, lookup.lookup (Long.class));
 106.246 -        assertEquals ("Find number", i2, lookup.lookup (Number.class));
 106.247 -    }
 106.248 -    
 106.249 -    /** Checks whether setPairs keeps the order.
 106.250 -     */
 106.251 -    public void testSetPairs () {
 106.252 -        // test setPairs method
 106.253 -        List<Object> li = new ArrayList<Object>();
 106.254 -        li.addAll (Arrays.asList (INSTANCES));
 106.255 -        ic.set (li, null);
 106.256 -        
 106.257 -        Lookup.Result<Object> res = lookup.lookupResult(Object.class);
 106.258 -        Iterator<?> all = res.allInstances().iterator();
 106.259 -        checkIterator ("Original order not kept", all, li);
 106.260 -        
 106.261 -        // reverse the order
 106.262 -        Collections.reverse (li);
 106.263 -        
 106.264 -        // change the pairs
 106.265 -        LL listener = new LL (res);
 106.266 -        res.addLookupListener (listener);
 106.267 -        ic.set (li, null);
 106.268 -        if (listener.getCount () != 1) {
 106.269 -            fail ("Result has not changed even we set reversed order");
 106.270 -        }
 106.271 -        
 106.272 -        all = res.allInstances ().iterator ();
 106.273 -        checkIterator ("Reversed order not kept", all, li);
 106.274 -    }
 106.275 -
 106.276 -    /** Checks whether setPairs fires correct events.
 106.277 -     */
 106.278 -    public void testSetPairsFire () {
 106.279 -        // test setPairs method
 106.280 -        List<Object> li = new ArrayList<Object>();
 106.281 -        li.addAll (Arrays.asList (INSTANCES));
 106.282 -        ic.set (li, null);
 106.283 -        
 106.284 -        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
 106.285 -        Iterator<?> all = res.allInstances().iterator();
 106.286 -        checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
 106.287 -        
 106.288 -        // change the pairs
 106.289 -        LL listener = new LL (res);
 106.290 -        res.addLookupListener (listener);
 106.291 -
 106.292 -        List<Object> l2 = new ArrayList<Object>(li);
 106.293 -        l2.remove (INSTANCES[0]);
 106.294 -        ic.set (l2, null);
 106.295 -
 106.296 -        all = lookup.lookupAll(Object.class).iterator();
 106.297 -        checkIterator ("The removed integer is not noticed", all, l2);
 106.298 -
 106.299 -        if (listener.getCount () != 1) {
 106.300 -            fail ("Nothing has not been fired");
 106.301 -        }
 106.302 -    }
 106.303 -
 106.304 -    /** Checks whether set pairs does not fire when they should not.
 106.305 -    */
 106.306 -    public void testSetPairsDoesNotFire () {
 106.307 -        Object tmp = new Object ();
 106.308 -
 106.309 -        List<Object> li = new ArrayList<Object>();
 106.310 -        li.add (tmp);
 106.311 -        li.addAll (Arrays.asList (INSTANCES));
 106.312 -        ic.set (li, null);
 106.313 -        
 106.314 -        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
 106.315 -        Iterator<?> all = res.allInstances ().iterator ();
 106.316 -        checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0]));
 106.317 -        
 106.318 -        // change the pairs
 106.319 -        LL listener = new LL (res);
 106.320 -        res.addLookupListener (listener);
 106.321 -
 106.322 -        List<Object> l2 = new ArrayList<Object>(li);
 106.323 -        l2.remove (tmp);
 106.324 -        ic.set (l2, null);
 106.325 -
 106.326 -        all = lookup.lookupAll(Object.class).iterator();
 106.327 -        checkIterator ("The removed integer is not noticed", all, l2);
 106.328 -
 106.329 -        if (listener.getCount () != 0) {
 106.330 -            fail ("Something has been fired");
 106.331 -        }
 106.332 -    }
 106.333 -    
 106.334 -    /** Test whether after registration it is possible to find registered objects
 106.335 -    * 
 106.336 -     */
 106.337 -    public void testLookupAndAdd () throws Exception {
 106.338 -        addInstances (INSTANCES);
 106.339 -
 106.340 -        for (int i = 0; i < INSTANCES.length; i++) {
 106.341 -            Object obj = INSTANCES[i];
 106.342 -            findAll (lookup, obj.getClass (), true);
 106.343 -        }
 106.344 -    }
 106.345 -
 106.346 -    /** Tries to find all classes and superclasses in the lookup.
 106.347 -    */
 106.348 -    private void findAll(Lookup lookup, Class<?> clazz, boolean shouldBeThere) {
 106.349 -        if (clazz == null) return;
 106.350 -
 106.351 -        Object found = lookup.lookup (clazz);
 106.352 -        if (found == null) {
 106.353 -            if (shouldBeThere) {
 106.354 -                // should find at either instance or something else, but must
 106.355 -                // find at least something
 106.356 -                fail ("Lookup (" + clazz.getName () + ") found nothing");
 106.357 -            }
 106.358 -        } else {
 106.359 -            if (!shouldBeThere) {
 106.360 -                // should find at either instance or something else, but must
 106.361 -                // find at least something
 106.362 -                fail ("Lookup (" + clazz.getName () + ") found " + found);
 106.363 -            }
 106.364 -        }
 106.365 -
 106.366 -        Lookup.Result<?> res = lookup.lookupResult(clazz);
 106.367 -        Collection<?> collection = res.allInstances();
 106.368 -
 106.369 -        for (int i = 0; i < INSTANCES.length; i++) {
 106.370 -            boolean isSubclass = clazz.isInstance (INSTANCES[i]);
 106.371 -            boolean isThere = collection.contains (INSTANCES[i]);
 106.372 -
 106.373 -            if (isSubclass != isThere) {
 106.374 -                // a problem found
 106.375 -                // should find at either instance or something else, but must
 106.376 -                // find at least something
 106.377 -                fail ("Lookup.Result (" + clazz.getName () + ") for " + INSTANCES[i] + " is subclass: " + isSubclass + " isThere: " + isThere);
 106.378 -            }
 106.379 -        }
 106.380 -
 106.381 -        // go on for superclasses
 106.382 -
 106.383 -        findAll (lookup, clazz.getSuperclass (), shouldBeThere);
 106.384 -
 106.385 -        Class[] ies = clazz.getInterfaces ();
 106.386 -        for (int i = 0; i < ies.length; i++) {
 106.387 -            findAll (lookup, ies[i], shouldBeThere);
 106.388 -        }
 106.389 -    }
 106.390 -    
 106.391 -    /** Test if it is possible to remove a registered object. */
 106.392 -    public void testRemoveRegisteredObject() {
 106.393 -        Integer inst = new Integer(10);
 106.394 -        
 106.395 -        ic.add(inst);
 106.396 -        if (lookup.lookup(inst.getClass()) == null) {
 106.397 -            // should find an instance
 106.398 -            fail("Lookup (" + inst.getClass().getName () + ") found nothing");
 106.399 -        }
 106.400 -        
 106.401 -        ic.remove(inst);
 106.402 -        if (lookup.lookup(inst.getClass()) != null) {
 106.403 -            // should NOT find an instance
 106.404 -            fail("Lookup (" + inst.getClass().getName () +
 106.405 -                ") found an instance after remove operation");
 106.406 -        }
 106.407 -    }
 106.408 -    
 106.409 -    public void testCanReturnReallyStrangeResults () throws Exception {
 106.410 -        class QueryingPair extends AbstractLookup.Pair<Object> {
 106.411 -            private Integer i = 434;
 106.412 -            
 106.413 -            //
 106.414 -            // do the test
 106.415 -            //
 106.416 -            
 106.417 -            public void doTest () throws Exception {
 106.418 -                ic.add (i);
 106.419 -                ic.addPair (this);
 106.420 -                
 106.421 -                Object found = lookup.lookup (QueryingPair.class);
 106.422 -                assertEquals ("This object is found", this, found);
 106.423 -            }
 106.424 -            
 106.425 -            
 106.426 -            //
 106.427 -            // Implementation of pair
 106.428 -            // 
 106.429 -        
 106.430 -            public String getId() {
 106.431 -                return getType ().toString();
 106.432 -            }
 106.433 -
 106.434 -            public String getDisplayName() {
 106.435 -                return getId ();
 106.436 -            }
 106.437 -
 106.438 -            public Class<?> getType() {
 106.439 -                return getClass ();
 106.440 -            }
 106.441 -
 106.442 -            protected boolean creatorOf(Object obj) {
 106.443 -                return obj == this;
 106.444 -            }
 106.445 -
 106.446 -            protected boolean instanceOf(Class<?> c) {
 106.447 -                assertEquals ("Integer found or exception is thrown", i, lookup.lookup (Integer.class));
 106.448 -                return c.isAssignableFrom(getType ());
 106.449 -            }
 106.450 -
 106.451 -            public Object getInstance() {
 106.452 -                return this;
 106.453 -            }
 106.454 -            
 106.455 -            
 106.456 -        }
 106.457 -        
 106.458 -        
 106.459 -        QueryingPair qp = new QueryingPair ();
 106.460 -        qp.doTest ();
 106.461 -    }
 106.462 -    
 106.463 -    /** Test of firing events. */
 106.464 -    public void testLookupListener() {
 106.465 -        Object inst = 10;
 106.466 -        Lookup.Result<?> res = lookup.lookupResult(inst.getClass());
 106.467 -        res.allInstances ();
 106.468 -        
 106.469 -        LL listener = new LL(res);
 106.470 -        res.addLookupListener(listener);
 106.471 -        
 106.472 -        ic.add(inst);
 106.473 -        if (listener.getCount() == 0) {
 106.474 -            fail("None event fired during NbLookup.addPair()");
 106.475 -        }
 106.476 -        
 106.477 -        ic.remove(inst);
 106.478 -        if (listener.getCount() == 0) {
 106.479 -            fail("None event fired during NbLookup.removePair()");
 106.480 -        }
 106.481 -        
 106.482 -        ic.add(inst);
 106.483 -        if (listener.getCount() == 0) {
 106.484 -            fail("None event fired during second NbLookup.addPair()");
 106.485 -        }
 106.486 -        
 106.487 -        ic.remove(inst);
 106.488 -        if (listener.getCount() == 0) {
 106.489 -            fail("None event fired during second NbLookup.removePair()");
 106.490 -        }
 106.491 -    }
 106.492 -    
 106.493 -    /** Testing identity of the lookup.
 106.494 -     */
 106.495 -    public void testId () {
 106.496 -        Lookup.Template<?> templ;
 106.497 -        int cnt;
 106.498 -        
 106.499 -        addInstances (INSTANCES);
 106.500 -        
 106.501 -        Lookup.Result<?> res = lookup.lookupResult(Object.class);
 106.502 -        for (AbstractLookup.Item<?> item : res.allItems()) {
 106.503 -            
 106.504 -            templ = new Lookup.Template<Object>(null, item.getId(), null);
 106.505 -            cnt = lookup.lookup (templ).allInstances ().size ();
 106.506 -            if (cnt != 1) {
 106.507 -                fail ("Identity lookup failed. Instances = " + cnt);
 106.508 -            }
 106.509 -
 106.510 -            templ = makeTemplate(item.getType(), item.getId());
 106.511 -            cnt = lookup.lookup (templ).allInstances ().size ();
 106.512 -            if (cnt != 1) {
 106.513 -                fail ("Identity lookup with type failed. Instances = " + cnt);
 106.514 -            }
 106.515 -            
 106.516 -            templ = makeTemplate(this.getClass(), item.getId());
 106.517 -            cnt = lookup.lookup (templ).allInstances ().size ();
 106.518 -            if (cnt != 0) {
 106.519 -                fail ("Identity lookup with wrong type failed. Instances = " + cnt);
 106.520 -            }
 106.521 -            
 106.522 -            templ = new Lookup.Template<Object>(null, null, item.getInstance());
 106.523 -            cnt = lookup.lookup (templ).allInstances ().size ();
 106.524 -            if (cnt != 1) {
 106.525 -                fail ("Instance lookup failed. Instances = " + cnt);
 106.526 -            }
 106.527 -
 106.528 -            templ = new Lookup.Template<Object>(null, item.getId(), item.getInstance());
 106.529 -            cnt = lookup.lookup (templ).allInstances ().size ();
 106.530 -            if (cnt != 1) {
 106.531 -                fail ("Instance & identity lookup failed. Instances = " + cnt);
 106.532 -            }
 106.533 -            
 106.534 -        }
 106.535 -    }
 106.536 -    private static <T> Lookup.Template<T> makeTemplate(Class<T> clazz, String id) { // captures type parameter
 106.537 -        return new Lookup.Template<T>(clazz, id, null);
 106.538 -    }
 106.539 -    
 106.540 -    /** Tests adding and removing.
 106.541 -     */
 106.542 -    public void testAddAndRemove () throws Exception {
 106.543 -        Object map = new javax.swing.ActionMap ();
 106.544 -        LL ll = new LL ();
 106.545 -        
 106.546 -        Lookup.Result<?> res = lookup.lookupResult(map.getClass());
 106.547 -        res.allItems();
 106.548 -        res.addLookupListener (ll);
 106.549 -        ll.source = res;
 106.550 -        
 106.551 -        ic.add (map);
 106.552 -        
 106.553 -        assertEquals ("First change when adding", ll.getCount (), 1);
 106.554 -        
 106.555 -        ic.remove (map);
 106.556 -        
 106.557 -        assertEquals ("Second when removing", ll.getCount (), 1);
 106.558 -        
 106.559 -        ic.add (map);
 106.560 -        
 106.561 -        assertEquals ("Third when readding", ll.getCount (), 1);
 106.562 -        
 106.563 -        ic.remove (map);
 106.564 -        
 106.565 -        assertEquals ("Forth when reremoving", ll.getCount (), 1);
 106.566 -        
 106.567 -    }
 106.568 -    
 106.569 -    /** Will a class garbage collect even it is registered in lookup.
 106.570 -     */
 106.571 -    public void testGarbageCollect () throws Exception {
 106.572 -        ClassLoader l = new CL ();
 106.573 -        Class<?> c = l.loadClass(Garbage.class.getName());
 106.574 -        Reference<?> ref = new WeakReference<Object>(c);
 106.575 -
 106.576 -        lookup.lookup (c);
 106.577 -        
 106.578 -        // now test garbage collection
 106.579 -        c = null;
 106.580 -        l = null;
 106.581 -        impl.clearCaches ();
 106.582 -        assertGC ("The classloader has not been garbage collected!", ref);
 106.583 -    }
 106.584 -                
 106.585 -    /** Items are the same as results.
 106.586 -     */
 106.587 -    public void testItemsAndIntances () {
 106.588 -        addInstances (INSTANCES);
 106.589 -        
 106.590 -        Lookup.Result<Object> r = lookup.lookupResult(Object.class);
 106.591 -        Collection<? extends Lookup.Item<?>> items = r.allItems();
 106.592 -        Collection<?> insts = r.allInstances();
 106.593 -        
 106.594 -        if (items.size () != insts.size ()) {
 106.595 -            fail ("Different size of sets");
 106.596 -        }
 106.597 -
 106.598 -        for (Lookup.Item<?> item : items) {
 106.599 -            if (!insts.contains (item.getInstance ())) {
 106.600 -                fail ("Intance " + item.getInstance () + " is missing in " + insts);
 106.601 -            }
 106.602 -        }
 106.603 -    }
 106.604 -    
 106.605 -    /** Checks search for interface.
 106.606 -     */
 106.607 -    public void testSearchForInterface () {
 106.608 -        Lookup.Template<Serializable> t = new Lookup.Template<Serializable>(Serializable.class, null, null);
 106.609 -        
 106.610 -        assertNull("Nothing to find", lookup.lookupItem (t));
 106.611 -        
 106.612 -        Serializable s = new Serializable () {};
 106.613 -        ic.add (s);
 106.614 -        
 106.615 -        Lookup.Item item = lookup.lookupItem (t);
 106.616 -        assertNotNull ("Something found", item);
 106.617 -    }
 106.618 -
 106.619 -    /** Test to add broken item if it incorrectly answers instanceOf questions.
 106.620 -     */
 106.621 -    public void testIncorectInstanceOf40364 () {
 106.622 -        final Long sharedLong = new Long (0);
 106.623 -        
 106.624 -        class P extends AbstractLookup.Pair<Object> {
 106.625 -            public boolean isLong;
 106.626 -            
 106.627 -            P (boolean b) {
 106.628 -                isLong = b;
 106.629 -            }
 106.630 -            
 106.631 -            protected boolean creatorOf (Object obj) {
 106.632 -                return obj == sharedLong;
 106.633 -            }
 106.634 -            
 106.635 -            public String getDisplayName () {
 106.636 -                return "";
 106.637 -            }
 106.638 -            
 106.639 -            public String getId () {
 106.640 -                return "";
 106.641 -            }
 106.642 -            
 106.643 -            public Object getInstance () {
 106.644 -                return sharedLong;
 106.645 -            }
 106.646 -            
 106.647 -            public Class<?> getType() {
 106.648 -                return isLong ? Long.class : Number.class;
 106.649 -            }
 106.650 -            
 106.651 -            protected boolean instanceOf(Class<?> c) {
 106.652 -                return c.isAssignableFrom (getType ());
 106.653 -            }
 106.654 -    
 106.655 -            public @Override int hashCode() {
 106.656 -                return getClass ().hashCode ();
 106.657 -            }    
 106.658 -
 106.659 -            public @Override boolean equals(Object obj) {
 106.660 -                return obj != null && getClass ().equals (obj.getClass ());
 106.661 -            }
 106.662 -        }
 106.663 -        
 106.664 -        // to create the right structure in the lookup
 106.665 -        lookup.lookup (Object.class);
 106.666 -        lookup.lookup (Long.class);
 106.667 -        lookup.lookup (Number.class);
 106.668 -        
 106.669 -        P lng1 = new P (true);
 106.670 -        ic.addPair (lng1);
 106.671 -
 106.672 -        P lng2 = new P (false);
 106.673 -        ic.setPairs (Collections.singleton (lng2));
 106.674 -        
 106.675 -        Collection<? extends Lookup.Item<?>> res = lookup.lookupResult(Object.class).allItems();
 106.676 -        assertEquals ("Just one pair", 1, res.size ());
 106.677 -    }
 106.678 -
 106.679 -    public void testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly () throws Exception {
 106.680 -        class X implements TestInterfaceInheritanceA, TestInterfaceInheritanceB {
 106.681 -        }
 106.682 -        final X shared = new X ();
 106.683 -        
 106.684 -        class P extends AbstractLookup.Pair<Object> {
 106.685 -            public int howLong;
 106.686 -            
 106.687 -            P (int b) {
 106.688 -                howLong = b;
 106.689 -            }
 106.690 -            
 106.691 -            protected boolean creatorOf (Object obj) {
 106.692 -                return obj == shared;
 106.693 -            }
 106.694 -            
 106.695 -            public String getDisplayName () {
 106.696 -                return "";
 106.697 -            }
 106.698 -            
 106.699 -            public String getId () {
 106.700 -                return "";
 106.701 -            }
 106.702 -            
 106.703 -            public Object getInstance () {
 106.704 -                return shared;
 106.705 -            }
 106.706 -            
 106.707 -            public Class<?> getType() {
 106.708 -                return howLong == 0 ? TestInterfaceInheritanceB.class : TestInterfaceInheritanceA.class;
 106.709 -            }
 106.710 -            
 106.711 -            protected boolean instanceOf(Class<?> c) {
 106.712 -                return c.isAssignableFrom (getType ());
 106.713 -            }
 106.714 -    
 106.715 -            public @Override int hashCode() {
 106.716 -                return getClass ().hashCode ();
 106.717 -            }    
 106.718 -
 106.719 -            public @Override boolean equals(Object obj) {
 106.720 -                if (obj instanceof P) {
 106.721 -                    P p = (P)obj;
 106.722 -                    if (this.howLong > 0) {
 106.723 -                        this.howLong--;
 106.724 -                        return false;
 106.725 -                    }
 106.726 -                    if (p.howLong > 0) {
 106.727 -                        p.howLong--;
 106.728 -                        return false;
 106.729 -                    }
 106.730 -                    return getClass ().equals (p.getClass ());
 106.731 -                }
 106.732 -                return false;
 106.733 -            }
 106.734 -        }
 106.735 -        
 106.736 -        // to create the right structure in the lookup
 106.737 -        Lookup.Result<?> a = lookup.lookupResult(TestInterfaceInheritanceA.class);
 106.738 -        Lookup.Result<?> b = lookup.lookupResult(TestInterfaceInheritanceB.class);
 106.739 -        
 106.740 -        P lng1 = new P (0);
 106.741 -        ic.addPair (lng1);
 106.742 -        
 106.743 -        assertEquals ("One in a", 1, a.allItems ().size ());
 106.744 -        assertEquals ("One in b", 1, b.allItems ().size ());
 106.745 -
 106.746 -        P lng2 = new P (1);
 106.747 -        
 106.748 -
 106.749 -        /* Following call used to generate this exception:
 106.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
 106.751 -	at org.openide.util.lookup.ALPairComparator.compare(ALPairComparator.java:52)
 106.752 -	at java.util.Arrays.mergeSort(Arrays.java:1284)
 106.753 -	at java.util.Arrays.sort(Arrays.java:1223)
 106.754 -	at java.util.Collections.sort(Collections.java:159)
 106.755 -	at org.openide.util.lookup.InheritanceTree.retainAllInterface(InheritanceTree.java:753)
 106.756 -	at org.openide.util.lookup.InheritanceTree.retainAll(InheritanceTree.java:183)
 106.757 -	at org.openide.util.lookup.DelegatingStorage.retainAll(DelegatingStorage.java:83)
 106.758 -	at org.openide.util.lookup.AbstractLookup.setPairsAndCollectListeners(AbstractLookup.java:238)
 106.759 -	at org.openide.util.lookup.AbstractLookup.setPairs(AbstractLookup.java:203)
 106.760 -	at org.openide.util.lookup.AbstractLookup$Content.setPairs(AbstractLookup.java:885)
 106.761 -	at org.openide.util.lookup.AbstractLookupBaseHid.testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly(AbstractLookupBaseHid.java:696)
 106.762 -	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 106.763 -	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 106.764 -	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 106.765 -	at org.netbeans.junit.NbTestCase.run(NbTestCase.java:119)
 106.766 -    */  
 106.767 -        ic.setPairs (Collections.singleton (lng2));
 106.768 -
 106.769 -        
 106.770 -    }
 106.771 -    
 106.772 -    public void testInstancesArePreservedFoundWhenFixing48590 () throws Exception {
 106.773 -        class X implements Runnable, Serializable {
 106.774 -            public void run () {
 106.775 -                
 106.776 -            }
 106.777 -            
 106.778 -            public void assertOnlyMe (String msg, Lookup.Result<?> res) {
 106.779 -                Collection<?> col = res.allInstances();
 106.780 -                assertEquals (msg + " just one", 1, col.size ());
 106.781 -                assertSame (msg + " and it is me", this, col.iterator ().next ());
 106.782 -            }
 106.783 -        }
 106.784 -        
 106.785 -        Lookup.Result<?> runnable = lookup.lookupResult(Runnable.class);
 106.786 -        Lookup.Result<?> serial = lookup.lookupResult(Serializable.class);
 106.787 -        
 106.788 -        
 106.789 -        X x = new X ();
 106.790 -        ic.add (x);
 106.791 -        
 106.792 -        
 106.793 -        x.assertOnlyMe ("x implements it (1)", runnable);
 106.794 -        x.assertOnlyMe ("x implements it (2)", serial);
 106.795 -        
 106.796 -        ic.set (Collections.singleton (x), null);
 106.797 -        
 106.798 -        x.assertOnlyMe ("x implements it (3)", runnable);
 106.799 -        x.assertOnlyMe ("x implements it (4)", serial);
 106.800 -    }
 106.801 -    
 106.802 -    /** Testing lookup of inherited classes. */
 106.803 -    public void testInheritance() {
 106.804 -        class A {}
 106.805 -        class B extends A implements java.rmi.Remote {}
 106.806 -        class BB extends B {}
 106.807 -        class C extends A implements java.rmi.Remote {}
 106.808 -        class D extends A {}
 106.809 -        
 106.810 -        A[] types = {new B(), new BB(), new C(), new D()};
 106.811 -        
 106.812 -        for (int i = 0; i < types.length; i++) {
 106.813 -            ic.add(types[i]);
 106.814 -            if (lookup.lookup(types[i].getClass()) == null) {
 106.815 -                // should find an instance
 106.816 -                fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
 106.817 -            }
 106.818 -        }
 106.819 -        
 106.820 -        int size1, size2;
 106.821 -        
 106.822 -        //interface query
 106.823 -        size1 = lookup.lookupAll(java.rmi.Remote.class).size();
 106.824 -        size2 = countInstances(types, java.rmi.Remote.class);
 106.825 -        
 106.826 -        if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
 106.827 -        
 106.828 -        // superclass query
 106.829 -        size1 = lookup.lookupAll(A.class).size();
 106.830 -        size2 = countInstances(types, A.class);
 106.831 -        
 106.832 -        if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
 106.833 -    }
 106.834 -    
 106.835 -    /** Test interface inheritance.
 106.836 -     */
 106.837 -    public void testInterfaceInheritance() {
 106.838 -        TestInterfaceInheritanceA[] types = {
 106.839 -            new TestInterfaceInheritanceB() {},
 106.840 -            new TestInterfaceInheritanceBB() {},
 106.841 -            new TestInterfaceInheritanceC() {},
 106.842 -            new TestInterfaceInheritanceD() {}
 106.843 -        };
 106.844 -        
 106.845 -        for (int i = 0; i < types.length; i++) {
 106.846 -            ic.add(types[i]);
 106.847 -            if (lookup.lookup(types[i].getClass()) == null) {
 106.848 -                // should find an instance
 106.849 -                fail("Lookup (" + types[i].getClass().getName () + ") found nothing");
 106.850 -            }
 106.851 -        }
 106.852 -        
 106.853 -        int size1, size2;
 106.854 -        
 106.855 -        //interface query
 106.856 -        LL l = new LL ();
 106.857 -        Lookup.Result<?> res = lookup.lookupResult(java.rmi.Remote.class);
 106.858 -        l.source = res;
 106.859 -        size1 = res.allInstances().size();
 106.860 -        size2 = countInstances(types, java.rmi.Remote.class);
 106.861 -        
 106.862 -        if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2);
 106.863 -        
 106.864 -        // superclass query
 106.865 -        size1 = lookup.lookupAll(TestInterfaceInheritanceA.class).size();
 106.866 -        size2 = countInstances(types, TestInterfaceInheritanceA.class);
 106.867 -        
 106.868 -        if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2);
 106.869 -        
 106.870 -        res.addLookupListener (l);
 106.871 -        ic.remove (types[0]);
 106.872 -        
 106.873 -        if (l.getCount () != 1) {
 106.874 -            fail ("No notification that a Remote is removed");
 106.875 -        }
 106.876 -    }
 106.877 -    
 106.878 -    /** Checks whether the AbstractLookup is guarded against modifications
 106.879 -     * while doing some kind of modification.
 106.880 -     */
 106.881 -    public void testModificationArePreventedWhenDoingModifications () throws Exception {
 106.882 -        BrokenPair broken = new BrokenPair (true, false);
 106.883 -        ic.addPair (broken);
 106.884 -        
 106.885 -        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
 106.886 -        Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
 106.887 -        assertEquals ("Broken is found", broken, item);
 106.888 -    }
 106.889 -    
 106.890 -    public void testModificationArePreventedWhenDoingModificationsResult () throws Exception {
 106.891 -        BrokenPair broken = new BrokenPair (false, true);
 106.892 -        ic.addPair (broken);
 106.893 -        
 106.894 -        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
 106.895 -        
 106.896 -        Collection<? extends BrokenPair> c = lookup.lookup (templ).allInstances();
 106.897 -        assertEquals ("One item", 1, c.size ());
 106.898 -        assertEquals ("Broken is found again", broken, c.iterator().next ());
 106.899 -    }
 106.900 -    
 106.901 -    public void testModificationArePreventedWhenDoingModificationsItemAndResult () throws Exception {
 106.902 -        BrokenPair broken = new BrokenPair (false, true);
 106.903 -        ic.addPair (broken);
 106.904 -        
 106.905 -        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
 106.906 -        Lookup.Item<BrokenPair> item = lookup.lookupItem (templ);
 106.907 -        assertEquals ("Broken is found", broken, item);
 106.908 -        
 106.909 -        Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
 106.910 -        assertEquals ("One item", 1, c.size ());
 106.911 -        assertEquals ("Broken is found again", broken, c.iterator().next ());
 106.912 -    }
 106.913 -
 106.914 -    public void testModificationArePreventedWhenDoingModificationsResultAndItem () throws Exception {
 106.915 -        BrokenPair broken = new BrokenPair (false, true);
 106.916 -        ic.addPair (broken);
 106.917 -        
 106.918 -        Lookup.Template<BrokenPair> templ = new Lookup.Template<BrokenPair>(BrokenPair.class);
 106.919 -        Collection<? extends BrokenPair> c = lookup.lookup(templ).allInstances();
 106.920 -        assertEquals ("One item", 1, c.size ());
 106.921 -        assertEquals ("Broken is found again", broken, c.iterator().next ());
 106.922 -        
 106.923 -        Object item = lookup.lookupItem (templ);
 106.924 -        assertEquals ("Broken is found", broken, item);
 106.925 -    }
 106.926 -    
 106.927 -    public void testAddALotOfPairsIntoTheLookupOneByOne () throws Exception {
 106.928 -        Lookup.Result<Integer> res = lookup.lookupResult(Integer.class);
 106.929 -        for (int i = 0; i < 1000; i++) {
 106.930 -            ic.add(i);
 106.931 -        }
 106.932 -        assertEquals (
 106.933 -            "there is the right count", 
 106.934 -            1000, 
 106.935 -            res.allItems().size ()
 106.936 -        );
 106.937 -    }
 106.938 -    
 106.939 -    public void testAddALotOfPairsIntoTheLookup () throws Exception {
 106.940 -        List<Integer> arr = new ArrayList<Integer>();
 106.941 -        for (int i = 0; i < 1000; i++) {
 106.942 -            arr.add(i);
 106.943 -        }
 106.944 -        ic.set (arr, null);
 106.945 -        
 106.946 -        assertEquals (
 106.947 -            "there is the right count", 
 106.948 -            1000, 
 106.949 -            lookup.lookupResult(Integer.class).allItems().size()
 106.950 -        );
 106.951 -    }
 106.952 -
 106.953 -    
 106.954 -    public void testDoubleAddIssue35274 () throws Exception {
 106.955 -        class P extends AbstractLookup.Pair<Object> {
 106.956 -            protected boolean creatorOf(Object obj) { return false; }
 106.957 -            public String getDisplayName() { return ""; }
 106.958 -            public String getId() { return ""; }
 106.959 -            public Object getInstance() { return null; }
 106.960 -            public Class<?> getType() { return Object.class; }
 106.961 -            protected boolean instanceOf(Class<?> c) { return c.isAssignableFrom(getType ()); }
 106.962 -            public @Override int hashCode() {return getClass().hashCode();}
 106.963 -            public @Override boolean equals(Object obj) {return getClass() == obj.getClass();}
 106.964 -        }
 106.965 -        
 106.966 -        P p = new P ();
 106.967 -        
 106.968 -        ic.addPair (p);
 106.969 -        ic.addPair (p);
 106.970 -        
 106.971 -        Lookup.Result<Object> result = lookup.lookupResult(Object.class);
 106.972 -        Collection res = result.allItems ();
 106.973 -        assertEquals ("One item there", 1, res.size ());
 106.974 -        assertTrue ("It is the p", p == res.iterator ().next ());
 106.975 -        
 106.976 -        P p2 = new P ();
 106.977 -        ic.addPair (p2);
 106.978 -        
 106.979 -        Reference<?> ref = new WeakReference<Object>(result);
 106.980 -        result = null;
 106.981 -        assertGC ("The result can disappear", ref);
 106.982 -        
 106.983 -        impl.clearCaches ();
 106.984 -        
 106.985 -        result = lookup.lookupResult(Object.class);
 106.986 -        res = result.allItems ();
 106.987 -        assertEquals ("One item is still there", 1, res.size ());
 106.988 -        assertTrue ("But the p2 replaced p", p2 == res.iterator ().next ());
 106.989 -        
 106.990 -    }
 106.991 -    
 106.992 -    /** Test for proper serialization.
 106.993 -     */
 106.994 -    public void testSerializationSupport () throws Exception {
 106.995 -        doSerializationSupport (1);
 106.996 -    }
 106.997 -    public void testDoubleSerializationSupport () throws Exception {
 106.998 -        doSerializationSupport (2);
 106.999 -    }
106.1000 -
106.1001 -    private void doSerializationSupport (int count) throws Exception {
106.1002 -        if (lookup instanceof Serializable) {
106.1003 -            ic.addPair (new SerialPair ("1"));
106.1004 -            ic.addPair (new SerialPair ("2"));
106.1005 -            ic.addPair (new SerialPair ("3"));
106.1006 -
106.1007 -            Lookup l = (Lookup)reserialize(lookup);
106.1008 -
106.1009 -            assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
106.1010 -
106.1011 -            assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
106.1012 -
106.1013 -            while (count-- > 0) {
106.1014 -                l = (Lookup)reserialize(l);
106.1015 -            }
106.1016 -
106.1017 -            assertEquals ("Able to answer simple query", "1", l.lookup (String.class));
106.1018 -
106.1019 -            assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ());
106.1020 -        }
106.1021 -    }
106.1022 -
106.1023 -    /** When a lookup with two different versions of the same class 
106.1024 -     * get's serialized, the results may be very bad. 
106.1025 -     */
106.1026 -    public void testSerializationOfTwoClassesWithTheSameName () throws Exception {
106.1027 -        if (lookup instanceof Serializable) {
106.1028 -            doTwoSerializedClasses (false, false);
106.1029 -        }
106.1030 -    }
106.1031 -    public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSave () throws Exception {
106.1032 -        if (lookup instanceof Serializable) {
106.1033 -            doTwoSerializedClasses (true, false);
106.1034 -        }
106.1035 -    }
106.1036 -    public void testSerializationOfTwoClassesWithTheSameNameWithBroken () throws Exception {
106.1037 -        if (lookup instanceof Serializable) {
106.1038 -            doTwoSerializedClasses (false, true);
106.1039 -        }
106.1040 -    }
106.1041 -    public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSaveWithBroken () throws Exception {
106.1042 -        if (lookup instanceof Serializable) {
106.1043 -            doTwoSerializedClasses (true, true);
106.1044 -        }
106.1045 -    }
106.1046 -   
106.1047 -    private void doTwoSerializedClasses (boolean queryBeforeSerialization, boolean useBroken) throws Exception {
106.1048 -        ClassLoader loader = new CL ();
106.1049 -        Class c = loader.loadClass (Garbage.class.getName ());
106.1050 -
106.1051 -        // in case of InheritanceTree it creates a slot for class Garbage
106.1052 -        lookup.lookup(c);
106.1053 -
106.1054 -        // but creates new instance and adds it into the lookup
106.1055 -        // without querying for it
106.1056 -        loader = new CL ();
106.1057 -        c = loader.loadClass (Garbage.class.getName ());
106.1058 -
106.1059 -        Object theInstance = c.newInstance ();
106.1060 -
106.1061 -        ic.addPair (new SerialPair (theInstance));
106.1062 -
106.1063 -        Broken2Pair broken = null;
106.1064 -        if (useBroken) {
106.1065 -            broken = new Broken2Pair ();
106.1066 -            ic.addPair (broken);
106.1067 -            
106.1068 -            assertNull (
106.1069 -                "We need to create the slot for the List as " +
106.1070 -                "the Broken2Pair will ask for it after deserialization", 
106.1071 -                lookup.lookup (java.awt.List.class)
106.1072 -            );
106.1073 -        }
106.1074 -
106.1075 -        if (queryBeforeSerialization) {
106.1076 -            assertEquals ("Instance is found", theInstance, lookup.lookup (c));
106.1077 -        }
106.1078 -        
106.1079 -        // replace the old lookup with new one
106.1080 -        lookup = (Lookup)reserialize(lookup);
106.1081 -        
106.1082 -        Lookup.Result result = lookup.lookup (new Lookup.Template (Garbage.class));
106.1083 -        assertEquals ("One item is the result", 1, result.allInstances ().size ());
106.1084 -        Object r = result.allInstances ().iterator ().next ();
106.1085 -        assertNotNull("A value is found", r);
106.1086 -        assertEquals ("It is of the right class", Garbage.class, r.getClass());
106.1087 -    }
106.1088 -   
106.1089 -    /** Test of reorder and item change which used to fail on interfaces.
106.1090 -     */
106.1091 -    public void testReoderingIssue13779 () throws Exception {
106.1092 -        LinkedList arr = new LinkedList ();
106.1093 -        
106.1094 -        class R extends Exception implements Cloneable {
106.1095 -        }
106.1096 -        Object o1 = new R ();
106.1097 -        Object o2 = new R ();
106.1098 -        Object o3 = new R ();
106.1099 -        
106.1100 -        arr.add (o1);
106.1101 -        arr.add (o2);
106.1102 -        
106.1103 -        ic.set (arr, null);
106.1104 -        
106.1105 -        Lookup.Result objectResult = lookup.lookup (new Lookup.Template (Exception.class));
106.1106 -        Lookup.Result interfaceResult = lookup.lookup (new Lookup.Template (Cloneable.class));
106.1107 -        objectResult.allItems ();
106.1108 -        interfaceResult.allItems ();
106.1109 -        
106.1110 -        LL l1 = new LL (objectResult);
106.1111 -        LL l2 = new LL (interfaceResult);
106.1112 -        
106.1113 -        objectResult.addLookupListener(l1);
106.1114 -        interfaceResult.addLookupListener(l2);
106.1115 -        
106.1116 -        arr.addFirst (o3);
106.1117 -        
106.1118 -        ic.set (arr, null);
106.1119 -        
106.1120 -        assertEquals ("One change on objects", 1, l1.getCount ());
106.1121 -        assertEquals ("One change on interfaces", 1, l2.getCount ());
106.1122 -        
106.1123 -        arr.addFirst (new Cloneable () { });
106.1124 -        ic.set (arr, null);
106.1125 -        
106.1126 -        assertEquals ("No change on objects", 0, l1.getCount ());
106.1127 -        assertEquals ("But one change on interfaces", 1, l2.getCount ());
106.1128 -        
106.1129 -    }
106.1130 -    
106.1131 -    public void testDeadlockBetweenProxyResultAndLookupIssue47772 () throws Exception {
106.1132 -        final String myModule = "My Module";
106.1133 -        ic.add (myModule);
106.1134 -        
106.1135 -        class MyProxy extends ProxyLookup {
106.1136 -            public MyProxy () {
106.1137 -                super (new Lookup[] { lookup });
106.1138 -            }
106.1139 -        }
106.1140 -        final MyProxy my = new MyProxy ();
106.1141 -        
106.1142 -        final Lookup.Result allModules = my.lookup (new Lookup.Template (String.class));
106.1143 -        
106.1144 -        class PairThatNeedsInfoAboutModules extends AbstractLookup.Pair {
106.1145 -            public String getDisplayName () {
106.1146 -                return "Need a module";
106.1147 -            }
106.1148 -            public String getId () {
106.1149 -                return getDisplayName ();
106.1150 -            }
106.1151 -            public Class getType () {
106.1152 -                return Integer.class;
106.1153 -            }
106.1154 -            protected boolean instanceOf (Class c) {
106.1155 -                if (c == Integer.class) {
106.1156 -                    synchronized (this) {
106.1157 -                        notifyAll ();
106.1158 -                        try {
106.1159 -                            wait (1000);
106.1160 -                        } catch (InterruptedException ex) {
106.1161 -                            fail (ex.getMessage ());
106.1162 -                        }
106.1163 -                    }
106.1164 -                    java.util.Collection coll = allModules.allInstances ();
106.1165 -                    assertEquals ("Size is 1", 1, coll.size ());
106.1166 -                    assertEquals ("My module is there", myModule, coll.iterator ().next ());
106.1167 -                }
106.1168 -                return c.isAssignableFrom (Integer.class);
106.1169 -            }
106.1170 -            
106.1171 -            public Object getInstance () {
106.1172 -                return new Integer (10);
106.1173 -            }
106.1174 -            
106.1175 -            protected boolean creatorOf (Object obj) {
106.1176 -                return new Integer (10).equals (obj);
106.1177 -            }
106.1178 -        }
106.1179 -        
106.1180 -        PairThatNeedsInfoAboutModules pair = new PairThatNeedsInfoAboutModules ();
106.1181 -        ic.addPair (pair);
106.1182 -        
106.1183 -        synchronized (pair) {
106.1184 -            class BlockInInstanceOf implements Runnable {
106.1185 -                public void run () {
106.1186 -                    Integer i = my.lookup(Integer.class);
106.1187 -                    assertEquals (new Integer (10), i);
106.1188 -                }
106.1189 -            }
106.1190 -            BlockInInstanceOf blk = new BlockInInstanceOf ();
106.1191 -            Executors.newSingleThreadScheduledExecutor().schedule(blk, 0, TimeUnit.MICROSECONDS);
106.1192 -            pair.wait ();
106.1193 -        }
106.1194 -        
106.1195 -        java.util.Collection coll = allModules.allInstances ();
106.1196 -        assertEquals ("Size is 1", 1, coll.size ());
106.1197 -        assertEquals ("My module is there", myModule, coll.iterator ().next ());
106.1198 -    }
106.1199 -
106.1200 -    public void testAWayToGenerateProblem13779 () {
106.1201 -        ic.add (new Integer (1));
106.1202 -        ic.add (new Integer (2));
106.1203 -        ic.add (new Integer (1));
106.1204 -        ic.add (new Integer (2));
106.1205 -        
106.1206 -        Collection c = lookup.lookup (new Lookup.Template (Integer.class)).allInstances ();
106.1207 -        assertEquals ("There are two objects", 2, c.size ());
106.1208 -        
106.1209 -    }
106.1210 -    
106.1211 -    /** Replacing items with different objects.
106.1212 -     */
106.1213 -    public void testReplacingObjectsDoesNotGenerateException () throws Exception {
106.1214 -        LinkedList arr = new LinkedList ();
106.1215 -        
106.1216 -        class R extends Exception implements Cloneable {
106.1217 -        }
106.1218 -        arr.add (new R ());
106.1219 -        arr.add (new R ());
106.1220 -        
106.1221 -        ic.set (arr, null);
106.1222 -        
106.1223 -        arr.clear();
106.1224 -        
106.1225 -        arr.add (new R ());
106.1226 -        arr.add (new R ());
106.1227 -        
106.1228 -        ic.set (arr, null);
106.1229 -    }
106.1230 -
106.1231 -    public void testAfterDeserializationNoQueryIsPeformedOnAlreadyQueriedObjects() throws Exception {
106.1232 -        if (! (lookup instanceof Serializable)) {
106.1233 -            // well this test works only for serializable lookups
106.1234 -            return;
106.1235 -        }
106.1236 -        
106.1237 -        SerialPair my = new SerialPair ("no");
106.1238 -        ic.addPair (my);
106.1239 -        
106.1240 -        Lookup.Result res = lookup.lookup (new Lookup.Template (String.class));
106.1241 -        assertEquals ("One instance", 1, res.allInstances().size ());
106.1242 -        assertEquals ("my.instanceOf called once", 1, my.countInstanceOf);
106.1243 -        
106.1244 -        Lookup serial = (Lookup)reserialize(lookup);
106.1245 -        
106.1246 -        Lookup.Result r2 = serial.lookup(new Lookup.Template(String.class));
106.1247 -        
106.1248 -        assertEquals ("One item", 1, r2.allItems ().size ());
106.1249 -        Object one = r2.allItems().iterator().next ();
106.1250 -        assertEquals ("The right class", SerialPair.class, one.getClass());
106.1251 -        SerialPair p = (SerialPair)one;
106.1252 -        
106.1253 -        assertEquals ("p.instanceOf has not been queried", 0, p.countInstanceOf);
106.1254 -    }
106.1255 -    
106.1256 -    /** Checks the iterator */
106.1257 -    private <T> void checkIterator(String msg, Iterator<? extends T> it1, List<? extends T> list) {
106.1258 -        int cnt = 0;
106.1259 -        Iterator<? extends T> it2 = list.iterator();
106.1260 -        while (it1.hasNext () && it2.hasNext ()) {
106.1261 -            T n1 = it1.next();
106.1262 -            T n2 = it2.next();
106.1263 -            
106.1264 -            if (n1 != n2) {
106.1265 -                fail (msg + " iterator[" + cnt + "] = " + n1 + " but list[" + cnt + "] = " + n2);
106.1266 -            }
106.1267 -            
106.1268 -            cnt++;
106.1269 -        }
106.1270 -        
106.1271 -        if (it1.hasNext ()) {
106.1272 -            fail ("Iterator has more elements than list");
106.1273 -        }
106.1274 -        
106.1275 -        if (it2.hasNext ()) {
106.1276 -            fail ("List has more elements than iterator");
106.1277 -        }
106.1278 -    }
106.1279 -    
106.1280 -    
106.1281 -    public void testResultsAreUnmodifyableOrAtLeastTheyDoNotPropagateToCache() throws Exception {
106.1282 -        String s = "Ahoj";
106.1283 -        
106.1284 -        ic.add(s);
106.1285 -        
106.1286 -        Lookup.Result res = lookup.lookup(new Template(String.class));
106.1287 -        
106.1288 -        for (int i = 1; i < 5; i++) {
106.1289 -            Collection c1 = res.allInstances();
106.1290 -            Collection c2 = res.allClasses();
106.1291 -            Collection c3 = res.allItems();
106.1292 -
106.1293 -            assertTrue(i + ": c1 has it", c1.contains(s));
106.1294 -            assertTrue(i + ": c2 has it", c2.contains(s.getClass()));
106.1295 -            assertEquals(i + ": c3 has one", 1, c3.size());
106.1296 -            Lookup.Item item = (Lookup.Item) c3.iterator().next();
106.1297 -            assertEquals(i + ": c3 has it", s, item.getInstance());
106.1298 -
106.1299 -            try {
106.1300 -                c1.remove(s);
106.1301 -                assertEquals("No elements now", 0, c1.size());
106.1302 -            } catch (UnsupportedOperationException ex) {
106.1303 -                // ok, this need not be supported
106.1304 -            }
106.1305 -            try {
106.1306 -                c2.remove(s.getClass());
106.1307 -                assertEquals("No elements now", 0, c2.size());
106.1308 -            } catch (UnsupportedOperationException ex) {
106.1309 -                // ok, this need not be supported
106.1310 -            }
106.1311 -            try {
106.1312 -                c3.remove(item);
106.1313 -                assertEquals("No elements now", 0, c3.size());
106.1314 -            } catch (UnsupportedOperationException ex) {
106.1315 -                // ok, this need not be supported
106.1316 -            }
106.1317 -        }
106.1318 -    }
106.1319 -    
106.1320 -    public void testSomeProblemWithDVBFrameworkSeemsToBeInLookup() {
106.1321 -        for (int i = 0; i < 5; i++) {
106.1322 -            ic.add(lookup);
106.1323 -            assertEquals("Can be found", lookup, lookup.lookup(lookup.getClass()));
106.1324 -            ic.set(Collections.EMPTY_LIST, null);
106.1325 -        }        
106.1326 -    }
106.1327 -
106.1328 -    public void testListeningAndQueryingByTwoListenersInstances() {
106.1329 -        doListeningAndQueryingByTwoListeners(0);
106.1330 -    }
106.1331 -    public void testListeningAndQueryingByTwoListenersClasses() {
106.1332 -        doListeningAndQueryingByTwoListeners(1);        
106.1333 -    }
106.1334 -    public void testListeningAndQueryingByTwoListenersItems() {
106.1335 -        doListeningAndQueryingByTwoListeners(2);
106.1336 -    }
106.1337 -    
106.1338 -    
106.1339 -    private void doListeningAndQueryingByTwoListeners(final int type) {
106.1340 -        class L implements LookupListener {
106.1341 -            Lookup.Result integer = lookup.lookup(new Template(Integer.class));
106.1342 -            Lookup.Result number = lookup.lookup(new Template(Number.class));
106.1343 -            Lookup.Result serial = lookup.lookup(new Template(Serializable.class));
106.1344 -            
106.1345 -            {
106.1346 -                integer.addLookupListener(this);
106.1347 -                number.addLookupListener(this);
106.1348 -                serial.addLookupListener(this);
106.1349 -            }
106.1350 -            
106.1351 -            int round;
106.1352 -            
106.1353 -            public void resultChanged(LookupEvent ev) {
106.1354 -                Collection c1 = get(type, integer);
106.1355 -                Collection c2 = get(type, number);
106.1356 -                Collection c3 = get(type, serial);
106.1357 -                
106.1358 -                assertEquals("round " + round + " c1 vs. c2", c1, c2);
106.1359 -                assertEquals("round " + round + " c1 vs. c3", c1, c3);
106.1360 -                assertEquals("round " + round + " c2 vs. c3", c2, c3);
106.1361 -                
106.1362 -                round++;
106.1363 -            }            
106.1364 -
106.1365 -            private Collection get(int type, Lookup.Result res) {
106.1366 -                Collection c;
106.1367 -                switch(type) {
106.1368 -                    case 0: c = res.allInstances(); break;
106.1369 -                    case 1: c = res.allClasses(); break;
106.1370 -                    case 2: c = res.allItems(); break;
106.1371 -                    default: c = null; fail("Type: " + type); break;
106.1372 -                }
106.1373 -                
106.1374 -                assertNotNull(c);
106.1375 -                return new ArrayList(c);
106.1376 -            }
106.1377 -        }
106.1378 -        
106.1379 -        L listener = new L();
106.1380 -        listener.resultChanged(null);
106.1381 -        
106.1382 -        for(int i = 0; i < 100; i++) {
106.1383 -            ic.add(new Integer(i));
106.1384 -        }
106.1385 -        
106.1386 -        assertEquals("3x100+1 checks", 301, listener.round);
106.1387 -    }
106.1388 -    
106.1389 -    public void testChangeOfNodeDoesNotFireChangeInActionMap() {
106.1390 -        ActionMap am = new ActionMap();
106.1391 -        Lookup s = Lookups.singleton(am);
106.1392 -        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, false);
106.1393 -    }
106.1394 -    public void testChangeOfNodeDoesNotFireChangeInActionMapSimple() {
106.1395 -        ActionMap am = new ActionMap();
106.1396 -        Lookup s = Lookups.singleton(am);
106.1397 -        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, true);
106.1398 -    }
106.1399 -
106.1400 -    public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookupSimple() {
106.1401 -        doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(true);
106.1402 -    }
106.1403 -    
106.1404 -    public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup() {
106.1405 -        doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(false);
106.1406 -    }
106.1407 -    private void doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(boolean wrapBySimple) {
106.1408 -        final ActionMap am = new ActionMap();
106.1409 -        
106.1410 -        class Before extends AbstractLookup {
106.1411 -            public InstanceContent ic;
106.1412 -            public Before() {
106.1413 -                this(new InstanceContent());
106.1414 -            }
106.1415 -            
106.1416 -            private Before(InstanceContent ic) {
106.1417 -                super(ic);
106.1418 -                this.ic = ic;
106.1419 -            }
106.1420 -
106.1421 -            protected @Override void beforeLookup(Template template) {
106.1422 -                if (ic != null) {
106.1423 -                    ic.add(am);
106.1424 -                    ic = null;
106.1425 -                }
106.1426 -            }
106.1427 -        }
106.1428 -        
106.1429 -        Before s = new Before();
106.1430 -        doChangeOfNodeDoesNotFireChangeInActionMap(am, s, wrapBySimple);
106.1431 -        
106.1432 -        assertNull("beforeLookup called once", s.ic);
106.1433 -    }
106.1434 -    
106.1435 -    private void doChangeOfNodeDoesNotFireChangeInActionMap(final ActionMap am, Lookup actionMapLookup, final boolean wrapBySimple) {
106.1436 -        Lookup[] lookups = { lookup, actionMapLookup };
106.1437 -        
106.1438 -        class Provider implements Lookup.Provider {
106.1439 -            ProxyLookup delegate;
106.1440 -            Lookup query;
106.1441 -            
106.1442 -            public Provider(Lookup[] arr) {
106.1443 -                if (wrapBySimple) {
106.1444 -                    delegate = new ProxyLookup(arr);
106.1445 -                    query = Lookups.proxy(this);
106.1446 -                } else {
106.1447 -                    query = delegate = new ProxyLookup(arr);
106.1448 -                }
106.1449 -            }
106.1450 -            
106.1451 -            public Lookup getLookup() {
106.1452 -                return delegate;
106.1453 -            }
106.1454 -            
106.1455 -            public void setLookups(Lookup... arr) {
106.1456 -                if (wrapBySimple) {
106.1457 -                    delegate = new ProxyLookup(arr);                    
106.1458 -                } else {
106.1459 -                    delegate.setLookups(arr);
106.1460 -                }
106.1461 -            }
106.1462 -        }
106.1463 -        
106.1464 -        Provider p = new Provider(lookups);
106.1465 -        
106.1466 -        Lookup.Result res = p.query.lookup(new Lookup.Template(ActionMap.class));
106.1467 -        LL ll = new LL();
106.1468 -        res.addLookupListener(ll);
106.1469 -
106.1470 -        Collection c = res.allInstances();
106.1471 -        assertFalse("Has next", c.isEmpty());
106.1472 -        
106.1473 -        ActionMap am1 = (ActionMap)c.iterator().next();
106.1474 -        assertEquals("Am is there", am, am1);
106.1475 -        
106.1476 -        assertEquals("No change in first get", 0, ll.getCount());
106.1477 -        
106.1478 -        Object m1 = new InputMap();
106.1479 -        Object m2 = new InputMap();
106.1480 -        
106.1481 -        ic.add(m1);
106.1482 -        assertEquals("No change in ActionMap 1", 0, ll.getCount());
106.1483 -        ic.set(Collections.singletonList(m2), null);
106.1484 -        assertEquals("No change in ActionMap 2", 0, ll.getCount());
106.1485 -        ic.add(m2);
106.1486 -        assertEquals("No change in ActionMap 3", 0, ll.getCount());
106.1487 -        p.setLookups(lookup, actionMapLookup, Lookup.EMPTY);
106.1488 -        assertEquals("No change in ActionMap 4", 0, ll.getCount());
106.1489 -        
106.1490 -        ActionMap am2 = p.query.lookup(ActionMap.class);
106.1491 -        assertEquals("Still the same action map", am, am2);
106.1492 -        
106.1493 -        
106.1494 -        class Before extends AbstractLookup {
106.1495 -            public InstanceContent ic;
106.1496 -            public Before() {
106.1497 -                this(new InstanceContent());
106.1498 -            }
106.1499 -            
106.1500 -            private Before(InstanceContent ic) {
106.1501 -                super(ic);
106.1502 -                this.ic = ic;
106.1503 -            }
106.1504 -
106.1505 -            protected @Override void beforeLookup(Template template) {
106.1506 -                if (ic != null) {
106.1507 -                    ic.add(am);
106.1508 -                    ic = null;
106.1509 -                }
106.1510 -            }
106.1511 -        }
106.1512 -        
106.1513 -        Before s = new Before();
106.1514 -        
106.1515 -        // adding different Before, but returning the same instance
106.1516 -        // this happens with metaInfServices lookup often, moreover
106.1517 -        // it adds the instance in beforeLookup, which confuses a lot
106.1518 -        p.setLookups(new Lookup[]{ lookup, new Before() });
106.1519 -        assertEquals("No change in ActionMap 5", 0, ll.getCount());
106.1520 -        
106.1521 -        
106.1522 -    }
106.1523 -
106.1524 -    public void testTasklistsCase() throws Exception {
106.1525 -        ic.remove(new Object());
106.1526 -    }
106.1527 -    
106.1528 -    
106.1529 -
106.1530 -    public void testMultipleListeners() {
106.1531 -        Object object = new ImplementationObject();
106.1532 -        ic.add(object);
106.1533 -        
106.1534 -        Listener[] listeners = new Listener[4];
106.1535 -        Lookup.Result result = lookup.lookup(new Lookup.Template(LookupObject.class));
106.1536 -        for(int i = 0; i < listeners.length; ++i) {
106.1537 -            listeners[i] = new Listener();
106.1538 -            result.addLookupListener(listeners[i]);
106.1539 -        }
106.1540 -        // initialize listening
106.1541 -        result.allItems();
106.1542 -        
106.1543 -        ic.remove(object);
106.1544 -        
106.1545 -        // Apparently, only odd-numbered listeners get called when there are multiple LookupListeners on a result
106.1546 -        //for(int i = 0; i < listeners.length; ++i) {
106.1547 -        //    System.out.println("Listener " + i + ": " + listeners[i].wasCalled());            
106.1548 -        //}
106.1549 -        for(int i = 0; i < listeners.length; ++i) {
106.1550 -            assertTrue("Listener " + i + " called", listeners[i].wasCalled());
106.1551 -        }
106.1552 -    }
106.1553 -
106.1554 -    static Object reserialize(Object o) throws Exception {
106.1555 -        ByteArrayOutputStream os = new ByteArrayOutputStream();
106.1556 -        ObjectOutputStream oos = new ObjectOutputStream(os);
106.1557 -        oos.writeObject(o);
106.1558 -        oos.close();
106.1559 -
106.1560 -        ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
106.1561 -        ObjectInputStream ois = new ObjectInputStream(is);
106.1562 -        return ois.readObject();
106.1563 -    }
106.1564 -    
106.1565 -    private class Listener implements LookupListener {
106.1566 -        private boolean listenerCalled = false;
106.1567 -        
106.1568 -        public void resultChanged(LookupEvent ev) {
106.1569 -            listenerCalled = true;
106.1570 -        }
106.1571 -        
106.1572 -        public boolean wasCalled() {
106.1573 -            return listenerCalled;
106.1574 -        }
106.1575 -        
106.1576 -        public void reset() {
106.1577 -            listenerCalled = false;
106.1578 -        }
106.1579 -    }
106.1580 -    
106.1581 -    private interface LookupObject {}
106.1582 -    private class ImplementationObject implements LookupObject {}
106.1583 -    private class NullObject implements LookupObject {}
106.1584 -    
106.1585 -    
106.1586 -    public void testReturnSomethingElseThenYouClaimYouWillReturn() {
106.1587 -        class Liar extends AbstractLookup.Pair {
106.1588 -            public Object obj;
106.1589 -            
106.1590 -            protected boolean instanceOf(Class c) {
106.1591 -                return c.isAssignableFrom(String.class);
106.1592 -            }
106.1593 -
106.1594 -            protected boolean creatorOf(Object obj) {
106.1595 -                return this.obj == obj;
106.1596 -            }
106.1597 -
106.1598 -            public Object getInstance() {
106.1599 -                return this.obj;
106.1600 -            }
106.1601 -
106.1602 -            public Class getType() {
106.1603 -                return String.class;
106.1604 -            }
106.1605 -
106.1606 -            public String getId() {
106.1607 -                return String.class.getName();
106.1608 -            }
106.1609 -
106.1610 -            public String getDisplayName() {
106.1611 -                return getId();
106.1612 -            }
106.1613 -        }
106.1614 -        
106.1615 -        
106.1616 -        Liar l = new Liar();
106.1617 -        l.obj = new Integer(5);
106.1618 -        
106.1619 -        this.ic.addPair(l);
106.1620 -        
106.1621 -        Collection c = lookup.lookup(new Lookup.Template(String.class)).allInstances();
106.1622 -        assertTrue("It is empty: " + c, c.isEmpty());
106.1623 -    }
106.1624 -
106.1625 -    public void testCanProxyLookupHaveWrongResults() {
106.1626 -        class L implements LookupListener {
106.1627 -            ProxyLookup pl;
106.1628 -            Lookup.Result<String> original;
106.1629 -            Lookup.Result<String> wrapped;
106.1630 -            boolean ok;
106.1631 -
106.1632 -            public void test() {
106.1633 -                pl = new ProxyLookup(lookup);
106.1634 -                original = lookup.lookupResult(String.class);
106.1635 -
106.1636 -                original.addLookupListener(this);
106.1637 -
106.1638 -                wrapped = pl.lookupResult(String.class);
106.1639 -
106.1640 -                assertEquals("Original empty", 0, original.allInstances().size());
106.1641 -                assertEquals("Wrapped empty", 0, wrapped.allInstances().size());
106.1642 -
106.1643 -                ic.add("Hello!");
106.1644 -            }
106.1645 -
106.1646 -            public void resultChanged(LookupEvent ev) {
106.1647 -                ok = true;
106.1648 -
106.1649 -                assertEquals("Original has hello", 1, original.allInstances().size());
106.1650 -                assertEquals("Wrapped has hello", 1, wrapped.allInstances().size());
106.1651 -            }
106.1652 -
106.1653 -        }
106.1654 -        L listener = new L();
106.1655 -        listener.test();
106.1656 -        assertTrue("Listener called", listener.ok);
106.1657 -    }
106.1658 -
106.1659 -    public void testObjectFromInstanceContentConverterDisappearsIfNotReferenced() {
106.1660 -        Conv converter = new Conv("foo");
106.1661 -        ic.add (converter, converter);
106.1662 -        Lookup lkp = instanceLookup;
106.1663 -        StringBuilder sb = lookup.lookup (StringBuilder.class);
106.1664 -        assertNotNull (sb);
106.1665 -        int hash = System.identityHashCode(sb);
106.1666 -        assertEquals ("foo", sb.toString());
106.1667 -        Reference<StringBuilder> r = new WeakReference<StringBuilder>(sb);
106.1668 -        sb = null;
106.1669 -        assertGC("Lookup held onto object", r);
106.1670 -        sb = lookup.lookup (StringBuilder.class);
106.1671 -        assertNotSame(hash, System.identityHashCode(sb));
106.1672 -        r = new WeakReference<StringBuilder>(sb);
106.1673 -        sb = null;
106.1674 -        assertGC("Lookup held onto object", r);
106.1675 -        ic.remove (converter, converter);
106.1676 -        Reference <InstanceContent.Convertor> cref = new WeakReference<InstanceContent.Convertor>(converter);
106.1677 -        converter = null;
106.1678 -        assertGC("Converter still referenced", cref); 
106.1679 -
106.1680 -        sb = lkp.lookup(StringBuilder.class);
106.1681 -        assertNull ("Converter removed from lookup, but object it " +
106.1682 -                "created still present:'" + sb +"'", sb);
106.1683 -        converter = new Conv("bar");
106.1684 -        ic.add (converter, converter);
106.1685 -        assertNotNull (lkp.lookup(StringBuilder.class));
106.1686 -        assertEquals ("bar", lkp.lookup(StringBuilder.class).toString());
106.1687 -    }
106.1688 -
106.1689 -    private static class Conv implements InstanceContent.Convertor<Conv, StringBuilder> {
106.1690 -        private final String str;
106.1691 -        private Conv (String str) {
106.1692 -            this.str = str;
106.1693 -        }
106.1694 -
106.1695 -        public StringBuilder convert(Conv obj) {
106.1696 -            return new StringBuilder (str);
106.1697 -        }
106.1698 -
106.1699 -        public Class<? extends StringBuilder> type(Conv obj) {
106.1700 -            return StringBuilder.class;
106.1701 -        }
106.1702 -
106.1703 -        public String id(Conv obj) {
106.1704 -            return "Foo";
106.1705 -        }
106.1706 -
106.1707 -        public String displayName(Conv obj) {
106.1708 -            return "Foo";
106.1709 -        }
106.1710 -    } // end of Conv
106.1711 -
106.1712 -    public void testCanGCResults() throws Exception {
106.1713 -        class L implements LookupListener {
106.1714 -            int cnt;
106.1715 -            
106.1716 -            public void resultChanged(LookupEvent ev) {
106.1717 -                cnt++;
106.1718 -            }
106.1719 -            
106.1720 -        }
106.1721 -        L listener1 = new L();
106.1722 -        L listener2 = new L();
106.1723 -        
106.1724 -        Lookup.Result<String> res1 = this.instanceLookup.lookupResult(String.class);
106.1725 -        Lookup.Result<String> res2 = this.lookup.lookupResult(String.class);
106.1726 -        
106.1727 -        assertEquals("Empty1", 0, res1.allItems().size());
106.1728 -        assertEquals("Empty2", 0, res2.allItems().size());
106.1729 -        
106.1730 -        res1.addLookupListener(listener1);
106.1731 -        res2.addLookupListener(listener2);
106.1732 -        
106.1733 -        addInstances(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
106.1734 -        this.ic.add("Ahoj");
106.1735 -        
106.1736 -        assertEquals("Change1", 1, listener1.cnt);
106.1737 -        assertEquals("Change2", 1, listener2.cnt);
106.1738 -        
106.1739 -        assertEquals("Full1", 1, res1.allItems().size());
106.1740 -        assertEquals("Full2", 1, res2.allItems().size());
106.1741 -        
106.1742 -        
106.1743 -        Reference<Object> ref2 = new WeakReference<Object>(res2);
106.1744 -        res2 = null;
106.1745 -        assertGC("Result can disappear", ref2);
106.1746 -    }
106.1747 -    
106.1748 -    void beforeActualTest(String n) {
106.1749 -        if (n.equals("testEqualsIsNotCalledTooMuch")) {
106.1750 -            CntPair.cnt = 0;
106.1751 -            CntPair.hashCnt = 0;
106.1752 -            CntPair.instances = 0;
106.1753 -            int how = 1000;
106.1754 -
106.1755 -            for(int i = 0; i < how; i++) {
106.1756 -                this.ic.addPair(new CntPair("x" + i));
106.1757 -            }
106.1758 -
106.1759 -            assertEquals("No equals called", 0, CntPair.cnt);
106.1760 -            assertEquals("1000 instances ", how, CntPair.instances);
106.1761 -        }
106.1762 -    }
106.1763 -    
106.1764 -    public void testEqualsIsNotCalledTooMuch() throws Exception {
106.1765 -        // most of the work done in beforeActualTest
106.1766 -
106.1767 -        // desirable: assertEquals("no comparitions", 0, CntPair.cnt);
106.1768 -        // works for InheritanceTree, but not for ArrayStorage, but array
106.1769 -        // storages are generally small
106.1770 -        
106.1771 -        if (CntPair.cnt > 12000) {
106.1772 -            fail("Too much comparitions " + CntPair.cnt);
106.1773 -        }
106.1774 -        if (CntPair.hashCnt > 40000) {
106.1775 -            fail("Too much hashes: " + CntPair.hashCnt);
106.1776 -        }
106.1777 -        
106.1778 -        assertEquals("instaces is enough", 1000, CntPair.instances);
106.1779 -    }
106.1780 -    
106.1781 -    /** Adds instances to the instance lookup.
106.1782 -     */
106.1783 -    private void addInstances (Object... instances) {
106.1784 -        for (int i = 0; i < instances.length; i++) {
106.1785 -            ic.add(instances[i]);
106.1786 -        }
106.1787 -    }
106.1788 -    
106.1789 -    /** Count instances of clazz in an array. */
106.1790 -    private int countInstances (Object[] objs, Class clazz) {
106.1791 -        int count = 0;
106.1792 -        for (int i = 0; i < objs.length; i++) {
106.1793 -            if (clazz.isInstance(objs[i])) count++;
106.1794 -        }
106.1795 -        return count;
106.1796 -    }
106.1797 -    
106.1798 -    /** Counting listener */
106.1799 -    protected static class LL implements LookupListener {
106.1800 -        private int count = 0;
106.1801 -        public Object source;
106.1802 -        public Thread changesIn;
106.1803 -        
106.1804 -        public LL () {
106.1805 -            this (null);
106.1806 -        }
106.1807 -        
106.1808 -        public LL (Object source) {
106.1809 -            this.source = source;
106.1810 -        }
106.1811 -        
106.1812 -        public void resultChanged(LookupEvent ev) {
106.1813 -            if (changesIn != null) {
106.1814 -                assertEquals("Changes in the same thread", changesIn, Thread.currentThread());
106.1815 -            } else {
106.1816 -                changesIn = Thread.currentThread();
106.1817 -            }
106.1818 -            ++count;
106.1819 -            if (source != null) {
106.1820 -                assertSame ("Source is the same", source, ev.getSource ());
106.1821 -//                assertSame ("Result is the same", source, ev.getResult ());
106.1822 -            }
106.1823 -        }
106.1824 -
106.1825 -        public int getCount() {
106.1826 -            int i = count;
106.1827 -            count = 0;
106.1828 -            return i;
106.1829 -        }
106.1830 -    };
106.1831 -
106.1832 -    /** A set of interfaces for testInterfaceInheritance
106.1833 -     */
106.1834 -    interface TestInterfaceInheritanceA {}
106.1835 -    interface TestInterfaceInheritanceB extends TestInterfaceInheritanceA, java.rmi.Remote {}
106.1836 -    interface TestInterfaceInheritanceBB extends TestInterfaceInheritanceB {}
106.1837 -    interface TestInterfaceInheritanceC extends TestInterfaceInheritanceA, java.rmi.Remote {}
106.1838 -    interface TestInterfaceInheritanceD extends TestInterfaceInheritanceA {}
106.1839 -    
106.1840 -    /** A special class for garbage test */
106.1841 -    public static final class Garbage extends Object implements Serializable {
106.1842 -        static final long serialVersionUID = 435340912534L;
106.1843 -    }
106.1844 -    
106.1845 -
106.1846 -    /* A classloader that can load one class in a special way */
106.1847 -    private static class CL extends ClassLoader {
106.1848 -        public CL () {
106.1849 -            super (null);
106.1850 -        }
106.1851 -
106.1852 -        public @Override Class findClass(String name) throws ClassNotFoundException {
106.1853 -            if (name.equals (Garbage.class.getName ())) {
106.1854 -                String n = name.replace ('.', '/');
106.1855 -                java.io.InputStream is = getClass ().getResourceAsStream ("/" + n + ".class");
106.1856 -                byte[] arr = new byte[8096];
106.1857 -                try {
106.1858 -                    int cnt = is.read (arr);
106.1859 -                    if (cnt == arr.length) {
106.1860 -                        fail ("Buffer to load the class is not big enough");
106.1861 -                    }
106.1862 -
106.1863 -                    return defineClass (name, arr, 0, cnt);
106.1864 -                } catch (java.io.IOException ex) {
106.1865 -                        ex.printStackTrace();
106.1866 -                        fail ("IO Exception");
106.1867 -                        return null;
106.1868 -                }
106.1869 -            } else {
106.1870 -                return null;
106.1871 -            }
106.1872 -        }
106.1873 -
106.1874 -        /** Convert obj to other object. There is no need to implement
106.1875 -         * cache mechanism. It is provided by AbstractLookup.Item.getInstance().
106.1876 -         * Method should be called more than once because Lookup holds
106.1877 -         * just weak reference.
106.1878 -         */
106.1879 -        public Object convert(Object obj) {
106.1880 -            return null;
106.1881 -        }
106.1882 -
106.1883 -        /** Return type of converted object. */
106.1884 -        public Class type(Object obj) {
106.1885 -            try {
106.1886 -                return loadClass (Garbage.class.getName ());
106.1887 -            } catch (ClassNotFoundException ex) {
106.1888 -                fail ("Class not found");
106.1889 -                throw new InternalError ();
106.1890 -            }
106.1891 -        }
106.1892 -    }
106.1893 -    
106.1894 -    private static final class CntPair extends AbstractLookup.Pair {
106.1895 -        private static int instances;
106.1896 -        private String txt;
106.1897 -        
106.1898 -        public CntPair(String txt) {
106.1899 -            this.txt = txt;
106.1900 -            instances++;
106.1901 -        }
106.1902 -
106.1903 -        public static int hashCnt;
106.1904 -        @Override
106.1905 -        public int hashCode() {
106.1906 -            hashCnt++;
106.1907 -            return txt.hashCode() + 3777;
106.1908 -        }
106.1909 -
106.1910 -        public static int cnt;
106.1911 -        @Override
106.1912 -        public boolean equals(Object obj) {
106.1913 -            cnt++;
106.1914 -            
106.1915 -            if (obj == null) {
106.1916 -                return false;
106.1917 -            }
106.1918 -            if (getClass() != obj.getClass()) {
106.1919 -                return false;
106.1920 -            }
106.1921 -            final CntPair other = (CntPair) obj;
106.1922 -            if (this.txt != other.txt && (this.txt == null || !this.txt.equals(other.txt))) {
106.1923 -                return false;
106.1924 -            }
106.1925 -            return true;
106.1926 -        }
106.1927 -
106.1928 -        protected boolean instanceOf(Class c) {
106.1929 -            return c.isAssignableFrom(String.class);
106.1930 -        }
106.1931 -
106.1932 -        protected boolean creatorOf(Object obj) {
106.1933 -            return obj == txt;
106.1934 -        }
106.1935 -
106.1936 -        public Object getInstance() {
106.1937 -            return txt;
106.1938 -        }
106.1939 -
106.1940 -        public Class getType() {
106.1941 -            return String.class;
106.1942 -        }
106.1943 -
106.1944 -        public String getId() {
106.1945 -            return txt;
106.1946 -        }
106.1947 -
106.1948 -        public String getDisplayName() {
106.1949 -            return txt;
106.1950 -        }
106.1951 -        
106.1952 -    }
106.1953 -
106.1954 -    public static final class SerialPair extends AbstractLookup.Pair
106.1955 -    implements java.io.Serializable {
106.1956 -        static final long serialVersionUID = 54305834L;
106.1957 -        private Object value;
106.1958 -        public transient int countInstanceOf;
106.1959 -        
106.1960 -        public SerialPair (Object value) {
106.1961 -            this.value = value;
106.1962 -        }
106.1963 -        
106.1964 -        protected boolean creatorOf(Object obj) {
106.1965 -            return obj == value;
106.1966 -        }
106.1967 -        
106.1968 -        public String getDisplayName() {
106.1969 -            return getId ();
106.1970 -        }
106.1971 -        
106.1972 -        public String getId() {
106.1973 -            return value.toString();
106.1974 -        }
106.1975 -        
106.1976 -        public Object getInstance() {
106.1977 -            return value;
106.1978 -        }
106.1979 -        
106.1980 -        public Class getType() {
106.1981 -            return value.getClass ();
106.1982 -        }
106.1983 -        
106.1984 -        protected boolean instanceOf(Class c) {
106.1985 -            countInstanceOf++;
106.1986 -            return c.isInstance(value);
106.1987 -        }
106.1988 -    } // end of SerialPair
106.1989 -    
106.1990 -    private static class BrokenPair extends AbstractLookup.Pair {
106.1991 -        private transient ThreadLocal IN = new ThreadLocal ();
106.1992 -        private boolean checkModify;
106.1993 -        private boolean checkQuery;
106.1994 -        
106.1995 -        public BrokenPair (boolean checkModify, boolean checkQuery) {
106.1996 -            this.checkModify = checkModify;
106.1997 -            this.checkQuery = checkQuery;
106.1998 -        }
106.1999 -        
106.2000 -        protected boolean creatorOf(Object obj) { return this == obj; }
106.2001 -        public String getDisplayName() { return "Broken"; }
106.2002 -        public String getId() { return "broken"; }
106.2003 -        public Object getInstance() { return this; }
106.2004 -        public Class getType() { return getClass (); }
106.2005 -        protected boolean instanceOf(Class c) { 
106.2006 -            
106.2007 -            if (checkQuery) {
106.2008 -                if (IN.get () == null) {
106.2009 -                    try {
106.2010 -                        IN.set (this);
106.2011 -                        // broken behaviour, tries to modify the lookup
106.2012 -                        // queries have to survive
106.2013 -
106.2014 -                        running.lookup.lookup (java.awt.List.class);
106.2015 -
106.2016 -                        // 
106.2017 -                        // creation of new result has to survive as well
106.2018 -                        Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.Button.class));
106.2019 -                        Collection all = myQuery.allItems ();
106.2020 -                    } finally {
106.2021 -                        IN.set (null);
106.2022 -                    }
106.2023 -                }
106.2024 -            }
106.2025 -                
106.2026 -
106.2027 -            if (checkModify) {
106.2028 -                //
106.2029 -                // modifications should fail
106.2030 -                //
106.2031 -
106.2032 -                try {
106.2033 -                    running.ic.addPair (new SerialPair (""));
106.2034 -                    fail ("Modification from a query should be prohibited");
106.2035 -                } catch (IllegalStateException ex) {
106.2036 -                }
106.2037 -                
106.2038 -                try {
106.2039 -                    running.ic.removePair (this);
106.2040 -                    fail ("This has to throw the exception");
106.2041 -                } catch (IllegalStateException ex) {
106.2042 -                }
106.2043 -                try {
106.2044 -                    running.ic.setPairs (Collections.EMPTY_SET);
106.2045 -                    fail ("This has to throw the exception as well");
106.2046 -                } catch (IllegalStateException ex) {
106.2047 -                }
106.2048 -            }
106.2049 -            
106.2050 -            return c.isAssignableFrom(getType ()); 
106.2051 -        }
106.2052 -    } // end of BrokenPair
106.2053 -    
106.2054 -    private static class Broken2Pair extends AbstractLookup.Pair {
106.2055 -        static final long serialVersionUID = 4532587018501L;
106.2056 -        public transient ThreadLocal IN;
106.2057 -        
106.2058 -        public Broken2Pair () {
106.2059 -        }
106.2060 -        
106.2061 -        private void writeObject (java.io.ObjectOutputStream oos) throws java.io.IOException {
106.2062 -        }
106.2063 -        
106.2064 -        private void readObject (java.io.ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException {
106.2065 -            IN = new ThreadLocal ();
106.2066 -        }
106.2067 -        
106.2068 -        protected boolean creatorOf(Object obj) { return this == obj; }
106.2069 -        public String getDisplayName() { return "Broken"; }
106.2070 -        public String getId() { return "broken"; }
106.2071 -        public Object getInstance() { return this; }
106.2072 -        public Class getType() { return getClass (); }
106.2073 -        protected boolean instanceOf(Class c) { 
106.2074 -            
106.2075 -            // behaviour gets broken only after deserialization
106.2076 -            if (IN != null && IN.get () == null) {
106.2077 -                try {
106.2078 -                    IN.set (this);
106.2079 -
106.2080 -                    // creation of new result has to survive as well
106.2081 -                    Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.List.class));
106.2082 -                    Collection all = myQuery.allItems ();
106.2083 -                } finally {
106.2084 -                    IN.set (null);
106.2085 -                }
106.2086 -            }
106.2087 -            
106.2088 -            return c.isAssignableFrom(getType ()); 
106.2089 -        }
106.2090 -    } // end of Broken2Pair    
106.2091 -}
   107.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupExecutorTest.java	Sat Oct 31 15:06:58 2009 +0100
   107.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.3 @@ -1,98 +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 -
  107.45 -package org.openide.util.lookup;
  107.46 -
  107.47 -import java.util.concurrent.Executor;
  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 -public class AbstractLookupExecutorTest extends AbstractLookupBaseHid 
  107.53 -implements AbstractLookupBaseHid.Impl, Executor, LookupListener {
  107.54 -    Lookup.Result<?> res;
  107.55 -    
  107.56 -    
  107.57 -    public AbstractLookupExecutorTest(java.lang.String testName) {
  107.58 -        super(testName, null);
  107.59 -    }
  107.60 -
  107.61 -    //
  107.62 -    // Impl of AbstractLookupBaseHid.Impl
  107.63 -    //
  107.64 -
  107.65 -    /** Creates the initial abstract lookup.
  107.66 -     */
  107.67 -    public Lookup createInstancesLookup (InstanceContent ic) {
  107.68 -        ic.attachExecutor(this);
  107.69 -        Lookup l = new AbstractLookup (ic, new InheritanceTree ());
  107.70 -        return l;
  107.71 -    }
  107.72 -    
  107.73 -    /** Creates an lookup for given lookup. This class just returns 
  107.74 -     * the object passed in, but subclasses can be different.
  107.75 -     * @param lookup in lookup
  107.76 -     * @return a lookup to use
  107.77 -     */
  107.78 -    public Lookup createLookup (Lookup lookup) {
  107.79 -        res = lookup.lookupResult(Object.class);
  107.80 -        res.addLookupListener(this);
  107.81 -        return lookup;
  107.82 -    }
  107.83 -
  107.84 -    public void clearCaches () {
  107.85 -    }    
  107.86 -
  107.87 -    ThreadLocal<Object> ME = new ThreadLocal<Object>();
  107.88 -    public void execute(Runnable command) {
  107.89 -        assertEquals("Not yet set", null, ME.get());
  107.90 -        ME.set(this);
  107.91 -        try {
  107.92 -            command.run();
  107.93 -        } finally {
  107.94 -            ME.set(null);
  107.95 -        }
  107.96 -    }
  107.97 -
  107.98 -    public void resultChanged(LookupEvent ev) {
  107.99 -        assertEquals("Changes delivered only from execute method", this, ME.get());
 107.100 -    }
 107.101 -}
   108.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupMemoryTest.java	Sat Oct 31 15:06:58 2009 +0100
   108.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.3 @@ -1,158 +0,0 @@
   108.4 -/*
   108.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   108.6 - *
   108.7 - * Copyright 1997-2009 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 - * Contributor(s):
  108.28 - *
  108.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  108.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  108.31 - * Microsystems, Inc. All Rights Reserved.
  108.32 - *
  108.33 - * If you wish your version of this file to be governed by only the CDDL
  108.34 - * or only the GPL Version 2, indicate your decision by adding
  108.35 - * "[Contributor] elects to include this software in this distribution
  108.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  108.37 - * single choice of license, a recipient has the option to distribute
  108.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  108.39 - * to extend the choice of license to its licensees as provided above.
  108.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  108.41 - * Version 2 license, then the option applies only if the new code is
  108.42 - * made subject to such option by the copyright holder.
  108.43 - */
  108.44 -
  108.45 -package org.openide.util.lookup;
  108.46 -
  108.47 -import java.util.*;
  108.48 -import org.netbeans.junit.*;
  108.49 -import org.netbeans.modules.openide.util.ActiveQueue;
  108.50 -import org.openide.util.Lookup;
  108.51 -
  108.52 -/** Testing memory consumption of various AbstractLookup aspects.
  108.53 - */
  108.54 -public class AbstractLookupMemoryTest extends NbTestCase {
  108.55 -    public AbstractLookupMemoryTest(java.lang.String testName) {
  108.56 -        super(testName);
  108.57 -    }
  108.58 -
  108.59 -    public static void main(java.lang.String[] args) {
  108.60 -        junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupMemoryTest.class));
  108.61 -    }
  108.62 -
  108.63 -    public void testEmptySize () {
  108.64 -        AbstractLookup instanceLookup = new AbstractLookup ();
  108.65 -        assertSize ("Empty lookup should be small", 16, instanceLookup);
  108.66 -        
  108.67 -        InstanceContent ic = new InstanceContent ();
  108.68 -        instanceLookup = new AbstractLookup (ic);
  108.69 -        assertSize ("Lookup with InstanceContent should be small as well", 16, instanceLookup);
  108.70 -    }
  108.71 -
  108.72 -    public void testPairSize () {
  108.73 -        AbstractLookup.Pair pair = new EmptyPair ();
  108.74 -        assertSize ("Pair occupies only 16 bytes", 16, pair);
  108.75 -    }
  108.76 -    
  108.77 -    public void testPairWithOnePointerSize () {
  108.78 -        AbstractLookup.Pair pair = new OneItemPair ();
  108.79 -        assertSize ("Pair occupies only 16 bytes", 16, pair);
  108.80 -    }
  108.81 -    
  108.82 -    public void testLookupWithPairs () {
  108.83 -        Lookup.Template<Object> t = new Lookup.Template<Object>(Object.class);
  108.84 -        class L implements org.openide.util.LookupListener {
  108.85 -            public int cnt;
  108.86 -            public void resultChanged (org.openide.util.LookupEvent ev) {
  108.87 -                cnt++;
  108.88 -            }
  108.89 -        }
  108.90 -        L listener = new L ();
  108.91 -        L listener2 = new L ();
  108.92 -
  108.93 -        EmptyPair[] pairs = {
  108.94 -            new EmptyPair(),
  108.95 -            new EmptyPair(),
  108.96 -            new EmptyPair(),
  108.97 -            new EmptyPair(),
  108.98 -        };
  108.99 -        Object[] ignore = {
 108.100 -            pairs[0],
 108.101 -            pairs[1],
 108.102 -            pairs[2],
 108.103 -            pairs[3],
 108.104 -            t,
 108.105 -            ActiveQueue.queue(),
 108.106 -            listener,
 108.107 -            listener2,
 108.108 -            new Integer (11) // trashhold is shared
 108.109 -        };
 108.110 -        
 108.111 -        AbstractLookup.Content c = new AbstractLookup.Content ();
 108.112 -        AbstractLookup l = new AbstractLookup (c, (Integer)ignore[ignore.length - 1]);
 108.113 -
 108.114 -        c.addPair ((EmptyPair)ignore[0]);
 108.115 -        assertSize ("Should be really small (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
 108.116 -        
 108.117 -        c.addPair ((EmptyPair)ignore[1]);
 108.118 -        assertSize ("Is bigger I guess (not counting the pair sizes)", Collections.singleton (l), 56, ignore);
 108.119 -        
 108.120 -        c.setPairs(Arrays.asList(pairs).subList(0, 3));
 108.121 -        assertSize ("Even bigger (not counting the pair sizes)", Collections.singleton (l), 64, ignore);
 108.122 -        
 108.123 -        c.setPairs(Arrays.asList(pairs).subList(0, 4));
 108.124 -        assertSize ("Now not that much(not counting the pair sizes)", Collections.singleton (l), 64, ignore);
 108.125 -        
 108.126 -        Lookup.Result res = l.lookup (t);
 108.127 -        
 108.128 -        assertSize ("After creating a result", Collections.singleton (l), 120, ignore);
 108.129 -        
 108.130 -        res.addLookupListener (listener);
 108.131 -        
 108.132 -        assertSize ("And attaching one listener", Collections.singleton (l), 120, ignore);
 108.133 -
 108.134 -        res.addLookupListener (listener2);
 108.135 -        assertSize ("Second listener makes the situation much worse", Collections.singleton (l), 200, ignore);
 108.136 -        res.removeLookupListener(listener2);
 108.137 -        assertSize ("But removing it returns us back to original size", Collections.singleton (l), 120, ignore);
 108.138 -        
 108.139 -        
 108.140 -        assertEquals ("Current for pairs are in", res.allItems ().size (), 4); // also activates the listener
 108.141 -        assertSize ("and making the listener to work", Collections.singleton (l), 120, ignore);
 108.142 -        
 108.143 -        c.removePair ((EmptyPair)ignore[0]);
 108.144 -        assertEquals ("A changes has been delivered", 1, listener.cnt);
 108.145 -    }
 108.146 -
 108.147 -    /** Simple pair with no data */
 108.148 -    private static class EmptyPair extends AbstractLookup.Pair {
 108.149 -        protected boolean creatorOf(Object obj) { return false; }
 108.150 -        public String getDisplayName() { return ""; }
 108.151 -        public String getId() { return ""; }
 108.152 -        public Object getInstance() { return null; }
 108.153 -        public Class getType() { return Object.class; }
 108.154 -        protected boolean instanceOf(Class c) { return c == getType (); }
 108.155 -    } // end of EmptyPair
 108.156 -    
 108.157 -    /** Pair with one item (like InstanceContent.Pair) */
 108.158 -    private static class OneItemPair extends EmptyPair {
 108.159 -        private Object pointer;
 108.160 -    }
 108.161 -}
   109.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   109.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.3 @@ -1,356 +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 -
  109.45 -package org.openide.util.lookup;
  109.46 -
  109.47 -import java.util.concurrent.ExecutionException;
  109.48 -
  109.49 -import java.lang.ref.WeakReference;
  109.50 -import java.util.*;
  109.51 -import java.util.concurrent.Executors;
  109.52 -import java.util.concurrent.TimeUnit;
  109.53 -import org.netbeans.junit.*;
  109.54 -import org.openide.util.Lookup;
  109.55 -import org.openide.util.lookup.AbstractLookup.Pair;
  109.56 -
  109.57 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  109.58 -public class AbstractLookupTest extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
  109.59 -    public AbstractLookupTest(java.lang.String testName) {
  109.60 -        super(testName, null);
  109.61 -    }
  109.62 -
  109.63 -    //
  109.64 -    // Impl of AbstractLookupBaseHid.Impl
  109.65 -    //
  109.66 -
  109.67 -    /** Creates the initial abstract lookup.
  109.68 -     */
  109.69 -    public Lookup createInstancesLookup (InstanceContent ic) {
  109.70 -        return new AbstractLookup (ic, new InheritanceTree ());
  109.71 -    }
  109.72 -    
  109.73 -    /** Creates an lookup for given lookup. This class just returns 
  109.74 -     * the object passed in, but subclasses can be different.
  109.75 -     * @param lookup in lookup
  109.76 -     * @return a lookup to use
  109.77 -     */
  109.78 -    public Lookup createLookup (Lookup lookup) {
  109.79 -        return lookup;
  109.80 -    }
  109.81 -
  109.82 -    public void clearCaches () {
  109.83 -    }    
  109.84 -    
  109.85 -    public static void main(java.lang.String[] args) {
  109.86 -        junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupTest.class));
  109.87 -    }
  109.88 -    
  109.89 -    static class LkpResultCanBeGargageCollectedAndClearsTheResult extends AbstractLookup {
  109.90 -        public int cleared;
  109.91 -        public int dirty;
  109.92 -
  109.93 -        synchronized @Override boolean cleanUpResult(Template t) {
  109.94 -            boolean res = super.cleanUpResult (t);
  109.95 -            if (res) {
  109.96 -                cleared++;
  109.97 -            } else {
  109.98 -                dirty++;
  109.99 -            }
 109.100 -
 109.101 -            notifyAll ();
 109.102 -
 109.103 -            return res;
 109.104 -        }
 109.105 -    }
 109.106 -    public void testResultCanBeGargageCollectedAndClearsTheResult () throws Exception {
 109.107 -        LkpResultCanBeGargageCollectedAndClearsTheResult lkp = new LkpResultCanBeGargageCollectedAndClearsTheResult ();
 109.108 -        assertSize ("24 for AbstractLookup, 8 for two ints", 32, lkp);
 109.109 -        synchronized (lkp) {
 109.110 -            Lookup.Result res = lkp.lookup (new Lookup.Template (getClass ()));
 109.111 -            res.allItems();
 109.112 -            
 109.113 -            WeakReference ref = new WeakReference (res);
 109.114 -            res = null;
 109.115 -            assertGC ("Reference can get cleared", ref);
 109.116 -         
 109.117 -            // wait till we 
 109.118 -            while (lkp.cleared == 0 && lkp.dirty == 0) {
 109.119 -                lkp.wait ();
 109.120 -            }
 109.121 -            
 109.122 -            assertEquals ("No dirty cleanups", 0, lkp.dirty);
 109.123 -            assertEquals ("One final cleanup", 1, lkp.cleared);
 109.124 -        }
 109.125 -        //assertSize ("Everything has been cleaned to original size", 32, lkp);
 109.126 -        
 109.127 -    }
 109.128 -    
 109.129 -    public void testPairCannotBeUsedInMoreThanOneLookupAtOnce () throws Exception {
 109.130 -        /** Simple pair with no data */
 109.131 -        class EmptyPair extends AbstractLookup.Pair {
 109.132 -            protected boolean creatorOf(Object obj) { return false; }
 109.133 -            public String getDisplayName() { return "Empty"; }
 109.134 -            public String getId() { return "empty"; }
 109.135 -            public Object getInstance() { return null; }
 109.136 -            public Class getType() { return Object.class; }
 109.137 -            protected boolean instanceOf(Class c) { return c == getType (); }
 109.138 -        } // end of EmptyPair
 109.139 -        
 109.140 -        AbstractLookup.Content c1 = new AbstractLookup.Content ();
 109.141 -        AbstractLookup.Content c2 = new AbstractLookup.Content ();
 109.142 -        AbstractLookup l1 = new AbstractLookup (c1);
 109.143 -        AbstractLookup l2 = new AbstractLookup (c2);
 109.144 -        
 109.145 -        EmptyPair empty = new EmptyPair ();
 109.146 -        c1.addPair (empty);
 109.147 -        Lookup.Result res = l1.lookup (new Lookup.Template (Object.class));
 109.148 -        assertEquals (
 109.149 -            "Pair is really found", empty, 
 109.150 -            res.allItems ().iterator().next ()
 109.151 -        );
 109.152 -        try {
 109.153 -            c2.addPair (empty);
 109.154 -            fail ("It should not be possible to add pair to two lookups");
 109.155 -        } catch (IllegalStateException ex) {
 109.156 -            // ok, exception is fine
 109.157 -        }
 109.158 -        assertEquals (
 109.159 -            "L2 is still empty", Collections.EMPTY_LIST, 
 109.160 -            new ArrayList (l2.lookup (new Lookup.Template (Object.class)).allItems ())
 109.161 -        );
 109.162 -    }
 109.163 -    
 109.164 -    public void testInitializationCanBeDoneFromAnotherThread () {
 109.165 -        class MyLkp extends AbstractLookup implements Runnable {
 109.166 -            private InstanceContent ic;
 109.167 -            private boolean direct;
 109.168 -            
 109.169 -            public MyLkp (boolean direct) {
 109.170 -                this (direct, new InstanceContent ());
 109.171 -            }
 109.172 -                
 109.173 -            private MyLkp (boolean direct, InstanceContent ic) {
 109.174 -                super (ic);
 109.175 -                this.direct = direct;
 109.176 -                this.ic = ic;
 109.177 -            }
 109.178 -            
 109.179 -            protected @Override void initialize() {
 109.180 -                if (direct) {
 109.181 -                    run ();
 109.182 -                } else {
 109.183 -                    try {
 109.184 -                        Executors.newSingleThreadScheduledExecutor().schedule(this, 0, TimeUnit.MICROSECONDS).get();
 109.185 -                    } catch (InterruptedException ex) {
 109.186 -                        ex.printStackTrace();
 109.187 -                    } catch (ExecutionException ex) {
 109.188 -                        ex.printStackTrace();
 109.189 -                    }
 109.190 -                }
 109.191 -            }
 109.192 -            
 109.193 -            public void run () {
 109.194 -                ic.add (this);
 109.195 -                ic.remove (this);
 109.196 -                ic.set (Collections.nCopies(10, this), null);
 109.197 -                ic.set (Collections.EMPTY_LIST, null);
 109.198 -                ic.add (AbstractLookupTest.this);
 109.199 -            }
 109.200 -        }
 109.201 -        
 109.202 -        assertEquals ("The test should be there", this, new MyLkp (true).lookup (Object.class));
 109.203 -        assertEquals ("and in async mode as well", this, new MyLkp (false).lookup (Object.class));
 109.204 -    }
 109.205 -    
 109.206 -    public void testBeforeLookupIsCalled () {
 109.207 -        class BeforeL extends AbstractLookup {
 109.208 -            public ArrayList list = new ArrayList ();
 109.209 -            public String toAdd;
 109.210 -            public InstanceContent ic;
 109.211 -            
 109.212 -            public BeforeL () {
 109.213 -                this (new InstanceContent ());
 109.214 -            }
 109.215 -            
 109.216 -            private BeforeL (InstanceContent c) {
 109.217 -                super (c);
 109.218 -                this.ic = c;
 109.219 -            }
 109.220 -        
 109.221 -            protected @Override void beforeLookup(Template t) {
 109.222 -                if (toAdd != null) {
 109.223 -                    list.add (0, new SerialPair (toAdd));
 109.224 -                    setPairs (list);
 109.225 -                } else {
 109.226 -                    ic.add (new Integer (1));
 109.227 -                }
 109.228 -            }
 109.229 -        }
 109.230 -        
 109.231 -        BeforeL lookup = new BeforeL ();
 109.232 -        
 109.233 -        lookup.toAdd = "First";
 109.234 -        assertEquals ("First if found", "First", lookup.lookup (String.class));
 109.235 -        
 109.236 -        lookup.toAdd = "2";
 109.237 -        assertEquals ("2 is not first", "2", lookup.lookup (String.class));
 109.238 -        
 109.239 -        Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
 109.240 -        for (int i = 3; i < 20; i++) {
 109.241 -            lookup.toAdd = String.valueOf (i);
 109.242 -            assertEquals (i + " items are now there", i, res.allInstances ().size ());
 109.243 -        }
 109.244 -        for (int i = 20; i < 35; i++) {
 109.245 -            lookup.toAdd = String.valueOf (i);
 109.246 -            assertEquals (i + " items are now there", i, res.allItems ().size ());
 109.247 -        }
 109.248 -        
 109.249 -        assertEquals ("Just strings are there now", 1, res.allClasses ().size ());
 109.250 -        lookup.toAdd = null; // this will add integer
 109.251 -        assertEquals ("Two classes now", 2, res.allClasses ().size ());
 109.252 -    }
 109.253 -
 109.254 -    public void testInconsistentAfterDeserIssue71744() throws Exception {
 109.255 -        InheritanceTree inhTree = new InheritanceTree();
 109.256 -
 109.257 -        AbstractLookup al = new AbstractLookup(new AbstractLookup.Content(), inhTree);
 109.258 -        {
 109.259 -
 109.260 -            Collection r = al.lookup(new Lookup.Template(Integer.class)).allInstances();
 109.261 -            assertEquals("None", 0, r.size());
 109.262 -        }
 109.263 -
 109.264 -        ICP item = new ICP(new Integer(10));
 109.265 -        al.addPair(item);
 109.266 -        al.removePair(item);
 109.267 -
 109.268 -        AbstractLookup newLookup = (AbstractLookup)reserialize(al);
 109.269 -
 109.270 -        newLookup.lookup(Number.class);
 109.271 -
 109.272 -
 109.273 -        newLookup.addPair(new ICP(new Long(20)));
 109.274 -
 109.275 -        {
 109.276 -
 109.277 -            Collection r = newLookup.lookup(new Lookup.Template(Number.class)).allInstances();
 109.278 -            assertEquals("one", 1, r.size());
 109.279 -/*
 109.280 -            Iterator it = r.iterator();
 109.281 -            assertEquals(new Integer(10), it.next());
 109.282 -            assertEquals(new Long(20), it.next());*/
 109.283 -        }
 109.284 -    }
 109.285 -
 109.286 -    public void testMatchesIssue130673() {
 109.287 -        class BrokenPairReturningNullID extends Pair<Object> {
 109.288 -            @Override
 109.289 -            protected boolean instanceOf(Class<?> c) {
 109.290 -                return false;
 109.291 -            }
 109.292 -
 109.293 -            @Override
 109.294 -            protected boolean creatorOf(Object obj) {
 109.295 -                return false;
 109.296 -            }
 109.297 -
 109.298 -            @Override
 109.299 -            public Object getInstance() {
 109.300 -                return null;
 109.301 -            }
 109.302 -
 109.303 -            @Override
 109.304 -            public Class<? extends Object> getType() {
 109.305 -                return null;
 109.306 -            }
 109.307 -
 109.308 -            @Override
 109.309 -            public String getId() {
 109.310 -                return null;
 109.311 -            }
 109.312 -
 109.313 -            @Override
 109.314 -            public String getDisplayName() {
 109.315 -                return null;
 109.316 -            }
 109.317 -        }
 109.318 -        BrokenPairReturningNullID broken = new BrokenPairReturningNullID();
 109.319 -        
 109.320 -        
 109.321 -        Lookup.Template<String> t = new Lookup.Template<String>(String.class, "ID", null);
 109.322 -        boolean not = AbstractLookup.matches(t, broken, true);
 109.323 -        assertFalse("Does not match the template, but throws no exception", not);
 109.324 -    }
 109.325 -    
 109.326 -    private static final class ICP extends AbstractLookup.Pair {
 109.327 -        private Number s;
 109.328 -
 109.329 -        public ICP (Number s) {
 109.330 -            this.s = s;
 109.331 -        }
 109.332 -
 109.333 -
 109.334 -        protected boolean instanceOf(Class c) {
 109.335 -            return c.isInstance(s);
 109.336 -        }
 109.337 -
 109.338 -        protected boolean creatorOf(Object obj) {
 109.339 -            return s == obj;
 109.340 -        }
 109.341 -
 109.342 -        public Object getInstance() {
 109.343 -            return s;
 109.344 -        }
 109.345 -
 109.346 -        public Class getType() {
 109.347 -            return s.getClass();
 109.348 -        }
 109.349 -
 109.350 -        public String getId() {
 109.351 -            return s.toString();
 109.352 -        }
 109.353 -
 109.354 -        public String getDisplayName() {
 109.355 -            return getId();
 109.356 -        }
 109.357 -
 109.358 -    }
 109.359 -}
   110.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/ExcludingLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   110.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.3 @@ -1,228 +0,0 @@
   110.4 -/*
   110.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   110.6 - *
   110.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   110.8 - *
   110.9 - * The contents of this file are subject to the terms of either the GNU
  110.10 - * General Public License Version 2 only ("GPL") or the Common
  110.11 - * Development and Distribution License("CDDL") (collectively, the
  110.12 - * "License"). You may not use this file except in compliance with the
  110.13 - * License. You can obtain a copy of the License at
  110.14 - * http://www.netbeans.org/cddl-gplv2.html
  110.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  110.16 - * specific language governing permissions and limitations under the
  110.17 - * License.  When distributing the software, include this License Header
  110.18 - * Notice in each file and include the License file at
  110.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  110.20 - * particular file as subject to the "Classpath" exception as provided
  110.21 - * by Sun in the GPL Version 2 section of the License file that
  110.22 - * accompanied this code. If applicable, add the following below the
  110.23 - * License Header, with the fields enclosed by brackets [] replaced by
  110.24 - * your own identifying information:
  110.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  110.26 - *
  110.27 - * Contributor(s):
  110.28 - *
  110.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  110.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  110.31 - * Microsystems, Inc. All Rights Reserved.
  110.32 - *
  110.33 - * If you wish your version of this file to be governed by only the CDDL
  110.34 - * or only the GPL Version 2, indicate your decision by adding
  110.35 - * "[Contributor] elects to include this software in this distribution
  110.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  110.37 - * single choice of license, a recipient has the option to distribute
  110.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  110.39 - * to extend the choice of license to its licensees as provided above.
  110.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  110.41 - * Version 2 license, then the option applies only if the new code is
  110.42 - * made subject to such option by the copyright holder.
  110.43 - */
  110.44 -
  110.45 -package org.openide.util.lookup;
  110.46 -
  110.47 -import java.util.*;
  110.48 -import org.openide.util.Lookup;
  110.49 -
  110.50 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
  110.51 - */
  110.52 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  110.53 -public class ExcludingLookupTest extends AbstractLookupBaseHid
  110.54 -implements AbstractLookupBaseHid.Impl {
  110.55 -    public ExcludingLookupTest(java.lang.String testName) {
  110.56 -        super(testName, null);
  110.57 -    }
  110.58 -
  110.59 -    public Lookup createLookup (final Lookup lookup) {
  110.60 -        return Lookups.exclude (lookup, new Class[0]);
  110.61 -    }
  110.62 -    
  110.63 -    public Lookup createInstancesLookup (InstanceContent ic) {
  110.64 -        return new AbstractLookup (ic);
  110.65 -    }
  110.66 -
  110.67 -    public void clearCaches () {
  110.68 -    }    
  110.69 -    
  110.70 -    public void testWeCanRemoveInteger () throws Exception {
  110.71 -        doBasicFilteringTest (Integer.class, Integer.class, 0);
  110.72 -    }
  110.73 -    
  110.74 -    public void testWeCanRemoveIntegersEvenByAskingForRemoveOfAllNumbers () throws Exception {
  110.75 -        doBasicFilteringTest (Number.class, Integer.class, 0);
  110.76 -    }
  110.77 -    public void testFunWithInterfaces () throws Exception {
  110.78 -        doBasicFilteringTest (java.io.Serializable.class, Integer.class, 0);
  110.79 -    }
  110.80 -    
  110.81 -    public void testWeCanGetInstanceOfSerializableEvenItIsExcludedIfWeAskForClassNotExtendingIt () throws Exception {
  110.82 -        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { java.io.Serializable.class });
  110.83 -        Lookup.Template t = new Lookup.Template (Object.class);
  110.84 -        Lookup.Result res = lookup.lookup (t);
  110.85 -        
  110.86 -        LL ll = new LL ();
  110.87 -        res.addLookupListener (ll);
  110.88 -        assertEquals ("Nothing is there", 0, res.allItems ().size ());
  110.89 -        
  110.90 -        Object inst = new Integer (3);
  110.91 -        ic.add (inst);
  110.92 -        
  110.93 -        assertEquals ("Not Filtered out", inst, lookup.lookup (Object.class));
  110.94 -        assertEquals ("Not Filtered out2", inst, lookup.lookupItem (t).getInstance ());
  110.95 -        assertEquals ("One is there - 2", 1, res.allItems ().size ());
  110.96 -        assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
  110.97 -        assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
  110.98 -        assertEquals ("Right # of events", 1, ll.getCount ());
  110.99 -        
 110.100 -        ic.remove (inst);
 110.101 -        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
 110.102 -        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
 110.103 -        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
 110.104 -        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
 110.105 -        assertEquals ("Of course it is not there", null, lookup.lookup (Object.class));
 110.106 -        assertEquals ("Right # of events", 1, ll.getCount ());
 110.107 -    }
 110.108 -    
 110.109 -    public void testIntegersQueriedThruObject () throws Exception {
 110.110 -        doBasicFilteringTest (Number.class, Object.class, 1);
 110.111 -    }
 110.112 -    
 110.113 -    private void doBasicFilteringTest (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
 110.114 -        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
 110.115 -        Lookup.Template t = new Lookup.Template (theQuery);
 110.116 -        Lookup.Result res = lookup.lookup (t);
 110.117 -        
 110.118 -        LL ll = new LL ();
 110.119 -        res.addLookupListener (ll);
 110.120 -        assertEquals ("Nothing is there", 0, res.allItems ().size ());
 110.121 -        
 110.122 -        Object inst = new Integer (3);
 110.123 -        ic.add (inst);
 110.124 -        
 110.125 -        assertEquals ("Filtered out", null, lookup.lookup (theQuery));
 110.126 -        assertEquals ("Filtered out2", null, lookup.lookupItem (t));
 110.127 -        assertEquals ("Nothing is there - 2", 0, res.allItems ().size ());
 110.128 -        assertEquals ("Nothing is there - 2a", 0, res.allInstances ().size ());
 110.129 -        assertEquals ("Nothing is there - 2b", 0, res.allClasses ().size ());
 110.130 -        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
 110.131 -        
 110.132 -        ic.remove (inst);
 110.133 -        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
 110.134 -        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
 110.135 -        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
 110.136 -        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
 110.137 -        assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
 110.138 -        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
 110.139 -        
 110.140 -    }
 110.141 -    
 110.142 -    public void testSizeOfTheLookup () throws Exception {
 110.143 -        Class exclude = String.class;
 110.144 -        
 110.145 -        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { exclude });
 110.146 -
 110.147 -        assertSize ("Should be pretty lightweight", Collections.singleton (lookup), 16, 
 110.148 -                new Object[] { this.instanceLookup, exclude });
 110.149 -    }
 110.150 -    public void testSizeOfTheLookupForMultipleFiltersIsHigher () throws Exception {
 110.151 -        Class exclude = String.class;
 110.152 -        Class exclude2 = Integer.class;
 110.153 -        Class[] arr = new Class[] { exclude, exclude2 };
 110.154 -        
 110.155 -        Lookup lookup = Lookups.exclude (this.instanceLookup, arr);
 110.156 -
 110.157 -        assertSize ("Is fatter", Collections.singleton (lookup), 40, 
 110.158 -                new Object[] { this.instanceLookup, exclude, exclude2 });
 110.159 -        assertSize ("But only due to the array", Collections.singleton (lookup), 16, 
 110.160 -                new Object[] { this.instanceLookup, exclude, exclude2, arr });
 110.161 -    }
 110.162 -    
 110.163 -    public void testFilteringOfSomething () throws Exception {
 110.164 -        doFilteringOfSomething (Runnable.class, java.io.Serializable.class, 1);
 110.165 -    }
 110.166 -    
 110.167 -    private void doFilteringOfSomething (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception {
 110.168 -        Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter });
 110.169 -        Lookup.Template t = new Lookup.Template (theQuery);
 110.170 -        Lookup.Result res = lookup.lookup (t);
 110.171 -        
 110.172 -        LL ll = new LL ();
 110.173 -        res.addLookupListener (ll);
 110.174 -        assertEquals ("Nothing is there", 0, res.allItems ().size ());
 110.175 -        
 110.176 -        Object inst = new Integer (3);
 110.177 -        ic.add (inst);
 110.178 -        
 110.179 -        assertEquals ("Accepted", inst, lookup.lookup (theQuery));
 110.180 -        assertNotNull ("Accepted too", lookup.lookupItem (t));
 110.181 -        assertEquals ("One is there - 2", 1, res.allItems ().size ());
 110.182 -        assertEquals ("One is there - 2a", 1, res.allInstances ().size ());
 110.183 -        assertEquals ("One is there - 2b", 1, res.allClasses ().size ());
 110.184 -        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
 110.185 -
 110.186 -        Object inst2 = new Thread (); // implements Runnable
 110.187 -        ic.add (inst2);
 110.188 -        assertEquals ("Accepted - 2", inst, lookup.lookup (theQuery));
 110.189 -        assertNotNull ("Accepted too -2", lookup.lookupItem (t));
 110.190 -        assertEquals ("One is there - 3", 1, res.allItems ().size ());
 110.191 -        assertEquals ("One is there - 3a", 1, res.allInstances ().size ());
 110.192 -        assertEquals ("One is there - 3b", 1, res.allClasses ().size ());
 110.193 -        assertEquals ("Right # of events", 0, ll.getCount ());
 110.194 -        
 110.195 -        
 110.196 -        ic.remove (inst);
 110.197 -        assertEquals ("Filtered out3", null, lookup.lookupItem (t));
 110.198 -        assertEquals ("Nothing is there - 3", 0, res.allItems ().size ());
 110.199 -        assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ());
 110.200 -        assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ());
 110.201 -        assertEquals ("Of course it is not there", null, lookup.lookup (theQuery));
 110.202 -        assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ());
 110.203 -    }
 110.204 -
 110.205 -    public void testTheBehaviourAsRequestedByDavidAndDescribedByJesse () throws Exception {
 110.206 -        class C implements Runnable, java.io.Serializable {
 110.207 -            public void run () {}
 110.208 -        }
 110.209 -        Object c = new C();
 110.210 -        Lookup l1 = Lookups.singleton(c);
 110.211 -        Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
 110.212 -        assertNull(l2.lookup(Runnable.class));
 110.213 -        assertEquals(c, l2.lookup(java.io.Serializable.class));
 110.214 -    }
 110.215 -    
 110.216 -    public void testTheBehaviourAsRequestedByDavidAndDescribedByJesseWithUsageOfResult () throws Exception {
 110.217 -        class C implements Runnable, java.io.Serializable {
 110.218 -            public void run () {}
 110.219 -        }
 110.220 -        Object c = new C();
 110.221 -        Lookup l1 = Lookups.singleton(c);
 110.222 -        Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class});
 110.223 -        
 110.224 -        Lookup.Result run = l2.lookup (new Lookup.Template (Runnable.class));
 110.225 -        Lookup.Result ser = l2.lookup (new Lookup.Template (java.io.Serializable.class));
 110.226 -        
 110.227 -        assertEquals ("Runnables filtered out", 0, run.allItems ().size ());
 110.228 -        assertEquals ("One serialiazble", 1, ser.allItems ().size ());
 110.229 -        assertEquals ("And it is c", c, ser.allInstances ().iterator ().next ());
 110.230 -    }
 110.231 -}
   111.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/InheritanceTreeTest.java	Sat Oct 31 15:06:58 2009 +0100
   111.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.3 @@ -1,77 +0,0 @@
   111.4 -/*
   111.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   111.6 - *
   111.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   111.8 - *
   111.9 - * The contents of this file are subject to the terms of either the GNU
  111.10 - * General Public License Version 2 only ("GPL") or the Common
  111.11 - * Development and Distribution License("CDDL") (collectively, the
  111.12 - * "License"). You may not use this file except in compliance with the
  111.13 - * License. You can obtain a copy of the License at
  111.14 - * http://www.netbeans.org/cddl-gplv2.html
  111.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  111.16 - * specific language governing permissions and limitations under the
  111.17 - * License.  When distributing the software, include this License Header
  111.18 - * Notice in each file and include the License file at
  111.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  111.20 - * particular file as subject to the "Classpath" exception as provided
  111.21 - * by Sun in the GPL Version 2 section of the License file that
  111.22 - * accompanied this code. If applicable, add the following below the
  111.23 - * License Header, with the fields enclosed by brackets [] replaced by
  111.24 - * your own identifying information:
  111.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  111.26 - *
  111.27 - * Contributor(s):
  111.28 - *
  111.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  111.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  111.31 - * Microsystems, Inc. All Rights Reserved.
  111.32 - *
  111.33 - * If you wish your version of this file to be governed by only the CDDL
  111.34 - * or only the GPL Version 2, indicate your decision by adding
  111.35 - * "[Contributor] elects to include this software in this distribution
  111.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  111.37 - * single choice of license, a recipient has the option to distribute
  111.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  111.39 - * to extend the choice of license to its licensees as provided above.
  111.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  111.41 - * Version 2 license, then the option applies only if the new code is
  111.42 - * made subject to such option by the copyright holder.
  111.43 - */
  111.44 -package org.openide.util.lookup;
  111.45 -
  111.46 -import junit.framework.TestCase;
  111.47 -import junit.framework.*;
  111.48 -import org.openide.util.Lookup;
  111.49 -import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
  111.50 -import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
  111.51 -import java.io.*;
  111.52 -import java.lang.ref.WeakReference;
  111.53 -import java.util.*;
  111.54 -
  111.55 -/**
  111.56 - *
  111.57 - * @author Jaroslav Tulach
  111.58 - */
  111.59 -public class InheritanceTreeTest extends TestCase {
  111.60 -
  111.61 -    public InheritanceTreeTest(String testName) {
  111.62 -        super(testName);
  111.63 -    }
  111.64 -
  111.65 -    protected void setUp() throws Exception {
  111.66 -    }
  111.67 -
  111.68 -    protected void tearDown() throws Exception {
  111.69 -    }
  111.70 -
  111.71 -    public void testDeserOfNode() {
  111.72 -        InheritanceTree inh = new InheritanceTree();
  111.73 -        InheritanceTree.Node n = new InheritanceTree.Node(String.class);
  111.74 -        n.markDeserialized();
  111.75 -        n.markDeserialized();
  111.76 -
  111.77 -        n.assignItem(inh, new InstanceContent.SimpleItem("Ahoj"));
  111.78 -    }
  111.79 -    
  111.80 -}
   112.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/InitializationBug44134Test.java	Sat Oct 31 15:06:58 2009 +0100
   112.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.3 @@ -1,126 +0,0 @@
   112.4 -/*
   112.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   112.6 - *
   112.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   112.8 - *
   112.9 - * The contents of this file are subject to the terms of either the GNU
  112.10 - * General Public License Version 2 only ("GPL") or the Common
  112.11 - * Development and Distribution License("CDDL") (collectively, the
  112.12 - * "License"). You may not use this file except in compliance with the
  112.13 - * License. You can obtain a copy of the License at
  112.14 - * http://www.netbeans.org/cddl-gplv2.html
  112.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  112.16 - * specific language governing permissions and limitations under the
  112.17 - * License.  When distributing the software, include this License Header
  112.18 - * Notice in each file and include the License file at
  112.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  112.20 - * particular file as subject to the "Classpath" exception as provided
  112.21 - * by Sun in the GPL Version 2 section of the License file that
  112.22 - * accompanied this code. If applicable, add the following below the
  112.23 - * License Header, with the fields enclosed by brackets [] replaced by
  112.24 - * your own identifying information:
  112.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  112.26 - *
  112.27 - * Contributor(s):
  112.28 - *
  112.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  112.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  112.31 - * Microsystems, Inc. All Rights Reserved.
  112.32 - *
  112.33 - * If you wish your version of this file to be governed by only the CDDL
  112.34 - * or only the GPL Version 2, indicate your decision by adding
  112.35 - * "[Contributor] elects to include this software in this distribution
  112.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  112.37 - * single choice of license, a recipient has the option to distribute
  112.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  112.39 - * to extend the choice of license to its licensees as provided above.
  112.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  112.41 - * Version 2 license, then the option applies only if the new code is
  112.42 - * made subject to such option by the copyright holder.
  112.43 - */
  112.44 -
  112.45 -package org.openide.util.lookup;
  112.46 -
  112.47 -import java.util.*;
  112.48 -import org.netbeans.junit.*;
  112.49 -import org.openide.util.Lookup;
  112.50 -
  112.51 -public class InitializationBug44134Test extends NbTestCase {
  112.52 -    public InitializationBug44134Test (java.lang.String testName) {
  112.53 -        super(testName);
  112.54 -    }
  112.55 -
  112.56 -    public static void main(java.lang.String[] args) {
  112.57 -        junit.textui.TestRunner.run(new NbTestSuite(InitializationBug44134Test.class));
  112.58 -    }
  112.59 -
  112.60 -    public void testThereShouldBe18Integers () throws Exception {
  112.61 -        FooManifestLookup foo = new FooManifestLookup ();
  112.62 -        
  112.63 -        Collection items = foo.lookup (new Lookup.Template (Integer.class)).allItems ();
  112.64 -        
  112.65 -        assertEquals ("18 of them", 18, items.size ());
  112.66 -        
  112.67 -        Iterator it = items.iterator ();
  112.68 -        while (it.hasNext()) {
  112.69 -            Lookup.Item t = (Lookup.Item)it.next ();
  112.70 -            assertEquals ("Is Integer", Integer.class, t.getInstance ().getClass ());
  112.71 -        }
  112.72 -    }
  112.73 -
  112.74 -    
  112.75 -    public class FooManifestLookup extends AbstractLookup {
  112.76 -        public FooManifestLookup() {
  112.77 -            super();
  112.78 -        }
  112.79 -        
  112.80 -        @Override
  112.81 -        protected void initialize() {
  112.82 -            for (int i=0; i<18; i++) {
  112.83 -                try {
  112.84 -                    String id= "__" + i;
  112.85 -                    
  112.86 -                    addPair(new FooLookupItem(new Integer(i),id));
  112.87 -                }
  112.88 -                catch (Exception e) {
  112.89 -                }
  112.90 -            }
  112.91 -        }
  112.92 -        
  112.93 -        public class FooLookupItem extends AbstractLookup.Pair {
  112.94 -            public FooLookupItem(Integer data, String id) {
  112.95 -                super();
  112.96 -                this.data=data;
  112.97 -                this.id=id;
  112.98 -            }
  112.99 -            
 112.100 -            protected boolean creatorOf(Object obj) {
 112.101 -                return obj == data;
 112.102 -            }
 112.103 -            
 112.104 -            public String getDisplayName() {
 112.105 -                return data.toString();
 112.106 -            }
 112.107 -            
 112.108 -            public Class getType () {
 112.109 -                return Integer.class;
 112.110 -            }
 112.111 -            
 112.112 -            protected boolean instanceOf (Class c) {
 112.113 -                return c.isInstance(data);
 112.114 -            }
 112.115 -            
 112.116 -            public Object getInstance() {
 112.117 -                return data;
 112.118 -            }
 112.119 -            
 112.120 -            public String getId() {
 112.121 -                return id;
 112.122 -            }
 112.123 -            
 112.124 -            private Integer data;
 112.125 -            private String id;
 112.126 -        }
 112.127 -    }
 112.128 -    
 112.129 -}
   113.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/KomrskaLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   113.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.3 @@ -1,177 +0,0 @@
   113.4 -/*
   113.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   113.6 - *
   113.7 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
   113.8 - *
   113.9 - * The contents of this file are subject to the terms of either the GNU
  113.10 - * General Public License Version 2 only ("GPL") or the Common
  113.11 - * Development and Distribution License("CDDL") (collectively, the
  113.12 - * "License"). You may not use this file except in compliance with the
  113.13 - * License. You can obtain a copy of the License at
  113.14 - * http://www.netbeans.org/cddl-gplv2.html
  113.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  113.16 - * specific language governing permissions and limitations under the
  113.17 - * License.  When distributing the software, include this License Header
  113.18 - * Notice in each file and include the License file at
  113.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  113.20 - * particular file as subject to the "Classpath" exception as provided
  113.21 - * by Sun in the GPL Version 2 section of the License file that
  113.22 - * accompanied this code. If applicable, add the following below the
  113.23 - * License Header, with the fields enclosed by brackets [] replaced by
  113.24 - * your own identifying information:
  113.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  113.26 - *
  113.27 - * If you wish your version of this file to be governed by only the CDDL
  113.28 - * or only the GPL Version 2, indicate your decision by adding
  113.29 - * "[Contributor] elects to include this software in this distribution
  113.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  113.31 - * single choice of license, a recipient has the option to distribute
  113.32 - * your version of this file under either the CDDL, the GPL Version 2 or
  113.33 - * to extend the choice of license to its licensees as provided above.
  113.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  113.35 - * Version 2 license, then the option applies only if the new code is
  113.36 - * made subject to such option by the copyright holder.
  113.37 - *
  113.38 - * Contributor(s):
  113.39 - *
  113.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  113.41 - */
  113.42 -package org.openide.util.lookup;
  113.43 -
  113.44 -import org.junit.After;
  113.45 -import org.junit.Before;
  113.46 -import org.junit.Test;
  113.47 -import org.openide.util.Lookup;
  113.48 -import org.openide.util.LookupEvent;
  113.49 -import org.openide.util.LookupListener;
  113.50 -import static org.junit.Assert.*;
  113.51 -
  113.52 -/**
  113.53 - * Test donated by Mr. Komrska. Seems to pass with 6.5.
  113.54 - * @author komrska
  113.55 - */
  113.56 -public final class KomrskaLookupTest {
  113.57 -    private TestLookupManager lookupManager=null;
  113.58 -    private StringBuffer result=null;
  113.59 -    
  113.60 -    //
  113.61 -    
  113.62 -    private void addToLookup(final TestLookupItemA object) {
  113.63 -        result.append('A');
  113.64 -        lookupManager.add(object);
  113.65 -    }
  113.66 -    private void removeFromLookup(final TestLookupItemA object) {
  113.67 -        result.append('A');
  113.68 -        lookupManager.remove(object);
  113.69 -    }
  113.70 -
  113.71 -    private void addToLookup(final TestLookupItemB object) {
  113.72 -        result.append('B');
  113.73 -        lookupManager.add(object);
  113.74 -    }
  113.75 -    private void removeFromLookup(final TestLookupItemB object) {
  113.76 -        result.append('B');
  113.77 -        lookupManager.remove(object);
  113.78 -    }
  113.79 -    
  113.80 -    public String getResult() {
  113.81 -        return result.toString();
  113.82 -    }
  113.83 -    
  113.84 -    //
  113.85 -
  113.86 -    @Before
  113.87 -    public void setUp() {
  113.88 -        lookupManager=new TestLookupManager();
  113.89 -        result=new StringBuffer();
  113.90 -    }
  113.91 -    
  113.92 -    @After
  113.93 -    public void tearDown() {
  113.94 -        lookupManager=null;
  113.95 -        result=null;
  113.96 -    }
  113.97 -    
  113.98 -    @Test
  113.99 -    public void testLookupBug() {
 113.100 -        TestLookupItemA itemA1=new TestLookupItemA();
 113.101 -        TestLookupItemB itemB1=new TestLookupItemB();
 113.102 -        //
 113.103 -        addToLookup(itemA1);
 113.104 -        addToLookup(itemB1);
 113.105 -        removeFromLookup(itemA1);
 113.106 -        removeFromLookup(itemB1);
 113.107 -        addToLookup(itemB1);
 113.108 -        removeFromLookup(itemB1);
 113.109 -        //
 113.110 -        addToLookup(itemA1);
 113.111 -        addToLookup(itemB1);
 113.112 -        removeFromLookup(itemA1);
 113.113 -        removeFromLookup(itemB1);
 113.114 -        addToLookup(itemB1);
 113.115 -        removeFromLookup(itemB1);
 113.116 -        //
 113.117 -        addToLookup(itemA1);
 113.118 -        addToLookup(itemB1);
 113.119 -        removeFromLookup(itemA1);
 113.120 -        removeFromLookup(itemB1);
 113.121 -        addToLookup(itemB1);
 113.122 -        removeFromLookup(itemB1);
 113.123 -        //
 113.124 -        assertEquals(getResult(),lookupManager.getResult());
 113.125 -    }
 113.126 -
 113.127 -    public static final class TestLookupItemA {}
 113.128 -    public static final class TestLookupItemB {}
 113.129 -    public static final class TestLookupManager {
 113.130 -        private InstanceContent instanceContent=new InstanceContent();
 113.131 -        private AbstractLookup abstractLookup=new AbstractLookup(instanceContent);
 113.132 -
 113.133 -        private Lookup.Result<TestLookupItemA> resultA=null;
 113.134 -        private Lookup.Result<TestLookupItemB> resultB=null;
 113.135 -
 113.136 -        private LookupListener listenerA=new LookupListener() {
 113.137 -            public void resultChanged(LookupEvent event) {
 113.138 -                result.append('A');
 113.139 -            }
 113.140 -        };
 113.141 -        private LookupListener listenerB=new LookupListener() {
 113.142 -            public void resultChanged(LookupEvent event) {
 113.143 -                result.append('B');
 113.144 -            }
 113.145 -        };
 113.146 -
 113.147 -        private StringBuffer result=new StringBuffer();
 113.148 -
 113.149 -        //
 113.150 -
 113.151 -        public TestLookupManager() {
 113.152 -            Lookup.Template<TestLookupItemA> templateA=
 113.153 -                new Lookup.Template<TestLookupItemA>(TestLookupItemA.class);
 113.154 -            resultA=abstractLookup.lookup(templateA);
 113.155 -            resultA.addLookupListener(listenerA);
 113.156 -            resultA.allInstances().size();
 113.157 -            //
 113.158 -            Lookup.Template<TestLookupItemB> templateB=
 113.159 -                new Lookup.Template<TestLookupItemB>(TestLookupItemB.class);
 113.160 -            resultB=abstractLookup.lookup(templateB);
 113.161 -            resultB.addLookupListener(listenerB);
 113.162 -            resultB.allInstances().size();
 113.163 -            // WORKAROUND
 113.164 -            // instanceContent.add(Boolean.TRUE);
 113.165 -        }
 113.166 -
 113.167 -        //
 113.168 -
 113.169 -        public void add(Object item) {
 113.170 -            instanceContent.add(item);
 113.171 -        }
 113.172 -        public void remove(Object item) {
 113.173 -            instanceContent.remove(item);
 113.174 -        }
 113.175 -        public String getResult() {
 113.176 -            return result.toString();
 113.177 -        }
 113.178 -    }
 113.179 -
 113.180 -}
   114.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/LookupBugTest.java	Sat Oct 31 15:06:58 2009 +0100
   114.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.3 @@ -1,79 +0,0 @@
   114.4 -package org.openide.util.lookup;
   114.5 -
   114.6 -import java.util.logging.Logger;
   114.7 -import org.junit.Before;
   114.8 -import org.junit.Test;
   114.9 -import org.openide.util.Lookup;
  114.10 -import org.openide.util.LookupEvent;
  114.11 -import org.openide.util.LookupListener;
  114.12 -import static org.junit.Assert.*;
  114.13 -
  114.14 -/**
  114.15 - * Test of a Lookup bug seen in NetBeans platforms 6.0-6.5M1.
  114.16 - * @author rlee
  114.17 - */
  114.18 -public class LookupBugTest implements LookupListener
  114.19 -{
  114.20 -    private static final int MAX_LOOPS = 1000;
  114.21 -    
  114.22 -    private AbstractLookup lookup;
  114.23 -    private InstanceContent content;
  114.24 -    private Lookup.Result<String> wordResult;
  114.25 -    private Lookup.Result<Integer> numberResult;
  114.26 -    private String word;
  114.27 -    private Integer number;
  114.28 -    private Logger LOG;
  114.29 -    
  114.30 -    private boolean fired;
  114.31 -    private int i;
  114.32 -
  114.33 -    @Before
  114.34 -    public void setUp()
  114.35 -    {
  114.36 -        LOG = Logger.getLogger("test.LookupBugTest");
  114.37 -        content = new InstanceContent();
  114.38 -        lookup = new AbstractLookup(content);
  114.39 -        wordResult = lookup.lookupResult(java.lang.String.class);
  114.40 -        wordResult.addLookupListener(this);
  114.41 -        numberResult = lookup.lookupResult(java.lang.Integer.class);
  114.42 -        numberResult.addLookupListener(this);
  114.43 -        
  114.44 -        fired = false;
  114.45 -    }
  114.46 -    
  114.47 -    @Test
  114.48 -    public void lookupTest()
  114.49 -    {
  114.50 -        for(i = 0; i < MAX_LOOPS; i++ )
  114.51 -        {
  114.52 -            word = String.valueOf(i);
  114.53 -            number = new Integer(i);
  114.54 -            content.add(word);
  114.55 -            assertTrue( "word on loop " + i, checkLookupEventFired() );
  114.56 -            content.add(number);
  114.57 -            assertTrue( "number on loop " + i, checkLookupEventFired() );
  114.58 -            content.remove(word);
  114.59 -            assertTrue( "remove word on loop " + i, checkLookupEventFired() );
  114.60 -            content.remove(number);
  114.61 -            assertTrue( "remove number on loop " + i, checkLookupEventFired() );
  114.62 -
  114.63 -            assertTrue("The lookup still needs to stay simple", AbstractLookup.isSimple(lookup));
  114.64 -        }
  114.65 -    }
  114.66 -
  114.67 -    public void resultChanged(LookupEvent ev)
  114.68 -    {
  114.69 -        fired = true;
  114.70 -    }
  114.71 -    
  114.72 -    public boolean checkLookupEventFired()
  114.73 -    {
  114.74 -        LOG.fine("  round: " + i + " word = " + word + " number = " + number);
  114.75 -        if( fired )
  114.76 -        {
  114.77 -            fired = false;
  114.78 -            return true;
  114.79 -        }
  114.80 -        else return false;
  114.81 -    }
  114.82 -}
   115.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/LookupsProxyTest.java	Sat Oct 31 15:06:58 2009 +0100
   115.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.3 @@ -1,282 +0,0 @@
   115.4 -/*
   115.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   115.6 - *
   115.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   115.8 - *
   115.9 - * The contents of this file are subject to the terms of either the GNU
  115.10 - * General Public License Version 2 only ("GPL") or the Common
  115.11 - * Development and Distribution License("CDDL") (collectively, the
  115.12 - * "License"). You may not use this file except in compliance with the
  115.13 - * License. You can obtain a copy of the License at
  115.14 - * http://www.netbeans.org/cddl-gplv2.html
  115.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  115.16 - * specific language governing permissions and limitations under the
  115.17 - * License.  When distributing the software, include this License Header
  115.18 - * Notice in each file and include the License file at
  115.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  115.20 - * particular file as subject to the "Classpath" exception as provided
  115.21 - * by Sun in the GPL Version 2 section of the License file that
  115.22 - * accompanied this code. If applicable, add the following below the
  115.23 - * License Header, with the fields enclosed by brackets [] replaced by
  115.24 - * your own identifying information:
  115.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  115.26 - *
  115.27 - * Contributor(s):
  115.28 - *
  115.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  115.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  115.31 - * Microsystems, Inc. All Rights Reserved.
  115.32 - *
  115.33 - * If you wish your version of this file to be governed by only the CDDL
  115.34 - * or only the GPL Version 2, indicate your decision by adding
  115.35 - * "[Contributor] elects to include this software in this distribution
  115.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  115.37 - * single choice of license, a recipient has the option to distribute
  115.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  115.39 - * to extend the choice of license to its licensees as provided above.
  115.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  115.41 - * Version 2 license, then the option applies only if the new code is
  115.42 - * made subject to such option by the copyright holder.
  115.43 - */
  115.44 -
  115.45 -package org.openide.util.lookup;
  115.46 -
  115.47 -import java.io.Serializable;
  115.48 -
  115.49 -import java.util.*;
  115.50 -import org.netbeans.junit.*;
  115.51 -import org.openide.util.Lookup;
  115.52 -import org.openide.util.LookupEvent;
  115.53 -import org.openide.util.LookupListener;
  115.54 -
  115.55 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
  115.56 - */
  115.57 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  115.58 -public class LookupsProxyTest extends AbstractLookupBaseHid
  115.59 -implements AbstractLookupBaseHid.Impl {
  115.60 -    public LookupsProxyTest(java.lang.String testName) {
  115.61 -        super(testName, null);
  115.62 -    }
  115.63 -
  115.64 -    public static void main(java.lang.String[] args) {
  115.65 -        junit.textui.TestRunner.run(new NbTestSuite (LookupsProxyTest.class));
  115.66 -    }
  115.67 -    
  115.68 -    /** Creates an lookup for given lookup. This class just returns 
  115.69 -     * the object passed in, but subclasses can be different.
  115.70 -     * @param lookup in lookup
  115.71 -     * @return a lookup to use
  115.72 -     */
  115.73 -    public Lookup createLookup (final Lookup lookup) {
  115.74 -        return org.openide.util.lookup.Lookups.proxy (
  115.75 -            new Lookup.Provider () {
  115.76 -                public Lookup getLookup () {
  115.77 -                    return lookup;
  115.78 -                }
  115.79 -            }
  115.80 -        );
  115.81 -    }
  115.82 -    
  115.83 -    public Lookup createInstancesLookup (InstanceContent ic) {
  115.84 -        return new AbstractLookup (ic);
  115.85 -    }
  115.86 -
  115.87 -    public void clearCaches () {
  115.88 -    }    
  115.89 -    
  115.90 -    
  115.91 -   
  115.92 -    /** Check whether setLookups method does not fire when there is no
  115.93 -     * change in the lookups.
  115.94 -     */
  115.95 -    public void testProxyListener () {
  115.96 -        Changer ch = new Changer (Lookup.EMPTY);
  115.97 -        
  115.98 -        Lookup lookup = Lookups.proxy(ch);
  115.99 -        Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class));
 115.100 -        
 115.101 -        LL ll = new LL ();
 115.102 -        res.addLookupListener (ll);
 115.103 -        Collection allRes = res.allInstances ();
 115.104 -
 115.105 -        ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
 115.106 -        lookup.lookup (Object.class); // does the refresh
 115.107 -        
 115.108 -        assertEquals("Replacing an empty by empty does not generate an event", 0, ll.getCount());
 115.109 -        
 115.110 -        InstanceContent content = new InstanceContent ();
 115.111 -        AbstractLookup del = new AbstractLookup (content);
 115.112 -        content.add (this);
 115.113 -        ch.setLookup (del);
 115.114 -        lookup.lookup (Object.class);
 115.115 -        
 115.116 -        if (ll.getCount () != 1) {
 115.117 -            fail ("Changing lookups with different content generates an event");
 115.118 -        }
 115.119 -        
 115.120 -        ch.setLookup (del);
 115.121 -        lookup.lookup (Object.class);
 115.122 -        
 115.123 -        if (ll.getCount () != 0) {
 115.124 -           fail ("Not changing the lookups does not generate any event");
 115.125 -        }
 115.126 -    }
 115.127 -
 115.128 -    
 115.129 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
 115.130 -        doListeningAndQueryingByTwoListenersSetLookups(0, 1, false);
 115.131 -    }
 115.132 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
 115.133 -        doListeningAndQueryingByTwoListenersSetLookups(1, 1, false);        
 115.134 -    }
 115.135 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
 115.136 -        doListeningAndQueryingByTwoListenersSetLookups(2, 1, false);
 115.137 -    }
 115.138 -    
 115.139 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
 115.140 -        doListeningAndQueryingByTwoListenersSetLookups(0, 2, false);
 115.141 -    }
 115.142 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
 115.143 -        doListeningAndQueryingByTwoListenersSetLookups(1, 2, false);        
 115.144 -    }
 115.145 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
 115.146 -        doListeningAndQueryingByTwoListenersSetLookups(2, 2, false);
 115.147 -    }
 115.148 -
 115.149 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookupsWithProxy() {
 115.150 -        doListeningAndQueryingByTwoListenersSetLookups(0, 1, true);
 115.151 -    }
 115.152 -    public void testListeningAndQueryingByTwoListenersClassesSetLookupsWithProxy() {
 115.153 -        doListeningAndQueryingByTwoListenersSetLookups(1, 1, true);        
 115.154 -    }
 115.155 -    public void testListeningAndQueryingByTwoListenersItemsSetLookupsWithProxy() {
 115.156 -        doListeningAndQueryingByTwoListenersSetLookups(2, 1, true);
 115.157 -    }
 115.158 -    
 115.159 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2WithProxy() {
 115.160 -        doListeningAndQueryingByTwoListenersSetLookups(0, 2, true);
 115.161 -    }
 115.162 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups2WithProxy() {
 115.163 -        doListeningAndQueryingByTwoListenersSetLookups(1, 2, true);        
 115.164 -    }
 115.165 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups2WithProxy() {
 115.166 -        doListeningAndQueryingByTwoListenersSetLookups(2, 2, true);
 115.167 -    }
 115.168 -    
 115.169 -    /* XXX: these are pretty slow, seems there is a performance problem 2^22
 115.170 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
 115.171 -        doListeningAndQueryingByTwoListenersSetLookups(0, 22);
 115.172 -    }
 115.173 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
 115.174 -        doListeningAndQueryingByTwoListenersSetLookups(1, 22);        
 115.175 -    }
 115.176 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
 115.177 -        doListeningAndQueryingByTwoListenersSetLookups(2, 22);
 115.178 -    }
 115.179 -     */
 115.180 -    
 115.181 -    private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth, boolean cacheOnTop) {
 115.182 -        Changer orig = new Changer(Lookup.EMPTY);
 115.183 -        Lookup on = Lookups.proxy(orig);
 115.184 -        Lookup first = on;
 115.185 -        
 115.186 -        while (--depth > 0) {
 115.187 -            Changer next = new Changer(on);
 115.188 -            on = Lookups.proxy(next);
 115.189 -        }
 115.190 -        
 115.191 -        
 115.192 -        final Lookup lookup = cacheOnTop ? new ProxyLookup(new Lookup[] { on }) : on;
 115.193 -        
 115.194 -        class L implements LookupListener {
 115.195 -            Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
 115.196 -            Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
 115.197 -            Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
 115.198 -            
 115.199 -            {
 115.200 -                integer.addLookupListener(this);
 115.201 -                number.addLookupListener(this);
 115.202 -                serial.addLookupListener(this);
 115.203 -            }
 115.204 -            
 115.205 -            int round;
 115.206 -            
 115.207 -            public void resultChanged(LookupEvent ev) {
 115.208 -                Collection c1 = get(type, integer);
 115.209 -                Collection c2 = get(type, number);
 115.210 -                Collection c3 = get(type, serial);
 115.211 -                
 115.212 -                assertEquals("round " + round + " c1 vs. c2", c1, c2);
 115.213 -                assertEquals("round " + round + " c1 vs. c3", c1, c3);
 115.214 -                assertEquals("round " + round + " c2 vs. c3", c2, c3);
 115.215 -                
 115.216 -                round++;
 115.217 -            }            
 115.218 -
 115.219 -            private Collection get(int type, Lookup.Result res) {
 115.220 -                Collection c;
 115.221 -                switch(type) {
 115.222 -                    case 0: c = res.allInstances(); break;
 115.223 -                    case 1: c = res.allClasses(); break;
 115.224 -                    case 2: c = res.allItems(); break;
 115.225 -                    default: c = null; fail("Type: " + type); break;
 115.226 -                }
 115.227 -                
 115.228 -                assertNotNull(c);
 115.229 -                return new ArrayList(c);
 115.230 -            }
 115.231 -        }
 115.232 -        
 115.233 -        L listener = new L();
 115.234 -        listener.resultChanged(null);
 115.235 -        ArrayList arr = new ArrayList();
 115.236 -        for(int i = 0; i < 100; i++) {
 115.237 -            arr.add(new Integer(i));
 115.238 -            
 115.239 -            orig.lookup = Lookups.fixed(arr.toArray());
 115.240 -            // do the refresh
 115.241 -            first.lookup((Class)null);
 115.242 -        }
 115.243 -        
 115.244 -        assertEquals("3x100+1 checks", 301, listener.round);
 115.245 -    }
 115.246 -    
 115.247 -    
 115.248 -    public void testRefreshWithoutAllInstances103300 () {
 115.249 -        Changer ch = new Changer (Lookup.EMPTY);
 115.250 -        
 115.251 -        Lookup lookup = Lookups.proxy(ch);
 115.252 -
 115.253 -        ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup
 115.254 -        assertNull("Nothing there", lookup.lookup (Object.class)); // does the refresh
 115.255 -        
 115.256 -        InstanceContent content = new InstanceContent ();
 115.257 -        AbstractLookup del = new AbstractLookup (content);
 115.258 -        content.add (this);
 115.259 -        ch.setLookup (del);
 115.260 -        assertEquals("Can see me", this, lookup.lookup (Object.class));
 115.261 -        
 115.262 -        ch.setLookup (del);
 115.263 -        assertEquals("Still can see me", this, lookup.lookup (Object.class));
 115.264 -
 115.265 -        assertEquals("I am visible", this, lookup.lookup(LookupsProxyTest.class));
 115.266 -    }
 115.267 -
 115.268 -
 115.269 -    private static final class Changer implements Lookup.Provider {
 115.270 -        private Lookup lookup;
 115.271 -        
 115.272 -        public Changer (Lookup lookup) {
 115.273 -            setLookup (lookup);
 115.274 -        }
 115.275 -        
 115.276 -        public void setLookup (Lookup lookup) {
 115.277 -            this.lookup = lookup;
 115.278 -        }
 115.279 -        
 115.280 -        public Lookup getLookup() {
 115.281 -            return lookup;
 115.282 -        }
 115.283 -    }
 115.284 -
 115.285 -}
   116.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   116.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.3 @@ -1,550 +0,0 @@
   116.4 -/*
   116.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   116.6 - *
   116.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   116.8 - *
   116.9 - * The contents of this file are subject to the terms of either the GNU
  116.10 - * General Public License Version 2 only ("GPL") or the Common
  116.11 - * Development and Distribution License("CDDL") (collectively, the
  116.12 - * "License"). You may not use this file except in compliance with the
  116.13 - * License. You can obtain a copy of the License at
  116.14 - * http://www.netbeans.org/cddl-gplv2.html
  116.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  116.16 - * specific language governing permissions and limitations under the
  116.17 - * License.  When distributing the software, include this License Header
  116.18 - * Notice in each file and include the License file at
  116.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  116.20 - * particular file as subject to the "Classpath" exception as provided
  116.21 - * by Sun in the GPL Version 2 section of the License file that
  116.22 - * accompanied this code. If applicable, add the following below the
  116.23 - * License Header, with the fields enclosed by brackets [] replaced by
  116.24 - * your own identifying information:
  116.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  116.26 - *
  116.27 - * Contributor(s):
  116.28 - *
  116.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  116.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  116.31 - * Microsystems, Inc. All Rights Reserved.
  116.32 - *
  116.33 - * If you wish your version of this file to be governed by only the CDDL
  116.34 - * or only the GPL Version 2, indicate your decision by adding
  116.35 - * "[Contributor] elects to include this software in this distribution
  116.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  116.37 - * single choice of license, a recipient has the option to distribute
  116.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  116.39 - * to extend the choice of license to its licensees as provided above.
  116.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  116.41 - * Version 2 license, then the option applies only if the new code is
  116.42 - * made subject to such option by the copyright holder.
  116.43 - */
  116.44 -
  116.45 -package org.openide.util.lookup;
  116.46 -
  116.47 -import java.io.ByteArrayInputStream;
  116.48 -import java.io.File;
  116.49 -import java.io.FileOutputStream;
  116.50 -import java.io.IOException;
  116.51 -import java.io.InputStream;
  116.52 -import java.io.InputStreamReader;
  116.53 -import java.lang.ref.Reference;
  116.54 -import java.lang.ref.WeakReference;
  116.55 -import java.net.URL;
  116.56 -import java.net.URLClassLoader;
  116.57 -import java.net.URLConnection;
  116.58 -import java.net.URLStreamHandler;
  116.59 -import java.util.ArrayList;
  116.60 -import java.util.Collection;
  116.61 -import java.util.Collections;
  116.62 -import java.util.Comparator;
  116.63 -import java.util.Enumeration;
  116.64 -import java.util.HashSet;
  116.65 -import java.util.Iterator;
  116.66 -import java.util.List;
  116.67 -import java.util.Map;
  116.68 -import java.util.Set;
  116.69 -import java.util.TreeSet;
  116.70 -import java.util.WeakHashMap;
  116.71 -import java.util.concurrent.atomic.AtomicBoolean;
  116.72 -import java.util.jar.JarEntry;
  116.73 -import java.util.jar.JarOutputStream;
  116.74 -import java.util.logging.Level;
  116.75 -import java.util.logging.Logger;
  116.76 -import java.util.regex.Matcher;
  116.77 -import java.util.regex.Pattern;
  116.78 -import org.bar.Comparator2;
  116.79 -import org.netbeans.junit.MockServices;
  116.80 -import org.netbeans.junit.NbTestCase;
  116.81 -import org.openide.util.Enumerations;
  116.82 -import org.openide.util.Exceptions;
  116.83 -import org.openide.util.Lookup;
  116.84 -import org.openide.util.LookupEvent;
  116.85 -import org.openide.util.LookupListener;
  116.86 -import org.openide.util.test.MockLookup;
  116.87 -
  116.88 -/** Test finding services from manifest.
  116.89 - * @author Jesse Glick
  116.90 - */
  116.91 -public class MetaInfServicesLookupTest extends NbTestCase {
  116.92 -    private Logger LOG;
  116.93 -    private Map<ClassLoader,Lookup> lookups = new WeakHashMap<ClassLoader,Lookup>();
  116.94 -    
  116.95 -    public MetaInfServicesLookupTest(String name) {
  116.96 -        super(name);
  116.97 -        LOG = Logger.getLogger("Test." + name);
  116.98 -    }
  116.99 -
 116.100 -    protected String prefix() {
 116.101 -        return "META-INF/services/";
 116.102 -    }
 116.103 -    
 116.104 -    protected Lookup createLookup(ClassLoader c) {
 116.105 -        return Lookups.metaInfServices(c);
 116.106 -    }
 116.107 -    
 116.108 -    @Override
 116.109 -    protected Level logLevel() {
 116.110 -        return Level.INFO;
 116.111 -    }
 116.112 -
 116.113 -    private Lookup getTestedLookup(ClassLoader c) {
 116.114 -        MockServices.setServices();
 116.115 -        Lookup l = lookups.get(c);
 116.116 -        if (l == null) {
 116.117 -            l = createLookup(c);
 116.118 -            lookups.put(c, l);
 116.119 -        }
 116.120 -        return l;
 116.121 -    }
 116.122 -
 116.123 -    private URL findJar(String n) throws IOException {
 116.124 -        LOG.info("Looking for " + n);
 116.125 -        File jarDir = new File(getWorkDir(), "jars");
 116.126 -        jarDir.mkdirs();
 116.127 -        File jar = new File(jarDir, n);
 116.128 -        if (jar.exists()) {
 116.129 -            return jar.toURI().toURL();
 116.130 -        }
 116.131 -        
 116.132 -        LOG.info("generating " + jar);
 116.133 -        
 116.134 -        URL data = MetaInfServicesLookupTest.class.getResource(n.replaceAll("\\.jar", "\\.txt"));
 116.135 -        assertNotNull("Data found", data);
 116.136 -        StringBuffer sb = new StringBuffer();
 116.137 -        InputStreamReader r = new InputStreamReader(data.openStream());
 116.138 -        for(;;) {
 116.139 -            int ch = r.read();
 116.140 -            if (ch == -1) {
 116.141 -                break;
 116.142 -            }
 116.143 -            sb.append((char)ch);
 116.144 -        }
 116.145 -        
 116.146 -        JarOutputStream os = new JarOutputStream(new FileOutputStream(jar));
 116.147 -        
 116.148 -        Pattern p = Pattern.compile(":([^:]+):([^:]*)", Pattern.MULTILINE | Pattern.DOTALL);
 116.149 -        Matcher m = p.matcher(sb);
 116.150 -        Pattern foobar = Pattern.compile("^(org\\.(foo|bar)\\..*)$", Pattern.MULTILINE);
 116.151 -        Set<String> names = new TreeSet<String>();
 116.152 -        while (m.find()) {
 116.153 -            assert m.groupCount() == 2;
 116.154 -            String entryName = prefix() + m.group(1);
 116.155 -            LOG.info("putting there entry: " + entryName);
 116.156 -            os.putNextEntry(new JarEntry(entryName));
 116.157 -            os.write(m.group(2).getBytes());
 116.158 -            os.closeEntry();
 116.159 -            
 116.160 -            Matcher fb = foobar.matcher(m.group(2));
 116.161 -            while (fb.find()) {
 116.162 -                String clazz = fb.group(1).replace('.', '/') + ".class";
 116.163 -                LOG.info("will copy " + clazz);
 116.164 -                names.add(clazz);
 116.165 -            }
 116.166 -        }
 116.167 -        
 116.168 -        for (String copy : names) {
 116.169 -            os.putNextEntry(new JarEntry(copy));
 116.170 -            LOG.info("copying " + copy);
 116.171 -            InputStream from = MetaInfServicesLookupTest.class.getResourceAsStream("/" + copy);
 116.172 -            assertNotNull(copy, from);
 116.173 -            for (;;) {
 116.174 -                int ch = from.read();
 116.175 -                if (ch == -1) {
 116.176 -                    break;
 116.177 -                }
 116.178 -                os.write(ch);
 116.179 -            }
 116.180 -            from.close();
 116.181 -            os.closeEntry();
 116.182 -        }
 116.183 -        os.close();
 116.184 -        LOG.info("done " + jar);
 116.185 -        return jar.toURI().toURL();
 116.186 -    }
 116.187 -
 116.188 -    ClassLoader c1, c2, c2a, c3, c4;
 116.189 -
 116.190 -    @Override
 116.191 -    protected void setUp() throws Exception {
 116.192 -        clearWorkDir();
 116.193 -        ClassLoader app = getClass().getClassLoader().getParent();
 116.194 -        ClassLoader c0 = app;
 116.195 -        
 116.196 -        c1 = new URLClassLoader(new URL[] {
 116.197 -            findJar("services-jar-1.jar"),
 116.198 -        }, c0);
 116.199 -        c2 = new URLClassLoader(new URL[] {
 116.200 -            findJar("services-jar-2.jar"),
 116.201 -        }, c1);
 116.202 -        c2a = new URLClassLoader(new URL[] {
 116.203 -            findJar("services-jar-2.jar"),
 116.204 -        }, c1);
 116.205 -        c3 = new URLClassLoader(new URL[] { findJar("services-jar-2.jar") },
 116.206 -            c0
 116.207 -        );
 116.208 -        c4 = new URLClassLoader(new URL[] {
 116.209 -            findJar("services-jar-1.jar"),
 116.210 -            findJar("services-jar-2.jar"),
 116.211 -        }, c0);
 116.212 -    }
 116.213 -
 116.214 -    @Override
 116.215 -    protected void tearDown() throws Exception {
 116.216 -        Set<Reference<Lookup>> weak = new HashSet<Reference<Lookup>>();
 116.217 -        for (Lookup l : lookups.values()) {
 116.218 -            weak.add(new WeakReference<Lookup>(l));
 116.219 -        }
 116.220 -        
 116.221 -        lookups = null;
 116.222 -        
 116.223 -        for(Reference<Lookup> ref : weak) {
 116.224 -            assertGC("Lookup can disappear", ref);
 116.225 -        }
 116.226 -    }
 116.227 -
 116.228 -    public void testBasicUsage() throws Exception {
 116.229 -        Lookup l = getTestedLookup(c2);
 116.230 -        Class<?> xface = c1.loadClass("org.foo.Interface");
 116.231 -        List<?> results = new ArrayList<Object>(l.lookupAll(xface));
 116.232 -        assertEquals("Two items in result: " + results, 2, results.size());
 116.233 -        // Note that they have to be in order:
 116.234 -        assertEquals("org.foo.impl.Implementation1", results.get(0).getClass().getName());
 116.235 -        assertEquals("org.bar.Implementation2", results.get(1).getClass().getName());
 116.236 -        // Make sure it does not gratuitously replace items:
 116.237 -        List<?> results2 = new ArrayList<Object>(l.lookupAll(xface));
 116.238 -        assertEquals(results, results2);
 116.239 -    }
 116.240 -
 116.241 -    public void testLoaderSkew() throws Exception {
 116.242 -        Class<?> xface1 = c1.loadClass("org.foo.Interface");
 116.243 -        Lookup l3 = getTestedLookup(c3);
 116.244 -        // If we cannot load Interface, there should be no impls of course... quietly!
 116.245 -        assertEquals(Collections.emptyList(),
 116.246 -                new ArrayList<Object>(l3.lookupAll(xface1)));
 116.247 -        Lookup l4 = getTestedLookup(c4);
 116.248 -        // If we can load Interface but it is the wrong one, ignore it.
 116.249 -        assertEquals(Collections.emptyList(),
 116.250 -                new ArrayList<Object>(l4.lookupAll(xface1)));
 116.251 -        // Make sure l4 is really OK - it can load from its own JARs.
 116.252 -        Class<?> xface4 = c4.loadClass("org.foo.Interface");
 116.253 -        assertEquals(2, l4.lookupAll(xface4).size());
 116.254 -    }
 116.255 -
 116.256 -    public void testStability() throws Exception {
 116.257 -        Lookup l = getTestedLookup(c2);
 116.258 -        Class<?> xface = c1.loadClass("org.foo.Interface");
 116.259 -        Object first = l.lookup(xface);
 116.260 -        assertEquals(first, l.lookupAll(xface).iterator().next());
 116.261 -        l = getTestedLookup(c2a);
 116.262 -        Object second = l.lookup(xface);
 116.263 -        assertEquals(first, second);
 116.264 -    }
 116.265 -
 116.266 -    public void testMaskingOfResources() throws Exception {
 116.267 -        Lookup l1 = getTestedLookup(c1);
 116.268 -        Lookup l2 = getTestedLookup(c2);
 116.269 -        Lookup l4 = getTestedLookup(c4);
 116.270 -
 116.271 -        assertNotNull("services1.jar defines a class that implements runnable", l1.lookup(Runnable.class));
 116.272 -        assertNull("services2.jar does not defines a class that implements runnable", l2.lookup(Runnable.class));
 116.273 -        assertNull("services1.jar defines Runnable, but services2.jar masks it out", l4.lookup(Runnable.class));
 116.274 -    }
 116.275 -
 116.276 -    public void testOrdering() throws Exception {
 116.277 -        Lookup l = getTestedLookup(c1);
 116.278 -        Class<?> xface = c1.loadClass("java.util.Comparator");
 116.279 -        List<?> results = new ArrayList<Object>(l.lookupAll(xface));
 116.280 -        assertEquals(1, results.size());
 116.281 -
 116.282 -        l = getTestedLookup(c2);
 116.283 -        xface = c2.loadClass("java.util.Comparator");
 116.284 -        results = new ArrayList<Object>(l.lookupAll(xface));
 116.285 -        assertEquals(2, results.size());
 116.286 -        // Test order:
 116.287 -        assertEquals("org.bar.Comparator2", results.get(0).getClass().getName());
 116.288 -        assertEquals("org.foo.impl.Comparator1", results.get(1).getClass().getName());
 116.289 -
 116.290 -        // test that items without position are always at the end
 116.291 -        l = getTestedLookup(c2);
 116.292 -        xface = c2.loadClass("java.util.Iterator");
 116.293 -        results = new ArrayList<Object>(l.lookupAll(xface));
 116.294 -        assertEquals(2, results.size());
 116.295 -        // Test order:
 116.296 -        assertEquals("org.bar.Iterator2", results.get(0).getClass().getName());
 116.297 -        assertEquals("org.foo.impl.Iterator1", results.get(1).getClass().getName());
 116.298 -    }
 116.299 -
 116.300 -    public void testNoCallToGetResourceForObjectIssue65124() throws Exception {
 116.301 -        class Loader extends ClassLoader {
 116.302 -            private int counter;
 116.303 -
 116.304 -            @Override
 116.305 -            protected URL findResource(String name) {
 116.306 -                if (name.equals(prefix() + "java.lang.Object")) {
 116.307 -                    counter++;
 116.308 -                }
 116.309 -
 116.310 -                URL retValue;
 116.311 -
 116.312 -                retValue = super.findResource(name);
 116.313 -                return retValue;
 116.314 -            }
 116.315 -
 116.316 -            @Override
 116.317 -            protected Enumeration<URL> findResources(String name) throws IOException {
 116.318 -                if (name.equals(prefix() + "java.lang.Object")) {
 116.319 -                    counter++;
 116.320 -                }
 116.321 -                return super.findResources(name);
 116.322 -            }
 116.323 -        }
 116.324 -        Loader loader = new Loader();
 116.325 -        Lookup l = getTestedLookup(loader);
 116.326 -
 116.327 -        Object no = l.lookup(String.class);
 116.328 -        assertNull("Not found of course", no);
 116.329 -        assertEquals("No lookup of Object", 0, loader.counter);
 116.330 -    }
 116.331 -
 116.332 -    public void testCanGarbageCollectClasses() throws Exception {
 116.333 -        class Loader extends ClassLoader {
 116.334 -            public Loader() {
 116.335 -                super(Loader.class.getClassLoader().getParent());
 116.336 -            }
 116.337 -
 116.338 -            @Override
 116.339 -            protected URL findResource(String name) {
 116.340 -                if (name.equals(prefix() + "java.lang.Runnable")) {
 116.341 -                    return Loader.class.getResource("MetaInfServicesLookupTestRunnable.txt");
 116.342 -                }
 116.343 -
 116.344 -                URL retValue;
 116.345 -
 116.346 -                retValue = super.findResource(name);
 116.347 -                return retValue;
 116.348 -            }
 116.349 -
 116.350 -            @Override
 116.351 -            protected Class<?> findClass(String name) throws ClassNotFoundException {
 116.352 -                if (name.equals("org.openide.util.lookup.MetaInfServicesLookupTestRunnable")) {
 116.353 -                    try {
 116.354 -                        InputStream is = getClass().getResourceAsStream("MetaInfServicesLookupTestRunnable.class");
 116.355 -                        byte[] arr = new byte[is.available()];
 116.356 -                        int read = is.read(arr);
 116.357 -                        assertEquals("Fully read", arr.length, read);
 116.358 -                        return defineClass(name, arr, 0, arr.length);
 116.359 -                    } catch (IOException ex) {
 116.360 -                        throw new ClassNotFoundException("Cannot load", ex);
 116.361 -                    }
 116.362 -                }
 116.363 -                throw new ClassNotFoundException();
 116.364 -            }
 116.365 -
 116.366 -
 116.367 -
 116.368 -            @Override
 116.369 -            protected Enumeration<URL> findResources(String name) throws IOException {
 116.370 -                if (name.equals(prefix() + "java.lang.Runnable")) {
 116.371 -                    return Collections.enumeration(Collections.singleton(findResource(name)));
 116.372 -                }
 116.373 -                return super.findResources(name);
 116.374 -            }
 116.375 -        }
 116.376 -        Loader loader = new Loader();
 116.377 -        Lookup l = getTestedLookup(loader);
 116.378 -
 116.379 -
 116.380 -        Object no = l.lookup(Runnable.class);
 116.381 -        assertNotNull("Found of course", no);
 116.382 -        assertEquals("The right name", "MetaInfServicesLookupTestRunnable", no.getClass().getSimpleName());
 116.383 -        if (no.getClass().getClassLoader() != loader) {
 116.384 -            fail("Wrong classloader: " + no.getClass().getClassLoader());
 116.385 -        }
 116.386 -
 116.387 -        WeakReference<Object> ref = new WeakReference<Object>(no.getClass());
 116.388 -        loader = null;
 116.389 -        no = null;
 116.390 -        l = null;
 116.391 -        lookups.clear();
 116.392 -        MockLookup.setInstances();
 116.393 -        Thread.currentThread().setContextClassLoader(null);
 116.394 -        assertGC("Class can be garbage collected", ref);
 116.395 -    }
 116.396 -
 116.397 -    public void testSuperTypes() throws Exception {
 116.398 -        doTestSuperTypes(createLookup(c2));
 116.399 -        doTestSuperTypes(new ProxyLookup(createLookup(c2)));
 116.400 -    }
 116.401 -    private void doTestSuperTypes(Lookup l) throws Exception {
 116.402 -        final Class<?> xface = c1.loadClass("org.foo.Interface");
 116.403 -        final Lookup.Result<Object> res = l.lookupResult(Object.class);
 116.404 -        assertEquals("Nothing yet", 0, res.allInstances().size());
 116.405 -        final AtomicBoolean event = new AtomicBoolean();
 116.406 -        final Thread here = Thread.currentThread();
 116.407 -        res.addLookupListener(new LookupListener() {
 116.408 -            public void resultChanged(LookupEvent ev) {
 116.409 -                if (Thread.currentThread() == here) {
 116.410 -                    event.set(true);
 116.411 -                }
 116.412 -            }
 116.413 -        });
 116.414 -        assertNotNull("Interface found", l.lookup(xface));
 116.415 -        assertFalse(event.get());
 116.416 -        class W implements Runnable {
 116.417 -            boolean ok;
 116.418 -            public synchronized void run() {
 116.419 -                ok = true;
 116.420 -                notifyAll();
 116.421 -            }
 116.422 -
 116.423 -            public synchronized void await() throws Exception {
 116.424 -                while (!ok) {
 116.425 -                    wait();
 116.426 -                }
 116.427 -            }
 116.428 -        }
 116.429 -        W w = new W();
 116.430 -        MetaInfServicesLookup.RP.execute(w);
 116.431 -        w.await();
 116.432 -        assertEquals("Now two", 2, res.allInstances().size());
 116.433 -    }
 116.434 -    
 116.435 -    public void testWrongOrderAsInIssue100320() throws Exception {
 116.436 -        ClassLoader app = getClass().getClassLoader().getParent();
 116.437 -        ClassLoader c0 = app;
 116.438 -        ClassLoader ctmp = new URLClassLoader(new URL[] {
 116.439 -            findJar("problem100320.jar"),
 116.440 -        }, c0);
 116.441 -        Lookup lookup = Lookups.metaInfServices(ctmp, prefix());
 116.442 -
 116.443 -        Collection<?> colAWT = lookup.lookupAll(IOException.class);
 116.444 -        assertEquals("There is enough objects to switch to InheritanceTree", 12, colAWT.size());
 116.445 -        
 116.446 -        
 116.447 -        List<?> col1 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
 116.448 -        assertEquals("Two", 2, col1.size());
 116.449 -        Collection<?> col2 = lookup.lookupAll(ctmp.loadClass(Comparator2.class.getName()));
 116.450 -        assertEquals("One", 1, col2.size());
 116.451 -        List<?> col3 = new ArrayList<Object>(lookup.lookupAll(Comparator.class));
 116.452 -        assertEquals("Two2", 2, col3.size());
 116.453 -        
 116.454 -        Iterator<?> it1 = col1.iterator();
 116.455 -        Iterator<?> it3 = col3.iterator();
 116.456 -        if (
 116.457 -            it1.next() != it3.next() || 
 116.458 -            it1.next() != it3.next() 
 116.459 -        ) {
 116.460 -            fail("Collections are different:\nFirst: " + col1 + "\nLast:  " + col3);
 116.461 -        }
 116.462 -    }
 116.463 -
 116.464 -    public void testContentionWhenLoadingMetainfServices() throws Exception {
 116.465 -        class My extends ClassLoader implements Runnable {
 116.466 -            Lookup query;
 116.467 -            Integer value;
 116.468 -
 116.469 -            public void run() {
 116.470 -                value = query.lookup(Integer.class);
 116.471 -            }
 116.472 -
 116.473 -
 116.474 -            @Override
 116.475 -            protected URL findResource(String name) {
 116.476 -                waitForTask(name);
 116.477 -                return super.findResource(name);
 116.478 -            }
 116.479 -
 116.480 -            @Override
 116.481 -            protected Enumeration<URL> findResources(String name) throws IOException {
 116.482 -                waitForTask(name);
 116.483 -                return super.findResources(name);
 116.484 -            }
 116.485 -
 116.486 -            private synchronized void waitForTask(String name) {
 116.487 -                if (name.startsWith(prefix()) && Thread.currentThread().getName().contains("block")) {
 116.488 -                    try {
 116.489 -                        wait();
 116.490 -                    } catch (InterruptedException ex) {
 116.491 -                        Exceptions.printStackTrace(ex);
 116.492 -                    }
 116.493 -                }
 116.494 -            }
 116.495 -        }
 116.496 -
 116.497 -        My loader = new My();
 116.498 -        loader.query = createLookup(loader);
 116.499 -        Thread t = new Thread(loader, "block when querying");
 116.500 -        t.start();
 116.501 -        t.join(1000);
 116.502 -
 116.503 -        // this blocks waiting for the waitForTask to finish
 116.504 -        // right now
 116.505 -        Float f = loader.query.lookup(Float.class);
 116.506 -        assertNull("Nothing found", f);
 116.507 -
 116.508 -        synchronized (loader) {
 116.509 -            loader.notifyAll();
 116.510 -        }
 116.511 -        t.join();
 116.512 -
 116.513 -        assertNull("Nothing found", loader.value);
 116.514 -    }
 116.515 -
 116.516 -    public void testInitializerRobustness() throws Exception { // #174055
 116.517 -        check(Broken1.class.getName());
 116.518 -        check(Broken2.class.getName());
 116.519 -    }
 116.520 -    private void check(final String n) {
 116.521 -        assertNull(Lookups.metaInfServices(new ClassLoader() {
 116.522 -            protected @Override Enumeration<URL> findResources(String name) throws IOException {
 116.523 -                if (name.equals("META-INF/services/java.lang.Object")) {
 116.524 -                    return Enumerations.singleton(new URL(null, "dummy:stuff", new URLStreamHandler() {
 116.525 -                        protected URLConnection openConnection(URL u) throws IOException {
 116.526 -                            return new URLConnection(u) {
 116.527 -                                public void connect() throws IOException {}
 116.528 -                                public @Override InputStream getInputStream() throws IOException {
 116.529 -                                    return new ByteArrayInputStream(n.getBytes("UTF-8"));
 116.530 -                                }
 116.531 -                            };
 116.532 -                        }
 116.533 -                    }));
 116.534 -                } else {
 116.535 -                    return Enumerations.empty();
 116.536 -                }
 116.537 -            }
 116.538 -        }).lookup(Object.class));
 116.539 -    }
 116.540 -    public static class Broken1 {
 116.541 -        public Broken1() {
 116.542 -            throw new NullPointerException("broken1");
 116.543 -        }
 116.544 -    }
 116.545 -    public static class Broken2 {
 116.546 -        static {
 116.547 -            if (true) { // otherwise javac complains
 116.548 -                throw new NullPointerException("broken2");
 116.549 -            }
 116.550 -        }
 116.551 -    }
 116.552 -
 116.553 -}
   117.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.java	Sat Oct 31 15:06:58 2009 +0100
   117.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.3 @@ -1,50 +0,0 @@
   117.4 -/*
   117.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   117.6 - *
   117.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   117.8 - *
   117.9 - * The contents of this file are subject to the terms of either the GNU
  117.10 - * General Public License Version 2 only ("GPL") or the Common
  117.11 - * Development and Distribution License("CDDL") (collectively, the
  117.12 - * "License"). You may not use this file except in compliance with the
  117.13 - * License. You can obtain a copy of the License at
  117.14 - * http://www.netbeans.org/cddl-gplv2.html
  117.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  117.16 - * specific language governing permissions and limitations under the
  117.17 - * License.  When distributing the software, include this License Header
  117.18 - * Notice in each file and include the License file at
  117.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  117.20 - * particular file as subject to the "Classpath" exception as provided
  117.21 - * by Sun in the GPL Version 2 section of the License file that
  117.22 - * accompanied this code. If applicable, add the following below the
  117.23 - * License Header, with the fields enclosed by brackets [] replaced by
  117.24 - * your own identifying information:
  117.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  117.26 - *
  117.27 - * Contributor(s):
  117.28 - *
  117.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  117.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  117.31 - * Microsystems, Inc. All Rights Reserved.
  117.32 - *
  117.33 - * If you wish your version of this file to be governed by only the CDDL
  117.34 - * or only the GPL Version 2, indicate your decision by adding
  117.35 - * "[Contributor] elects to include this software in this distribution
  117.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  117.37 - * single choice of license, a recipient has the option to distribute
  117.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  117.39 - * to extend the choice of license to its licensees as provided above.
  117.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  117.41 - * Version 2 license, then the option applies only if the new code is
  117.42 - * made subject to such option by the copyright holder.
  117.43 - */
  117.44 -
  117.45 -package org.openide.util.lookup;
  117.46 -
  117.47 -
  117.48 -/**
  117.49 - */
  117.50 -public final class MetaInfServicesLookupTestRunnable implements Runnable {
  117.51 -    public void run() {
  117.52 -    }
  117.53 -}
   118.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.txt	Sat Oct 31 15:06:58 2009 +0100
   118.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.3 @@ -1,1 +0,0 @@
   118.4 -org.openide.util.lookup.MetaInfServicesLookupTestRunnable
   119.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/NamedServicesLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   119.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.3 @@ -1,85 +0,0 @@
   119.4 -/*
   119.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   119.6 - *
   119.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   119.8 - *
   119.9 - * The contents of this file are subject to the terms of either the GNU
  119.10 - * General Public License Version 2 only ("GPL") or the Common
  119.11 - * Development and Distribution License("CDDL") (collectively, the
  119.12 - * "License"). You may not use this file except in compliance with the
  119.13 - * License. You can obtain a copy of the License at
  119.14 - * http://www.netbeans.org/cddl-gplv2.html
  119.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  119.16 - * specific language governing permissions and limitations under the
  119.17 - * License.  When distributing the software, include this License Header
  119.18 - * Notice in each file and include the License file at
  119.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  119.20 - * particular file as subject to the "Classpath" exception as provided
  119.21 - * by Sun in the GPL Version 2 section of the License file that
  119.22 - * accompanied this code. If applicable, add the following below the
  119.23 - * License Header, with the fields enclosed by brackets [] replaced by
  119.24 - * your own identifying information:
  119.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  119.26 - *
  119.27 - * Contributor(s):
  119.28 - *
  119.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  119.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  119.31 - * Microsystems, Inc. All Rights Reserved.
  119.32 - *
  119.33 - * If you wish your version of this file to be governed by only the CDDL
  119.34 - * or only the GPL Version 2, indicate your decision by adding
  119.35 - * "[Contributor] elects to include this software in this distribution
  119.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  119.37 - * single choice of license, a recipient has the option to distribute
  119.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  119.39 - * to extend the choice of license to its licensees as provided above.
  119.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  119.41 - * Version 2 license, then the option applies only if the new code is
  119.42 - * made subject to such option by the copyright holder.
  119.43 - */
  119.44 -
  119.45 -package org.openide.util.lookup;
  119.46 -
  119.47 -import org.openide.util.Lookup;
  119.48 -import org.openide.util.test.MockLookup;
  119.49 -
  119.50 -
  119.51 -/** Test finding services from manifest.
  119.52 - * @author Jaroslav Tulach
  119.53 - */
  119.54 -public class NamedServicesLookupTest extends MetaInfServicesLookupTest {
  119.55 -    static {
  119.56 -        MockLookup.init();
  119.57 -    }
  119.58 -    public NamedServicesLookupTest(String name) {
  119.59 -        super(name);
  119.60 -    }
  119.61 -
  119.62 -    @Override
  119.63 -    protected String prefix() {
  119.64 -        return "META-INF/namedservices/sub/path/";
  119.65 -    }
  119.66 -    
  119.67 -    @Override
  119.68 -    protected Lookup createLookup(ClassLoader c) {
  119.69 -        MockLookup.setInstances(c);
  119.70 -        Thread.currentThread().setContextClassLoader(c);
  119.71 -        Lookup l = Lookups.forPath("sub/path");
  119.72 -        return l;
  119.73 -    }
  119.74 -    
  119.75 -    //
  119.76 -    // this is not much inheriting test, as we mask most of the tested methods
  119.77 -    // anyway, but the infrastructure to generate the JAR files is useful
  119.78 -    //
  119.79 -    
  119.80 -    public @Override void testLoaderSkew() {}
  119.81 -    public @Override void testStability() throws Exception {}
  119.82 -    public @Override void testMaskingOfResources() throws Exception {}
  119.83 -    public @Override void testOrdering() throws Exception {}
  119.84 -    public @Override void testNoCallToGetResourceForObjectIssue65124() throws Exception {}
  119.85 -    public @Override void testSuperTypes() throws Exception {}
  119.86 -    public @Override void testWrongOrderAsInIssue100320() throws Exception {}
  119.87 -    
  119.88 -}
   120.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/PathInLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   120.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.3 @@ -1,112 +0,0 @@
   120.4 -/*
   120.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   120.6 - *
   120.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   120.8 - *
   120.9 - * The contents of this file are subject to the terms of either the GNU
  120.10 - * General Public License Version 2 only ("GPL") or the Common
  120.11 - * Development and Distribution License("CDDL") (collectively, the
  120.12 - * "License"). You may not use this file except in compliance with the
  120.13 - * License. You can obtain a copy of the License at
  120.14 - * http://www.netbeans.org/cddl-gplv2.html
  120.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  120.16 - * specific language governing permissions and limitations under the
  120.17 - * License.  When distributing the software, include this License Header
  120.18 - * Notice in each file and include the License file at
  120.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  120.20 - * particular file as subject to the "Classpath" exception as provided
  120.21 - * by Sun in the GPL Version 2 section of the License file that
  120.22 - * accompanied this code. If applicable, add the following below the
  120.23 - * License Header, with the fields enclosed by brackets [] replaced by
  120.24 - * your own identifying information:
  120.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  120.26 - *
  120.27 - * Contributor(s):
  120.28 - *
  120.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  120.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  120.31 - * Microsystems, Inc. All Rights Reserved.
  120.32 - *
  120.33 - * If you wish your version of this file to be governed by only the CDDL
  120.34 - * or only the GPL Version 2, indicate your decision by adding
  120.35 - * "[Contributor] elects to include this software in this distribution
  120.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  120.37 - * single choice of license, a recipient has the option to distribute
  120.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  120.39 - * to extend the choice of license to its licensees as provided above.
  120.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  120.41 - * Version 2 license, then the option applies only if the new code is
  120.42 - * made subject to such option by the copyright holder.
  120.43 - */
  120.44 -
  120.45 -package org.openide.util.lookup;
  120.46 -
  120.47 -import java.util.logging.Level;
  120.48 -import org.netbeans.junit.MockServices;
  120.49 -import org.netbeans.junit.NbTestCase;
  120.50 -import org.netbeans.modules.openide.util.NamedServicesProvider;
  120.51 -import org.openide.util.Lookup;
  120.52 -
  120.53 -/** 
  120.54 - * @author Jaroslav Tulach
  120.55 - */
  120.56 -public class PathInLookupTest extends NbTestCase {
  120.57 -    static {
  120.58 -        System.setProperty("org.openide.util.Lookup.paths", "MyServices:YourServices");
  120.59 -        MockServices.setServices(P.class);
  120.60 -        Lookup.getDefault();
  120.61 -    }
  120.62 -
  120.63 -    public PathInLookupTest(String name) {
  120.64 -        super(name);
  120.65 -    }
  120.66 -
  120.67 -    @Override
  120.68 -    protected Level logLevel() {
  120.69 -        return Level.FINE;
  120.70 -    }
  120.71 -    
  120.72 -    public void testInterfaceFoundInMyServices() throws Exception {
  120.73 -        assertNull("not found", Lookup.getDefault().lookup(Shared.class));
  120.74 -        Shared v = new Shared();
  120.75 -        P.ic1.add(v);
  120.76 -        assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
  120.77 -        P.ic1.remove(v);
  120.78 -        assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
  120.79 -    }
  120.80 -    public void testInterfaceFoundInMyServices2() throws Exception {
  120.81 -        assertNull("not found", Lookup.getDefault().lookup(Shared.class));
  120.82 -        Shared v = new Shared();
  120.83 -        P.ic2.add(v);
  120.84 -        assertNotNull("found", Lookup.getDefault().lookup(Shared.class));
  120.85 -        P.ic2.remove(v);
  120.86 -        assertNull("not found again", Lookup.getDefault().lookup(Shared.class));
  120.87 -    }
  120.88 -
  120.89 -    static final class Shared extends Object {}
  120.90 -
  120.91 -    public static final class P extends NamedServicesProvider {
  120.92 -        static InstanceContent ic1 = new InstanceContent();
  120.93 -        static InstanceContent ic2 = new InstanceContent();
  120.94 -        static AbstractLookup[] arr = {
  120.95 -            new AbstractLookup(ic1), new AbstractLookup(ic2)
  120.96 -        };
  120.97 -
  120.98 -
  120.99 -        @Override
 120.100 -        public Lookup create(String path) {
 120.101 -            int indx = -1;
 120.102 -            if (path.equals("MyServices/")) {
 120.103 -                indx = 0;
 120.104 -            }
 120.105 -            if (path.equals("YourServices/")) {
 120.106 -                indx = 1;
 120.107 -            }
 120.108 -            if (indx == -1) {
 120.109 -                fail("Unexpected lookup query: " + path);
 120.110 -            }
 120.111 -            return arr[indx];
 120.112 -        }
 120.113 -    }
 120.114 -
 120.115 -}
   121.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/PrefixServicesLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   121.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.3 @@ -1,63 +0,0 @@
   121.4 -/*
   121.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   121.6 - *
   121.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   121.8 - *
   121.9 - * The contents of this file are subject to the terms of either the GNU
  121.10 - * General Public License Version 2 only ("GPL") or the Common
  121.11 - * Development and Distribution License("CDDL") (collectively, the
  121.12 - * "License"). You may not use this file except in compliance with the
  121.13 - * License. You can obtain a copy of the License at
  121.14 - * http://www.netbeans.org/cddl-gplv2.html
  121.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  121.16 - * specific language governing permissions and limitations under the
  121.17 - * License.  When distributing the software, include this License Header
  121.18 - * Notice in each file and include the License file at
  121.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  121.20 - * particular file as subject to the "Classpath" exception as provided
  121.21 - * by Sun in the GPL Version 2 section of the License file that
  121.22 - * accompanied this code. If applicable, add the following below the
  121.23 - * License Header, with the fields enclosed by brackets [] replaced by
  121.24 - * your own identifying information:
  121.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  121.26 - *
  121.27 - * Contributor(s):
  121.28 - *
  121.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  121.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  121.31 - * Microsystems, Inc. All Rights Reserved.
  121.32 - *
  121.33 - * If you wish your version of this file to be governed by only the CDDL
  121.34 - * or only the GPL Version 2, indicate your decision by adding
  121.35 - * "[Contributor] elects to include this software in this distribution
  121.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  121.37 - * single choice of license, a recipient has the option to distribute
  121.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  121.39 - * to extend the choice of license to its licensees as provided above.
  121.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  121.41 - * Version 2 license, then the option applies only if the new code is
  121.42 - * made subject to such option by the copyright holder.
  121.43 - */
  121.44 -
  121.45 -package org.openide.util.lookup;
  121.46 -
  121.47 -import org.openide.util.Lookup;
  121.48 -
  121.49 -
  121.50 -/** Test finding services from manifest.
  121.51 - * @author Jaroslav Tulach
  121.52 - */
  121.53 -public class PrefixServicesLookupTest extends MetaInfServicesLookupTest {
  121.54 -    public PrefixServicesLookupTest(String name) {
  121.55 -        super(name);
  121.56 -    }
  121.57 -    
  121.58 -    protected String prefix() {
  121.59 -        return "META-INF/netbeans/prefix/services/test/";
  121.60 -    }
  121.61 -    
  121.62 -    protected Lookup createLookup(ClassLoader c) {
  121.63 -        return Lookups.metaInfServices(c, prefix());
  121.64 -    }
  121.65 -    
  121.66 -}
   122.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupEventIssue136866Test.java	Sat Oct 31 15:06:58 2009 +0100
   122.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.3 @@ -1,56 +0,0 @@
   122.4 -package org.openide.util.lookup;
   122.5 -
   122.6 -import junit.framework.TestCase;
   122.7 -import org.openide.util.Lookup;
   122.8 -import org.openide.util.LookupEvent;
   122.9 -import org.openide.util.LookupListener;
  122.10 -
  122.11 -/**
  122.12 - * Test case which demonstrates that ProxyLookup does not fire
  122.13 - * an event when it should.
  122.14 - */
  122.15 -public class ProxyLookupEventIssue136866Test extends TestCase {
  122.16 -
  122.17 -    public ProxyLookupEventIssue136866Test(String testName) {
  122.18 -        super(testName);
  122.19 -    }
  122.20 -
  122.21 -    public void testAbstractLookupFiresEventWhenContentChanged() {
  122.22 -        InstanceContent ic = new InstanceContent();
  122.23 -        AbstractLookup al = new AbstractLookup(ic);
  122.24 -
  122.25 -        final int[] counts = {0}; // Number of items observed upon a LookupEvent
  122.26 -        final Lookup.Result<String> result = al.lookupResult(String.class);
  122.27 -
  122.28 -        result.addLookupListener(new LookupListener() {
  122.29 -            public void resultChanged(LookupEvent ev) {
  122.30 -                // this gets called as expected
  122.31 -                assertSame(result, ev.getSource());
  122.32 -                counts[0] = result.allInstances().size();
  122.33 -            }
  122.34 -        });
  122.35 -        
  122.36 -        ic.add("hello1");
  122.37 -        assertEquals(1, counts[0]);
  122.38 -    }
  122.39 -    
  122.40 -    public void testProxyLookupFailsToFireEventWhenProxiedLookupChanged() {
  122.41 -        InstanceContent ic = new InstanceContent();
  122.42 -//        AbstractLookup al = new AbstractLookup(ic);
  122.43 -        Lookup proxy = new AbstractLookup(ic);
  122.44 -
  122.45 -        final int[] counts = {0}; // Number of items observed upon a LookupEvent
  122.46 -        final Lookup.Result<String> result = proxy.lookupResult(String.class);
  122.47 -
  122.48 -        result.addLookupListener(new LookupListener() {
  122.49 -            public void resultChanged(LookupEvent ev) {
  122.50 -                // this should be called but never is
  122.51 -                assertSame(result, ev.getSource());
  122.52 -                counts[0] = result.allInstances().size();
  122.53 -            }
  122.54 -        });
  122.55 -        
  122.56 -        ic.add("hello1");
  122.57 -        assertEquals(1, counts[0]);
  122.58 -    }
  122.59 -}
   123.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   123.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.3 @@ -1,655 +0,0 @@
   123.4 -/*
   123.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   123.6 - *
   123.7 - * Copyright 1997-2009 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 - * Contributor(s):
  123.28 - *
  123.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  123.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  123.31 - * Microsystems, Inc. All Rights Reserved.
  123.32 - *
  123.33 - * If you wish your version of this file to be governed by only the CDDL
  123.34 - * or only the GPL Version 2, indicate your decision by adding
  123.35 - * "[Contributor] elects to include this software in this distribution
  123.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  123.37 - * single choice of license, a recipient has the option to distribute
  123.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  123.39 - * to extend the choice of license to its licensees as provided above.
  123.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  123.41 - * Version 2 license, then the option applies only if the new code is
  123.42 - * made subject to such option by the copyright holder.
  123.43 - */
  123.44 -
  123.45 -package org.openide.util.lookup;
  123.46 -
  123.47 -import java.io.Serializable;
  123.48 -
  123.49 -import java.lang.ref.Reference;
  123.50 -import java.lang.ref.WeakReference;
  123.51 -import java.util.*;
  123.52 -import java.util.concurrent.Executor;
  123.53 -import junit.framework.*;
  123.54 -import org.netbeans.junit.*;
  123.55 -import org.netbeans.modules.openide.util.ActiveQueue;
  123.56 -import org.openide.util.Lookup;
  123.57 -import org.openide.util.Lookup.Result;
  123.58 -import org.openide.util.LookupEvent;
  123.59 -import org.openide.util.LookupListener;
  123.60 -
  123.61 -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
  123.62 - */
  123.63 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  123.64 -public class ProxyLookupTest extends AbstractLookupBaseHid
  123.65 -implements AbstractLookupBaseHid.Impl {
  123.66 -    public ProxyLookupTest(java.lang.String testName) {
  123.67 -        super(testName, null);
  123.68 -    }
  123.69 -
  123.70 -    public static Test suite() {
  123.71 -        return new NbTestSuite (ProxyLookupTest.class);
  123.72 -//        return new ProxyLookupTest("testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679");
  123.73 -    }
  123.74 -    
  123.75 -    /** Creates an lookup for given lookup. This class just returns 
  123.76 -     * the object passed in, but subclasses can be different.
  123.77 -     * @param lookup in lookup
  123.78 -     * @return a lookup to use
  123.79 -     */
  123.80 -    public Lookup createLookup (Lookup lookup) {
  123.81 -        return new ProxyLookup (new Lookup[] { lookup });
  123.82 -    }
  123.83 -    
  123.84 -    public Lookup createInstancesLookup (InstanceContent ic) {
  123.85 -        return new AbstractLookup (ic);
  123.86 -    }
  123.87 -    
  123.88 -
  123.89 -    public void clearCaches () {
  123.90 -    }    
  123.91 -    
  123.92 -    
  123.93 -    /** Check whether setLookups method does not fire when there is no
  123.94 -     * change in the lookups.
  123.95 -     */
  123.96 -    public void testProxyListener () {
  123.97 -        ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
  123.98 -
  123.99 -        final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
 123.100 -        final Object[] IGNORE = {
 123.101 -            ProxyLookup.ImmutableInternalData.EMPTY,
 123.102 -            ProxyLookup.ImmutableInternalData.EMPTY_ARR,
 123.103 -            ActiveQueue.queue(),
 123.104 -            Collections.emptyMap(),
 123.105 -            Collections.emptyList(),
 123.106 -            Collections.emptySet()
 123.107 -        };
 123.108 -        
 123.109 -        assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
 123.110 -        
 123.111 -        Lookup.Result<Object> res = lookup.lookup (template);
 123.112 -
 123.113 -        assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
 123.114 -        
 123.115 -        LL ll = new LL ();
 123.116 -        res.addLookupListener (ll);
 123.117 -        Collection allRes = res.allInstances ();
 123.118 -        
 123.119 -        lookup.setLookups (new Lookup[0]);
 123.120 -        
 123.121 -        if (ll.getCount () != 0) {
 123.122 -           fail ("Calling setLookups (emptyarray) fired a change");
 123.123 -        }
 123.124 -        
 123.125 -        InstanceContent t = new InstanceContent();
 123.126 -        Lookup del = new AbstractLookup (t);
 123.127 -        t.add("Ahoj");
 123.128 -        lookup.setLookups (new Lookup[] { del });
 123.129 -        
 123.130 -        if (ll.getCount () != 1) {
 123.131 -            fail ("Changing lookups did not generate an event");
 123.132 -        }
 123.133 -        
 123.134 -        lookup.setLookups (new Lookup[] { del });
 123.135 -        
 123.136 -        if (ll.getCount () != 0) {
 123.137 -           fail ("Calling setLookups (thesamearray) fired a change");
 123.138 -        }
 123.139 -    }
 123.140 -    
 123.141 -    public void testNoListenersProxyListener () {
 123.142 -        ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
 123.143 -        class E implements Executor {
 123.144 -            Runnable r;
 123.145 -            public void execute(Runnable command) {
 123.146 -                assertNull("NO previous", r);
 123.147 -                r = command;
 123.148 -            }
 123.149 -            public void perform() {
 123.150 -                assertNotNull("We shall have a runnable", r);
 123.151 -                r.run();
 123.152 -                r = null;
 123.153 -            }
 123.154 -        }
 123.155 -        E executor = new E();
 123.156 -                
 123.157 -
 123.158 -        final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
 123.159 -        final Object[] IGNORE = {
 123.160 -            ProxyLookup.ImmutableInternalData.EMPTY,
 123.161 -            ProxyLookup.ImmutableInternalData.EMPTY_ARR,
 123.162 -            ActiveQueue.queue(),
 123.163 -            Collections.emptyMap(),
 123.164 -            Collections.emptyList(),
 123.165 -            Collections.emptySet()
 123.166 -        };
 123.167 -        
 123.168 -        assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
 123.169 -        
 123.170 -        Lookup.Result<Object> res = lookup.lookup (template);
 123.171 -
 123.172 -        assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE);
 123.173 -        
 123.174 -        LL ll = new LL ();
 123.175 -        res.addLookupListener (ll);
 123.176 -        Collection allRes = res.allInstances ();
 123.177 -        
 123.178 -        lookup.setLookups (executor, new Lookup[0]);
 123.179 -        if (ll.getCount () != 0) {
 123.180 -           fail ("Calling setLookups (emptyarray) fired a change");
 123.181 -        }
 123.182 -        
 123.183 -        InstanceContent t = new InstanceContent();
 123.184 -        Lookup del = new AbstractLookup (t);
 123.185 -        t.add("Ahoj");
 123.186 -        lookup.setLookups (executor, new Lookup[] { del });
 123.187 -        assertEquals("No change yet", 0, ll.getCount());
 123.188 -        executor.perform();
 123.189 -        if (ll.getCount () != 1) {
 123.190 -            fail ("Changing lookups did not generate an event");
 123.191 -        }
 123.192 -        
 123.193 -        lookup.setLookups (executor, new Lookup[] { del });
 123.194 -        if (ll.getCount () != 0) {
 123.195 -           fail ("Calling setLookups (thesamearray) fired a change");
 123.196 -        }
 123.197 -    }
 123.198 -
 123.199 -    public void testSetLookups () throws Exception {
 123.200 -        AbstractLookup a1 = new AbstractLookup (new InstanceContent ());
 123.201 -        AbstractLookup a2 = new AbstractLookup (new InstanceContent ());
 123.202 -        
 123.203 -        InstanceContent i3 = new InstanceContent ();
 123.204 -        i3.add (i3);
 123.205 -        AbstractLookup a3 = new AbstractLookup (i3);
 123.206 -
 123.207 -        final ProxyLookup p = new ProxyLookup (new Lookup[] { a1, a2 });
 123.208 -        final Lookup.Result res1 = p.lookup (new Lookup.Template (Object.class));
 123.209 -        Collection c1 = res1.allInstances();
 123.210 -        
 123.211 -        Lookup.Result res2 = p.lookup (new Lookup.Template (String.class));
 123.212 -        Collection c2 = res2.allInstances ();
 123.213 -        
 123.214 -        
 123.215 -        assertTrue ("We need two results", res1 != res2);
 123.216 -
 123.217 -        final Object blocked = new Object ();
 123.218 -
 123.219 -        class L extends Object implements LookupListener {
 123.220 -            public void resultChanged (LookupEvent ev) {
 123.221 -                try {
 123.222 -                    res1.removeLookupListener(this);
 123.223 -                    
 123.224 -                    // waiting for second thread to start #111#
 123.225 -                    blocked.wait ();
 123.226 -
 123.227 -                } catch (Exception ex) {
 123.228 -                    ex.printStackTrace();
 123.229 -                    fail ("An exception occured ");
 123.230 -                }
 123.231 -            }
 123.232 -        }
 123.233 -        
 123.234 -        final L listener1 = new L ();
 123.235 -        res1.addLookupListener (listener1);
 123.236 -        
 123.237 -
 123.238 -        Runnable newLookupSetter = new Runnable() {
 123.239 -            public void run () {
 123.240 -                synchronized (blocked) {
 123.241 -                    try {
 123.242 -                        p.setLookups (new Lookup[0]);
 123.243 -                    } catch (Exception ex) {
 123.244 -                        ex.printStackTrace();
 123.245 -                        fail ("setLookups failed.");
 123.246 -                    } finally {
 123.247 -                        // starts the main thread #111#
 123.248 -                        blocked.notify ();
 123.249 -                    }
 123.250 -                }
 123.251 -            }
 123.252 -        };
 123.253 -        
 123.254 -        synchronized (blocked) {
 123.255 -            new Thread (newLookupSetter).start ();
 123.256 -            
 123.257 -            p.setLookups (new Lookup[] { a1, a2, a3 });
 123.258 -        }
 123.259 -    }
 123.260 -    
 123.261 -    public void testProxyLookupTemplateCaching(){
 123.262 -        Lookup lookups[] = new Lookup[1];
 123.263 -        doProxyLookupTemplateCaching(lookups, false);
 123.264 -    }
 123.265 -    
 123.266 -    public void testProxyLookupTemplateCachingOnSizeTwoArray() {
 123.267 -        Lookup lookups[] = new Lookup[2];
 123.268 -        lookups[1] = Lookup.EMPTY;
 123.269 -        doProxyLookupTemplateCaching(lookups, false);
 123.270 -    }
 123.271 -    public void testProxyLookupShallNotAllowModificationOfGetLookups(){
 123.272 -        Lookup lookups[] = new Lookup[1];
 123.273 -        doProxyLookupTemplateCaching(lookups, true);
 123.274 -    }
 123.275 -    
 123.276 -    public void testProxyLookupShallNotAllowModificationOfGetLookupsOnSizeTwoArray() {
 123.277 -        Lookup lookups[] = new Lookup[2];
 123.278 -        lookups[1] = Lookup.EMPTY;
 123.279 -        doProxyLookupTemplateCaching(lookups, true);
 123.280 -    }
 123.281 -    
 123.282 -    /** Index 0 of lookups will be modified, the rest is up to the 
 123.283 -     * setup code.
 123.284 -     */
 123.285 -    private void doProxyLookupTemplateCaching(Lookup[] lookups, boolean reget) {
 123.286 -        // Create MyProxyLookup with one lookup containing the String object
 123.287 -        InstanceContent inst = new InstanceContent();
 123.288 -        inst.add(new String("Hello World")); //NOI18N
 123.289 -        lookups[0] = new AbstractLookup(inst);
 123.290 -        ProxyLookup proxy = new ProxyLookup(lookups);
 123.291 -        if (reget) {
 123.292 -            lookups = proxy.getLookups();
 123.293 -        }
 123.294 -        
 123.295 -        // Performing template lookup for String object
 123.296 -        Lookup.Result result = proxy.lookup(new Lookup.Template(String.class, null, null));
 123.297 -        int stringTemplateResultSize = result.allInstances().size();
 123.298 -        assertEquals ("Ensure, there is only one instance of String.class in proxyLookup:", //NOI18N
 123.299 -                1, stringTemplateResultSize);
 123.300 -        
 123.301 -        // Changing lookup in proxy lookup, now it will contain 
 123.302 -        // StringBuffer Object instead of String
 123.303 -        InstanceContent ic2 = new InstanceContent();
 123.304 -        ic2.add(new Integer(1234567890));
 123.305 -        lookups[0] = new AbstractLookup(ic2);
 123.306 -        proxy.setLookups(lookups);
 123.307 -        
 123.308 -        assertEquals ("the old result is updated", 0, result.allInstances().size());
 123.309 -
 123.310 -        // Instance of String.class should not appear in proxyLookup
 123.311 -        Lookup.Result r2 = proxy.lookup(new Lookup.Template(String.class, null, null));
 123.312 -        assertEquals ("Instance of String.class should not appear in proxyLookup:", //NOI18N
 123.313 -                0, r2.allInstances().size());
 123.314 -
 123.315 -        Lookup.Result r3 = proxy.lookup(new Lookup.Template(Integer.class, null, null));
 123.316 -        assertEquals ("There is only one instance of Integer.class in proxyLookup:", //NOI18N
 123.317 -                1, r3.allInstances().size());
 123.318 -    }
 123.319 -    
 123.320 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
 123.321 -        doListeningAndQueryingByTwoListenersSetLookups(0, 1);
 123.322 -    }
 123.323 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
 123.324 -        doListeningAndQueryingByTwoListenersSetLookups(1, 1);        
 123.325 -    }
 123.326 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
 123.327 -        doListeningAndQueryingByTwoListenersSetLookups(2, 1);
 123.328 -    }
 123.329 -    
 123.330 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
 123.331 -        doListeningAndQueryingByTwoListenersSetLookups(0, 2);
 123.332 -    }
 123.333 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
 123.334 -        doListeningAndQueryingByTwoListenersSetLookups(1, 2);        
 123.335 -    }
 123.336 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
 123.337 -        doListeningAndQueryingByTwoListenersSetLookups(2, 2);
 123.338 -    }
 123.339 -    public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
 123.340 -        doListeningAndQueryingByTwoListenersSetLookups(0, 22);
 123.341 -    }
 123.342 -    public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
 123.343 -        doListeningAndQueryingByTwoListenersSetLookups(1, 22);        
 123.344 -    }
 123.345 -    public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
 123.346 -        doListeningAndQueryingByTwoListenersSetLookups(2, 22);
 123.347 -    }
 123.348 -    
 123.349 -    private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth) {
 123.350 -        ProxyLookup orig = new ProxyLookup();
 123.351 -        ProxyLookup on = orig;
 123.352 -        
 123.353 -        while (--depth > 0) {
 123.354 -            on = new ProxyLookup(new Lookup[] { on });
 123.355 -        }
 123.356 -        
 123.357 -        
 123.358 -        final ProxyLookup lookup = on;
 123.359 -        
 123.360 -        class L implements LookupListener {
 123.361 -            Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
 123.362 -            Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
 123.363 -            Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
 123.364 -            
 123.365 -            {
 123.366 -                integer.addLookupListener(this);
 123.367 -                number.addLookupListener(this);
 123.368 -                serial.addLookupListener(this);
 123.369 -            }
 123.370 -            
 123.371 -            int round;
 123.372 -            
 123.373 -            public void resultChanged(LookupEvent ev) {
 123.374 -                Collection c1 = get(type, integer);
 123.375 -                Collection c2 = get(type, number);
 123.376 -                Collection c3 = get(type, serial);
 123.377 -                
 123.378 -                assertEquals("round " + round + " c1 vs. c2", c1, c2);
 123.379 -                assertEquals("round " + round + " c1 vs. c3", c1, c3);
 123.380 -                assertEquals("round " + round + " c2 vs. c3", c2, c3);
 123.381 -                
 123.382 -                round++;
 123.383 -            }            
 123.384 -
 123.385 -            private Collection get(int type, Lookup.Result res) {
 123.386 -                Collection c;
 123.387 -                switch(type) {
 123.388 -                    case 0: c = res.allInstances(); break;
 123.389 -                    case 1: c = res.allClasses(); break;
 123.390 -                    case 2: c = res.allItems(); break;
 123.391 -                    default: c = null; fail("Type: " + type); break;
 123.392 -                }
 123.393 -                
 123.394 -                assertNotNull(c);
 123.395 -                return new ArrayList(c);
 123.396 -            }
 123.397 -        }
 123.398 -        
 123.399 -        L listener = new L();
 123.400 -        listener.resultChanged(null);
 123.401 -        ArrayList arr = new ArrayList();
 123.402 -        for(int i = 0; i < 100; i++) {
 123.403 -            arr.add(new Integer(i));
 123.404 -            
 123.405 -            orig.setLookups(new Lookup[] { Lookups.fixed(arr.toArray()) });
 123.406 -        }
 123.407 -        
 123.408 -        assertEquals("3x100+1 checks", 301, listener.round);
 123.409 -    }
 123.410 -
 123.411 -    static Object holder;
 123.412 -    
 123.413 -    public void testProxyWithLiveResultCanBeCollected() {
 123.414 -        Lookup layer0 = Lookups.singleton("Hello");
 123.415 -        Lookup layer1 = new ProxyLookup(new Lookup[] { layer0 });
 123.416 -        Lookup layer2 = new ProxyLookup(new Lookup[] { layer1 });
 123.417 -        Lookup.Result result1 = layer1.lookup(new Lookup.Template(String.class));
 123.418 -
 123.419 -        assertEquals("One instance", 1, result1.allInstances().size());
 123.420 -
 123.421 -        // this will create ProxyLookup$R which listens on origResult
 123.422 -        Lookup.Result result2 = layer2.lookup(new Lookup.Template(String.class));
 123.423 -        
 123.424 -        // this line is necessary. W/o actually querying the result,
 123.425 -        // it will nether compute it nor attach the listener.
 123.426 -        assertEquals("One instance", 1, result2.allInstances().size());
 123.427 -        
 123.428 -        result2.addLookupListener(new LookupListener() {
 123.429 -            public void resultChanged(LookupEvent ev) {}
 123.430 -        });
 123.431 -        
 123.432 -        Reference ref = new WeakReference(layer2);
 123.433 -        layer2 = null;
 123.434 -        result2 = null;
 123.435 -        try {
 123.436 -            holder = result1;
 123.437 -            assertGC ("The proxy lookup not been garbage collected!", ref);
 123.438 -        } finally {
 123.439 -            holder = null;
 123.440 -        }
 123.441 -    }
 123.442 -    
 123.443 -    public void testArrayIndexAsInIssue119292() throws Exception {
 123.444 -        final ProxyLookup pl = new ProxyLookup();
 123.445 -        final int[] cnt = { 0 };
 123.446 -        
 123.447 -        class L extends Lookup {
 123.448 -            L[] set;
 123.449 -            Lookup l;
 123.450 -            
 123.451 -            public L(String s) {
 123.452 -                l = Lookups.singleton(s);
 123.453 -            }
 123.454 -            
 123.455 -            @Override
 123.456 -            public <T> T lookup(Class<T> clazz) {
 123.457 -                return l.lookup(clazz);
 123.458 -            }
 123.459 -
 123.460 -            @Override
 123.461 -            public <T> Result<T> lookup(Template<T> template) {
 123.462 -                return l.lookup(template);
 123.463 -            }
 123.464 -
 123.465 -            @Override
 123.466 -            @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
 123.467 -            public boolean equals(Object obj) {
 123.468 -                if (set != null) {
 123.469 -                    cnt[0]++;
 123.470 -                    pl.setLookups(set);
 123.471 -                }
 123.472 -                return super.equals(obj);
 123.473 -            }
 123.474 -
 123.475 -            @Override
 123.476 -            public int hashCode() {
 123.477 -                int hash = 3;
 123.478 -                return hash;
 123.479 -            }
 123.480 -        }
 123.481 -
 123.482 -        Result<String> res = pl.lookupResult(String.class);
 123.483 -        assertEquals(Collections.EMPTY_LIST, res.allItems());
 123.484 -        
 123.485 -        L[] old = { new L("A"), new L("B") };
 123.486 -        L[] now = { new L("C") };
 123.487 -        
 123.488 -        pl.setLookups(old);
 123.489 -        cnt[0] = 0;
 123.490 -        
 123.491 -        old[0].set = new L[0];
 123.492 -        pl.setLookups(now);
 123.493 -
 123.494 -        assertEquals("No call to equals", 0, cnt[0]);
 123.495 -        
 123.496 -        assertEquals("Still assigned to C", Collections.singletonList("C"), res.allInstances());
 123.497 -    }
 123.498 -    
 123.499 -    public void testArrayIndexWithAddRemoveListenerAsInIssue119292() throws Exception {
 123.500 -        final ProxyLookup pl = new ProxyLookup();
 123.501 -        final int[] cnt = { 0 };
 123.502 -        
 123.503 -        class L extends Lookup {
 123.504 -            L[] set;
 123.505 -            Lookup l;
 123.506 -            
 123.507 -            public L(String s) {
 123.508 -                l = Lookups.singleton(s);
 123.509 -            }
 123.510 -            
 123.511 -            @Override
 123.512 -            public <T> T lookup(Class<T> clazz) {
 123.513 -                return l.lookup(clazz);
 123.514 -            }
 123.515 -
 123.516 -            @Override
 123.517 -            public <T> Result<T> lookup(Template<T> template) {
 123.518 -                Result<T> r = l.lookup(template);
 123.519 -                return new R<T>(r);
 123.520 -            }
 123.521 -
 123.522 -            final class R<T> extends Result<T> {
 123.523 -                private Result<T> delegate;
 123.524 -
 123.525 -                public R(Result<T> delegate) {
 123.526 -                    this.delegate = delegate;
 123.527 -                }
 123.528 -                
 123.529 -                @Override
 123.530 -                public void addLookupListener(LookupListener l) {
 123.531 -                    cnt[0]++;
 123.532 -                    if (set != null) {
 123.533 -                        pl.setLookups(set);
 123.534 -                    }
 123.535 -                    delegate.addLookupListener(l);
 123.536 -                }
 123.537 -
 123.538 -                @Override
 123.539 -                public void removeLookupListener(LookupListener l) {
 123.540 -                    cnt[0]++;
 123.541 -                    if (set != null) {
 123.542 -                        pl.setLookups(set);
 123.543 -                    }
 123.544 -                    delegate.removeLookupListener(l);
 123.545 -                }
 123.546 -
 123.547 -                @Override
 123.548 -                public Collection<? extends T> allInstances() {
 123.549 -                    return delegate.allInstances();
 123.550 -                }
 123.551 -            }
 123.552 -        }
 123.553 -
 123.554 -        Result<String> res = pl.lookupResult(String.class);
 123.555 -        assertEquals(Collections.EMPTY_LIST, res.allItems());
 123.556 -        
 123.557 -        L[] old = { new L("A"), new L("B") };
 123.558 -        L[] now = { new L("C") };
 123.559 -        
 123.560 -        pl.setLookups(old);
 123.561 -        cnt[0] = 0;
 123.562 -        
 123.563 -        old[0].set = new L[0];
 123.564 -        pl.setLookups(now);
 123.565 -
 123.566 -        if (cnt[0] == 0) {
 123.567 -            fail("There should be calls to listeners");
 123.568 -        }
 123.569 -        
 123.570 -        assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances());
 123.571 -    }
 123.572 -    
 123.573 -    
 123.574 -    public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception {
 123.575 -        final ProxyLookup pl = new ProxyLookup();
 123.576 -        final int[] cnt = { 0 };
 123.577 -        
 123.578 -        class L extends Lookup {
 123.579 -            L[] set;
 123.580 -            Lookup l;
 123.581 -            Collection<? extends Serializable> res;
 123.582 -            
 123.583 -            public L(String s) {
 123.584 -                l = Lookups.singleton(s);
 123.585 -            }
 123.586 -            
 123.587 -            @Override
 123.588 -            public <T> T lookup(Class<T> clazz) {
 123.589 -                return l.lookup(clazz);
 123.590 -            }
 123.591 -
 123.592 -            @Override
 123.593 -            public <T> Result<T> lookup(Template<T> template) {
 123.594 -                cnt[0]++;
 123.595 -                if (set != null) {
 123.596 -                    pl.setLookups(set);
 123.597 -                    res = pl.lookupAll(Serializable.class);
 123.598 -                }
 123.599 -                Result<T> r = l.lookup(template);
 123.600 -                return r;
 123.601 -            }
 123.602 -        }
 123.603 -
 123.604 -        L[] now = { new L("A"), new L("B") };
 123.605 -        L[] old = { new L("C") };
 123.606 -        pl.setLookups(old);
 123.607 -        old[0].set = now;
 123.608 -        
 123.609 -        Result<String> res = pl.lookupResult(String.class);
 123.610 -        assertEquals("New items visible", 2, res.allItems().size());
 123.611 -        
 123.612 -        
 123.613 -        pl.setLookups(new L("X"), new L("Y"), new L("Z"));
 123.614 -    }
 123.615 -    
 123.616 -    public void testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679() throws Exception {
 123.617 -        final ProxyLookup pl = new ProxyLookup();
 123.618 -        final int[] cnt = { 0 };
 123.619 -        
 123.620 -        class L extends Lookup {
 123.621 -            L[] set;
 123.622 -            Lookup l;
 123.623 -            Collection<? extends Serializable> res;
 123.624 -            
 123.625 -            public L(String s) {
 123.626 -                l = Lookups.singleton(s);
 123.627 -            }
 123.628 -            
 123.629 -            @Override
 123.630 -            public <T> T lookup(Class<T> clazz) {
 123.631 -                return l.lookup(clazz);
 123.632 -            }
 123.633 -
 123.634 -            @Override
 123.635 -            public <T> Result<T> lookup(Template<T> template) {
 123.636 -                cnt[0]++;
 123.637 -                if (set != null) {
 123.638 -                    pl.setLookups(set);
 123.639 -                    res = pl.lookupAll(Serializable.class);
 123.640 -                }
 123.641 -                Result<T> r = l.lookup(template);
 123.642 -                return r;
 123.643 -            }
 123.644 -        }
 123.645 -
 123.646 -        L dupl = new L("A");
 123.647 -        L[] now = { dupl };
 123.648 -        L[] old = { new L("C") };
 123.649 -        pl.setLookups(old);
 123.650 -        old[0].set = now;
 123.651 -        
 123.652 -        Result<String> res = pl.lookupResult(String.class);
 123.653 -        assertEquals("New items visible", 1, res.allItems().size());
 123.654 -        
 123.655 -        
 123.656 -        pl.setLookups(old);
 123.657 -    }
 123.658 -}
   124.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SimpleLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   124.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.3 @@ -1,351 +0,0 @@
   124.4 -/*
   124.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   124.6 - *
   124.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   124.8 - *
   124.9 - * The contents of this file are subject to the terms of either the GNU
  124.10 - * General Public License Version 2 only ("GPL") or the Common
  124.11 - * Development and Distribution License("CDDL") (collectively, the
  124.12 - * "License"). You may not use this file except in compliance with the
  124.13 - * License. You can obtain a copy of the License at
  124.14 - * http://www.netbeans.org/cddl-gplv2.html
  124.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  124.16 - * specific language governing permissions and limitations under the
  124.17 - * License.  When distributing the software, include this License Header
  124.18 - * Notice in each file and include the License file at
  124.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  124.20 - * particular file as subject to the "Classpath" exception as provided
  124.21 - * by Sun in the GPL Version 2 section of the License file that
  124.22 - * accompanied this code. If applicable, add the following below the
  124.23 - * License Header, with the fields enclosed by brackets [] replaced by
  124.24 - * your own identifying information:
  124.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  124.26 - *
  124.27 - * Contributor(s):
  124.28 - *
  124.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  124.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
  124.31 - * Microsystems, Inc. All Rights Reserved.
  124.32 - *
  124.33 - * If you wish your version of this file to be governed by only the CDDL
  124.34 - * or only the GPL Version 2, indicate your decision by adding
  124.35 - * "[Contributor] elects to include this software in this distribution
  124.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  124.37 - * single choice of license, a recipient has the option to distribute
  124.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  124.39 - * to extend the choice of license to its licensees as provided above.
  124.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  124.41 - * Version 2 license, then the option applies only if the new code is
  124.42 - * made subject to such option by the copyright holder.
  124.43 - */
  124.44 -
  124.45 -package org.openide.util.lookup;
  124.46 -
  124.47 -import java.util.ArrayList;
  124.48 -import java.util.Arrays;
  124.49 -import java.util.Collection;
  124.50 -import java.util.List;
  124.51 -import java.util.Set;
  124.52 -import org.netbeans.junit.NbTestCase;
  124.53 -import org.openide.util.Lookup;
  124.54 -
  124.55 -/**
  124.56 - * Tests for class SimpleLookup.
  124.57 - * @author David Strupl
  124.58 - */
  124.59 -public class SimpleLookupTest extends NbTestCase {
  124.60 -
  124.61 -    public SimpleLookupTest(String testName) {
  124.62 -        super(testName);
  124.63 -    }
  124.64 -
  124.65 -    public void testEmptyLookup() {
  124.66 -        assertSize("Lookup.EMPTY should be small", 8, Lookup.EMPTY);
  124.67 -    }
  124.68 -
  124.69 -    /**
  124.70 -     * Simple tests testing singleton lookup.
  124.71 -     */
  124.72 -    public void testSingleton() {
  124.73 -        //
  124.74 -        Object orig = new Object();
  124.75 -        Lookup p1 = Lookups.singleton(orig);
  124.76 -        Object obj = p1.lookup(Object.class);
  124.77 -        assertTrue(obj == orig);
  124.78 -        assertNull(p1.lookup(String.class)); 
  124.79 -        assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
  124.80 -        //
  124.81 -        Lookup p2 = Lookups.singleton("test");
  124.82 -        assertNotNull(p2.lookup(Object.class));
  124.83 -        assertNotNull(p2.lookup(String.class));
  124.84 -        assertNotNull(p2.lookup(java.io.Serializable.class));
  124.85 -    }
  124.86 -    
  124.87 -    public void testEmptyFixed() {
  124.88 -        Lookup l = Lookups.fixed();
  124.89 -        assertSize("Lookups.fixed() for empty list of items should be small", 8, l);
  124.90 -        assertSame(Lookup.EMPTY, l);
  124.91 -    }
  124.92 -
  124.93 -    public void testSingleItemFixed() {
  124.94 -        Object o = new Object();
  124.95 -        Lookup l = Lookups.fixed(o);
  124.96 -        assertSize("Lookups.fixed(o) for a single item should be small", 24, l);
  124.97 -    }
  124.98 -
  124.99 -    /**
 124.100 -     * Simple tests testing fixed lookup.
 124.101 -     */
 124.102 -    public void testFixed() {
 124.103 -        //
 124.104 -        Object[] orig = new Object[] { new Object(), new Object() };
 124.105 -        Lookup p1 = Lookups.fixed(orig);
 124.106 -        Object obj = p1.lookup(Object.class);
 124.107 -        assertTrue(obj == orig[0] || obj == orig[1]);
 124.108 -        assertNull(p1.lookup(String.class)); 
 124.109 -        //
 124.110 -        String[] s = new String[] { "test1", "test2" };
 124.111 -        Lookup p2 = Lookups.fixed((Object[]) s);
 124.112 -        Object obj2 = p2.lookup(Object.class);
 124.113 -        assertNotNull(obj2);
 124.114 -        if (obj2 != s[0] && obj2 != s[1]) {
 124.115 -            fail("Returned objects are not the originals");
 124.116 -        }
 124.117 -        assertNotNull(p2.lookup(String.class));
 124.118 -        assertNotNull(p2.lookup(java.io.Serializable.class));
 124.119 -        Lookup.Template<String> t = new Lookup.Template<String>(String.class);
 124.120 -        Lookup.Result<String> r = p2.lookup(t);
 124.121 -        Collection<? extends String> all = r.allInstances();
 124.122 -        assertTrue(all.size() == 2);
 124.123 -        for (String o : all) {
 124.124 -            assertTrue("allInstances contains wrong objects", o.equals(s[0]) || o.equals(s[1]));
 124.125 -        }
 124.126 -        
 124.127 -        try {
 124.128 -            Lookups.fixed(new Object[] {null});
 124.129 -            fail("No nulls are allowed");
 124.130 -        } catch (NullPointerException ex) {
 124.131 -            // ok, NPE is what we want
 124.132 -        }        
 124.133 -    }
 124.134 -
 124.135 -    public void testFixedSubtypes() {
 124.136 -        class A {}
 124.137 -        class B extends A {}
 124.138 -        Lookup l = Lookups.fixed(new A(), new B());
 124.139 -        assertEquals(1, l.lookupAll(B.class).size());
 124.140 -        assertEquals(2, l.lookupAll(A.class).size());
 124.141 -    }
 124.142 -
 124.143 -    /**
 124.144 -     * Simple tests testing converting lookup.
 124.145 -     */
 124.146 -    public void testConverting() {
 124.147 -        //
 124.148 -        String[] orig = new String[] { TestConvertor.TEST1, TestConvertor.TEST2 };
 124.149 -        TestConvertor convertor = new TestConvertor();
 124.150 -        Lookup p1 = Lookups.fixed(orig, convertor);
 124.151 -        assertNull("Converting from String to Integer - it should not find String in result", p1.lookup(String.class));
 124.152 -        assertNotNull(p1.lookup(Integer.class));
 124.153 -        assertNotNull(p1.lookup(Integer.class));
 124.154 -        assertTrue("Convertor should be called only once.", convertor.getNumberOfConvertCalls() == 1); 
 124.155 -        Lookup.Template<Integer> t = new Lookup.Template<Integer>(Integer.class);
 124.156 -        Lookup.Result<Integer> r = p1.lookup(t);
 124.157 -        Collection<? extends Integer> all = r.allInstances();
 124.158 -        assertTrue(all.size() == 2);
 124.159 -        for (int i : all) {
 124.160 -            assertTrue("allInstances contains wrong objects", i == TestConvertor.t1 || i == TestConvertor.t2);
 124.161 -        }
 124.162 -    }
 124.163 -    
 124.164 -    private static class TestConvertor implements InstanceContent.Convertor<String,Integer> {
 124.165 -        static final String TEST1 = "test1";
 124.166 -        static final int t1 = 1;
 124.167 -        static final String TEST2 = "test2";
 124.168 -        static final int t2 = 2;
 124.169 -        
 124.170 -        private int numberOfConvertCalls = 0;
 124.171 -        
 124.172 -        public Integer convert(String obj) {
 124.173 -            numberOfConvertCalls++;
 124.174 -            if (obj.equals(TEST1)) {
 124.175 -                return t1;
 124.176 -            }
 124.177 -            if (obj.equals(TEST2)) {
 124.178 -                return t2;
 124.179 -            }
 124.180 -            throw new IllegalArgumentException();
 124.181 -        }
 124.182 -        
 124.183 -        public String displayName(String obj) {
 124.184 -            return obj;
 124.185 -        }
 124.186 -        
 124.187 -        public String id(String obj) {
 124.188 -            if (obj.equals(TEST1)) {
 124.189 -                return TEST1;
 124.190 -            }
 124.191 -            if (obj.equals(TEST2)) {
 124.192 -                return TEST2;
 124.193 -            }
 124.194 -            return null;
 124.195 -        }
 124.196 -        
 124.197 -        public Class<? extends Integer> type(String obj) {
 124.198 -            return Integer.class;
 124.199 -        }
 124.200 -        
 124.201 -        int getNumberOfConvertCalls() { 
 124.202 -            return numberOfConvertCalls;
 124.203 -        }
 124.204 -    }
 124.205 -    
 124.206 -    public void testLookupItem() {
 124.207 -        SomeInst inst = new SomeInst();
 124.208 -        Lookup.Item item = Lookups.lookupItem(inst, "XYZ");
 124.209 -        
 124.210 -        assertTrue("Wrong instance", item.getInstance() == inst);
 124.211 -        assertTrue("Wrong instance class", item.getType() == inst.getClass());
 124.212 -        assertEquals("Wrong id", "XYZ", item.getId());
 124.213 -
 124.214 -        item = Lookups.lookupItem(inst, null);
 124.215 -        assertNotNull("Id must never be null", item.getId());
 124.216 -    }
 124.217 -
 124.218 -    public void testLookupItemEquals() {
 124.219 -        SomeInst instA = new SomeInst();
 124.220 -        SomeInst instB = new SomeInst();
 124.221 -        Lookup.Item itemA = Lookups.lookupItem(instA, null);
 124.222 -        Lookup.Item itemB = Lookups.lookupItem(instB, null);
 124.223 -        
 124.224 -        assertTrue("Lookup items shouldn't be equal", !itemA.equals(itemB) && !itemB.equals(itemA));
 124.225 -
 124.226 -        itemA = Lookups.lookupItem(instA, null);
 124.227 -        itemB = Lookups.lookupItem(instA, null); // same instance
 124.228 -
 124.229 -        assertTrue("Lookup items should be equal", itemA.equals(itemB) && itemB.equals(itemA));
 124.230 -        assertTrue("Lookup items hashcode should be same", itemA.hashCode() == itemB.hashCode());
 124.231 -
 124.232 -        itemA = Lookups.lookupItem(new String("VOKURKA"), null);
 124.233 -        itemB = Lookups.lookupItem(new String("VOKURKA"), null);
 124.234 -
 124.235 -        assertTrue("Lookup items shouldn't be equal (2)", !itemA.equals(itemB) && !itemB.equals(itemA));
 124.236 -    }
 124.237 -    
 124.238 -    public void testAllClassesIssue42399 () throws Exception {
 124.239 -        Object[] arr = { "Ahoj", new Object () };
 124.240 -        
 124.241 -        Lookup l = Lookups.fixed (arr);
 124.242 -        
 124.243 -        Set<Class<? extends Object>> s = l.lookup(new Lookup.Template<Object>(Object.class)).allClasses();
 124.244 -        
 124.245 -        assertEquals ("Two there", 2, s.size ());
 124.246 -        assertTrue ("Contains Object.class", s.contains (Object.class));
 124.247 -        assertTrue ("Contains string", s.contains (String.class));
 124.248 -        
 124.249 -    }
 124.250 -
 124.251 -    public void testLookupItemEarlyInitializationProblem() {
 124.252 -        InstanceContent ic = new InstanceContent();
 124.253 -        AbstractLookup al = new AbstractLookup(ic);
 124.254 -        LI item = new LI();
 124.255 -        List<AbstractLookup.Pair> pairs1 = new ArrayList<AbstractLookup.Pair>();
 124.256 -        List<AbstractLookup.Pair> pairs2 = new ArrayList<AbstractLookup.Pair>();
 124.257 -        
 124.258 -        assertEquals("Item's instance shouldn't be requested", 0, item.cnt);
 124.259 -
 124.260 -        pairs1.add(new ItemPair<Object>(Lookups.<Object>lookupItem(new SomeInst(), null)));
 124.261 -        pairs1.add(new ItemPair<Object>(item));
 124.262 -        pairs1.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
 124.263 -
 124.264 -        pairs2.add(new ItemPair<Object>(item));
 124.265 -        pairs2.add(new ItemPair<Object>(Lookups.lookupItem(new Object(), null)));
 124.266 -
 124.267 -        ic.setPairs(pairs1);
 124.268 -        ic.setPairs(pairs2);
 124.269 -
 124.270 -        assertEquals("Item's instance shouldn't be requested when added to lookup", 0, item.cnt);
 124.271 -        
 124.272 -        LI item2 = al.lookup(LI.class);
 124.273 -        assertEquals("Item's instance should be requested", 1, item.cnt);
 124.274 -    }
 124.275 -
 124.276 -    public void testConvenienceMethods() throws Exception {
 124.277 -        // Just check signatures and basic behavior of #73848.
 124.278 -        Lookup l = Lookups.fixed(new Object[] {1, "hello", 2, "goodbye"});
 124.279 -        Collection<? extends Integer> ints = l.lookupAll(Integer.class);
 124.280 -        assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
 124.281 -        Lookup.Result<Integer> r = l.lookupResult(Integer.class);
 124.282 -        ints = r.allInstances();
 124.283 -        assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList<Integer>(ints));
 124.284 -    }
 124.285 -    
 124.286 -    private static class SomeInst { }
 124.287 -    
 124.288 -    private static class LI extends Lookup.Item<Object> {
 124.289 -
 124.290 -        public long cnt = 0;
 124.291 -        
 124.292 -        public String getDisplayName() {
 124.293 -            return getId();
 124.294 -        }
 124.295 -
 124.296 -        public String getId() {
 124.297 -            return getClass() + "@" + hashCode();
 124.298 -        }
 124.299 -
 124.300 -        public Object getInstance() {
 124.301 -            cnt++;
 124.302 -            return this;
 124.303 -        }
 124.304 -
 124.305 -        public Class<? extends Object> getType() {
 124.306 -            return getClass();
 124.307 -        }
 124.308 -    } // End of LI class
 124.309 -
 124.310 -    private static class ItemPair<T> extends AbstractLookup.Pair<T> {
 124.311 -        
 124.312 -        private AbstractLookup.Item<T> item;
 124.313 -        
 124.314 -        public ItemPair(Lookup.Item<T> i) {
 124.315 -            this.item = i;
 124.316 -        }
 124.317 -
 124.318 -        protected boolean creatorOf(Object obj) {
 124.319 -            return item.getInstance() == obj;
 124.320 -        }
 124.321 -
 124.322 -        public String getDisplayName() {
 124.323 -            return item.getDisplayName ();
 124.324 -        }
 124.325 -
 124.326 -        public String getId() {
 124.327 -            return item.getId ();
 124.328 -        }
 124.329 -
 124.330 -        public T getInstance() {
 124.331 -            return item.getInstance ();
 124.332 -        }
 124.333 -
 124.334 -        public Class<? extends T> getType() {
 124.335 -            return item.getType ();
 124.336 -        }
 124.337 -
 124.338 -        protected boolean instanceOf(Class<?> c) {
 124.339 -            return c.isAssignableFrom(getType());
 124.340 -        }
 124.341 -
 124.342 -        public @Override boolean equals(Object o) {
 124.343 -            if (o instanceof ItemPair) {
 124.344 -                ItemPair p = (ItemPair)o;
 124.345 -                return item.equals (p.item);
 124.346 -            }
 124.347 -            return false;
 124.348 -        }
 124.349 -
 124.350 -        public @Override int hashCode() {
 124.351 -            return item.hashCode ();
 124.352 -        }
 124.353 -    } // end of ItemPair
 124.354 -}
   125.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SimpleProxyLookupIssue42244Test.java	Sat Oct 31 15:06:58 2009 +0100
   125.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.3 @@ -1,120 +0,0 @@
   125.4 -/*
   125.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   125.6 - *
   125.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
   125.8 - *
   125.9 - * The contents of this file are subject to the terms of either the GNU
  125.10 - * General Public License Version 2 only ("GPL") or the Common
  125.11 - * Development and Distribution License("CDDL") (collectively, the
  125.12 - * "License"). You may not use this file except in compliance with the
  125.13 - * License. You can obtain a copy of the License at
  125.14 - * http://www.netbeans.org/cddl-gplv2.html
  125.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  125.16 - * specific language governing permissions and limitations under the
  125.17 - * License.  When distributing the software, include this License Header
  125.18 - * Notice in each file and include the License file at
  125.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
  125.20 - * particular file as subject to the "Classpath" exception as provided
  125.21 - * by Sun in the GPL Version 2 section of the License file that
  125.22 - * accompanied this code. If applicable, add the following below the
  125.23 - * License Header, with the fields enclosed by brackets [] replaced by
  125.24 - * your own identifying information:
  125.25 - * "Portions Copyrighted [year] [name of copyright owner]"
  125.26 - *
  125.27 - * Contributor(s):
  125.28 - *
  125.29 - * The Original Software is NetBeans. The Initial Developer of the Original
  125.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  125.31 - * Microsystems, Inc. All Rights Reserved.
  125.32 - *
  125.33 - * If you wish your version of this file to be governed by only the CDDL
  125.34 - * or only the GPL Version 2, indicate your decision by adding
  125.35 - * "[Contributor] elects to include this software in this distribution
  125.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  125.37 - * single choice of license, a recipient has the option to distribute
  125.38 - * your version of this file under either the CDDL, the GPL Version 2 or
  125.39 - * to extend the choice of license to its licensees as provided above.
  125.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  125.41 - * Version 2 license, then the option applies only if the new code is
  125.42 - * made subject to such option by the copyright holder.
  125.43 - */
  125.44 -
  125.45 -package org.openide.util.lookup;
  125.46 -
  125.47 -import java.lang.ref.WeakReference;
  125.48 -import java.util.*;
  125.49 -import junit.framework.*;
  125.50 -import org.netbeans.junit.*;
  125.51 -import org.openide.util.Lookup;
  125.52 -
  125.53 -/** To simulate issue 42244.
  125.54 - */
  125.55 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  125.56 -public class SimpleProxyLookupIssue42244Test extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl {
  125.57 -    public SimpleProxyLookupIssue42244Test (java.lang.String testName) {
  125.58 -        super(testName, null);
  125.59 -    }
  125.60 -
  125.61 -    public static Test suite() {
  125.62 -        // return new SimpleProxyLookupIssue42244Test("testGarbageCollect");
  125.63 -        return new NbTestSuite(SimpleProxyLookupIssue42244Test.class);
  125.64 -    }
  125.65 -    
  125.66 -    /** Creates an lookup for given lookup. This class just returns 
  125.67 -     * the object passed in, but subclasses can be different.
  125.68 -     * @param lookup in lookup
  125.69 -     * @return a lookup to use
  125.70 -     */
  125.71 -    public Lookup createLookup (final Lookup lookup) {
  125.72 -        class C implements Lookup.Provider {
  125.73 -            public Lookup getLookup () {
  125.74 -                return lookup;
  125.75 -            }
  125.76 -        }
  125.77 -        return Lookups.proxy (new C ());
  125.78 -    }
  125.79 -    
  125.80 -    public Lookup createInstancesLookup (InstanceContent ic) {
  125.81 -        return new KeepResultsProxyLookup (new AbstractLookup (ic));
  125.82 -    }
  125.83 -    
  125.84 -    public void clearCaches () {
  125.85 -        KeepResultsProxyLookup k = (KeepResultsProxyLookup)this.instanceLookup;
  125.86 -        
  125.87 -        ArrayList toGC = new ArrayList ();
  125.88 -        Iterator it = k.allQueries.iterator ();
  125.89 -        while (it.hasNext ()) {
  125.90 -            Lookup.Result r = (Lookup.Result)it.next ();
  125.91 -            toGC.add (new WeakReference (r));
  125.92 -        }
  125.93 -        
  125.94 -        k.allQueries = null;
  125.95 -        
  125.96 -        it = toGC.iterator ();
  125.97 -        while (it.hasNext ()) {
  125.98 -            WeakReference r = (WeakReference)it.next ();
  125.99 -            assertGC ("Trying to release all results from memory", r);
 125.100 -        }
 125.101 -    }
 125.102 -    
 125.103 -    class KeepResultsProxyLookup extends ProxyLookup {
 125.104 -        private ArrayList allQueries = new ArrayList ();
 125.105 -        private ThreadLocal in = new ThreadLocal ();
 125.106 -        
 125.107 -        public KeepResultsProxyLookup (Lookup delegate) {
 125.108 -            super (new Lookup[] { delegate });
 125.109 -        }
 125.110 -        
 125.111 -        @Override
 125.112 -        protected void beforeLookup (org.openide.util.Lookup.Template template) {
 125.113 -            super.beforeLookup (template);
 125.114 -            if (allQueries != null && in.get () == null) {
 125.115 -                in.set (this);
 125.116 -                Lookup.Result res = lookup (template);
 125.117 -                allQueries.add (res);
 125.118 -                in.set (null);
 125.119 -            }
 125.120 -        }
 125.121 -        
 125.122 -    }
 125.123 -}
   126.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SimpleProxyLookupSpeedIssue42244Test.java	Sat Oct 31 15:06:58 2009 +0100
   126.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.3 @@ -1,118 +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 java.util.HashSet;
  126.48 -import java.util.Set;
  126.49 -import org.netbeans.junit.NbTestCase;
  126.50 -
  126.51 -import org.netbeans.junit.RandomlyFails;
  126.52 -import org.openide.util.Lookup;
  126.53 -
  126.54 -/**
  126.55 - * @author  Petr Nejedly, adapted to test by Jaroslav Tulach
  126.56 - */
  126.57 -@RandomlyFails // NB-Core-Build #1847
  126.58 -public class SimpleProxyLookupSpeedIssue42244Test extends NbTestCase {
  126.59 -
  126.60 -    public SimpleProxyLookupSpeedIssue42244Test (String name) {
  126.61 -        super (name);
  126.62 -    }
  126.63 -
  126.64 -    public void testCompareTheSpeed () {
  126.65 -        String content1 = "String1";
  126.66 -        String content2 = "String2";
  126.67 -        
  126.68 -        Lookup fixed1 = Lookups.singleton(content1);
  126.69 -        Lookup fixed2 = Lookups.singleton(content2);
  126.70 -        
  126.71 -        MyProvider provider = new MyProvider();
  126.72 -        provider.setLookup(fixed1);
  126.73 -        
  126.74 -        Lookup top = Lookups.proxy(provider);
  126.75 -
  126.76 -        Lookup.Result<String> r0 = top.lookupResult(String.class);
  126.77 -        r0.allInstances();
  126.78 -
  126.79 -        long time = System.currentTimeMillis();
  126.80 -        top.lookupAll(String.class);
  126.81 -        long withOneResult = System.currentTimeMillis() - time;
  126.82 -
  126.83 -     
  126.84 -        Set<Object> results = new HashSet<Object>();
  126.85 -        for (int i=0; i<10000; i++) {
  126.86 -            Lookup.Result<String> res = top.lookupResult(String.class);
  126.87 -            results.add (res);
  126.88 -            res.allInstances();
  126.89 -        }
  126.90 -        
  126.91 -        provider.setLookup(fixed2);
  126.92 -
  126.93 -        time = System.currentTimeMillis();
  126.94 -        top.lookupAll(String.class);
  126.95 -        long withManyResults = System.currentTimeMillis() - time;
  126.96 -        
  126.97 -        // if the measurement takes less then 10ms, pretend 10ms
  126.98 -        if (withManyResults < 10) {
  126.99 -            withManyResults = 10;
 126.100 -        }
 126.101 -        if (withOneResult < 10) {
 126.102 -            withOneResult = 10;
 126.103 -        }
 126.104 -
 126.105 -        if (withManyResults >= 10 * withOneResult) {
 126.106 -            fail ("With many results the test runs too long.\n With many: " + withManyResults + "\n With one : " + withOneResult);
 126.107 -        }
 126.108 -    }
 126.109 -    
 126.110 -    private static class MyProvider implements Lookup.Provider {
 126.111 -        private Lookup lookup;
 126.112 -        public Lookup getLookup() {
 126.113 -            return lookup;
 126.114 -        }
 126.115 -        
 126.116 -        void setLookup(Lookup lookup) {
 126.117 -            this.lookup = lookup;
 126.118 -        }
 126.119 -    }
 126.120 -    
 126.121 -}
   127.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SimpleProxyLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   127.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.3 @@ -1,73 +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.lang.ref.WeakReference;
  127.48 -import org.netbeans.junit.NbTestCase;
  127.49 -import org.openide.util.Lookup;
  127.50 -import org.openide.util.Lookup.Provider;
  127.51 -
  127.52 -/**
  127.53 - *
  127.54 - * @author Jan Lahoda
  127.55 - */
  127.56 -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them
  127.57 -public class SimpleProxyLookupTest extends NbTestCase {
  127.58 -
  127.59 -    public SimpleProxyLookupTest(String testName) {
  127.60 -        super(testName);
  127.61 -    }
  127.62 -
  127.63 -    public void test69810() throws Exception {
  127.64 -        Lookup.Template t = new Lookup.Template(String.class);
  127.65 -        SimpleProxyLookup spl = new SimpleProxyLookup(new Provider() {
  127.66 -            public Lookup getLookup() {
  127.67 -                return Lookups.fixed(new Object[] {"test1", "test2"});
  127.68 -            }
  127.69 -        });
  127.70 -        
  127.71 -        assertGC("", new WeakReference(spl.lookup(t)));
  127.72 -        
  127.73 -        spl.lookup(new Lookup.Template(Object.class)).allInstances();
  127.74 -    }
  127.75 -    
  127.76 -}
   128.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/SingletonLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   128.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.3 @@ -1,113 +0,0 @@
   128.4 -/*
   128.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   128.6 - * 
   128.7 - * Copyright 2008 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 - * If you wish your version of this file to be governed by only the CDDL
  128.28 - * or only the GPL Version 2, indicate your decision by adding
  128.29 - * "[Contributor] elects to include this software in this distribution
  128.30 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  128.31 - * single choice of license, a recipient has the option to distribute
  128.32 - * your version of this file under either the CDDL, the GPL Version 2 or
  128.33 - * to extend the choice of license to its licensees as provided above.
  128.34 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  128.35 - * Version 2 license, then the option applies only if the new code is
  128.36 - * made subject to such option by the copyright holder.
  128.37 - * 
  128.38 - * Contributor(s):
  128.39 - * 
  128.40 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  128.41 - */
  128.42 -
  128.43 -package org.openide.util.lookup;
  128.44 -
  128.45 -import java.util.Collection;
  128.46 -import org.netbeans.junit.NbTestCase;
  128.47 -import org.openide.util.Lookup;
  128.48 -
  128.49 -/**
  128.50 - * Contains tests of class {@code SingletonLookup}.
  128.51 - *
  128.52 - * @author  Marian Petras
  128.53 - */
  128.54 -public class SingletonLookupTest extends NbTestCase {
  128.55 -    
  128.56 -    public SingletonLookupTest(String testName) {
  128.57 -        super(testName);
  128.58 -    }
  128.59 -
  128.60 -    public void testBasics() {
  128.61 -        Object orig = new Object();
  128.62 -        Lookup p1 = new SingletonLookup(orig);
  128.63 -        Object obj = p1.lookup(Object.class);
  128.64 -        assertTrue(obj == orig);
  128.65 -        assertNull(p1.lookup(String.class)); 
  128.66 -        assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same?
  128.67 -        //
  128.68 -        Lookup p2 = new SingletonLookup("test");
  128.69 -        assertNotNull(p2.lookup(Object.class));
  128.70 -        assertNotNull(p2.lookup(String.class));
  128.71 -        assertNotNull(p2.lookup(java.io.Serializable.class));
  128.72 -    }
  128.73 -
  128.74 -    public void testId() {
  128.75 -        Object orig = new Object();
  128.76 -        Collection allInstances;
  128.77 -
  128.78 -        Lookup l = new SingletonLookup(orig, "id");
  128.79 -
  128.80 -        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, null, null)).allInstances();
  128.81 -        assertNotNull(allInstances);
  128.82 -        assertFalse(allInstances.isEmpty());
  128.83 -        assertEquals(1, allInstances.size());
  128.84 -        assertTrue(allInstances.iterator().next() == orig);
  128.85 -
  128.86 -        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "id", null)).allInstances();
  128.87 -        assertNotNull(allInstances);
  128.88 -        assertFalse(allInstances.isEmpty());
  128.89 -        assertEquals(1, allInstances.size());
  128.90 -        assertTrue(allInstances.iterator().next() == orig);
  128.91 -
  128.92 -        allInstances = l.lookup(new Lookup.Template<Object>(Object.class, "not", null)).allInstances();
  128.93 -        assertNotNull(allInstances);
  128.94 -        assertTrue(allInstances.isEmpty());
  128.95 -
  128.96 -        allInstances = l.lookup(new Lookup.Template<String>(String.class, null, null)).allInstances();
  128.97 -        assertNotNull(allInstances);
  128.98 -        assertTrue(allInstances.isEmpty());
  128.99 -
 128.100 -        allInstances = l.lookup(new Lookup.Template<String>(String.class, "id", null)).allInstances();
 128.101 -        assertNotNull(allInstances);
 128.102 -        assertTrue(allInstances.isEmpty());
 128.103 -
 128.104 -        allInstances = l.lookup(new Lookup.Template<String>(String.class, "not", null)).allInstances();
 128.105 -        assertNotNull(allInstances);
 128.106 -        assertTrue(allInstances.isEmpty());
 128.107 -    }
 128.108 -
 128.109 -    public void testSize() {
 128.110 -        final Object obj = new Object();
 128.111 -        assertSize("The singleton lookup instance should be small",
 128.112 -                   24,
 128.113 -                   new SingletonLookup(obj));
 128.114 -    }
 128.115 -
 128.116 -}
   129.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/problem100320.txt	Sat Oct 31 15:06:58 2009 +0100
   129.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.3 @@ -1,17 +0,0 @@
   129.4 -:java.io.IOException:
   129.5 -java.nio.charset.CharacterCodingException
   129.6 -java.io.EOFException
   129.7 -java.io.FileNotFoundException
   129.8 -java.io.InterruptedIOException
   129.9 -java.net.MalformedURLException
  129.10 -java.io.IOException
  129.11 -java.io.UnsupportedEncodingException
  129.12 -java.io.NotActiveException
  129.13 -java.io.StreamCorruptedException
  129.14 -java.io.UTFDataFormatException
  129.15 -java.util.zip.ZipException
  129.16 -java.util.jar.JarException
  129.17 -:java.util.Comparator:
  129.18 -org.bar.Comparator3
  129.19 -org.bar.Comparator2
  129.20 -#position=5
   130.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/services-jar-1.txt	Sat Oct 31 15:06:58 2009 +0100
   130.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.3 @@ -1,17 +0,0 @@
   130.4 -:somedummyfile:
   130.5 -org.foo.Interface
   130.6 -:java.lang.Runnable:
   130.7 -org.foo.impl.Runnable1
   130.8 -:java.util.Comparator:
   130.9 -#some comment
  130.10 -org.foo.impl.Comparator1
  130.11 -#position=10
  130.12 -#som comment2
  130.13 -:java.util.Iterator:
  130.14 -org.foo.impl.Iterator1
  130.15 -:org.foo.Interface:
  130.16 -# Some header info, maybe.
  130.17 -
  130.18 -# Our first impl here
  130.19 -org.foo.impl.Implementation1
  130.20 -
   131.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/services-jar-2.txt	Sat Oct 31 15:06:58 2009 +0100
   131.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.3 @@ -1,10 +0,0 @@
   131.4 -:java.lang.Runnable:
   131.5 -#-org.foo.impl.Runnable1
   131.6 -:java.util.Comparator:
   131.7 -org.bar.Comparator2
   131.8 -#position=5
   131.9 -:java.util.Iterator:
  131.10 -org.bar.Iterator2
  131.11 -#position=100
  131.12 -:org.foo.Interface:
  131.13 -org.bar.Implementation2
   132.1 --- a/openide.util/test/unit/src/org/openide/util/test/MockLookup.java	Sat Oct 31 15:06:58 2009 +0100
   132.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.3 @@ -1,135 +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-2007 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.test;
  132.46 -
  132.47 -import java.lang.reflect.Field;
  132.48 -import java.util.Collection;
  132.49 -import static junit.framework.Assert.*;
  132.50 -import org.openide.util.Lookup;
  132.51 -import org.openide.util.lookup.Lookups;
  132.52 -import org.openide.util.lookup.ProxyLookup;
  132.53 -
  132.54 -/**
  132.55 - * Mock implementation of system default lookup suitable for use in unit tests.
  132.56 - * The initial value just contains classpath services.
  132.57 - */
  132.58 -public class MockLookup extends ProxyLookup {
  132.59 -
  132.60 -    private static MockLookup DEFAULT;
  132.61 -    private static boolean making = false;
  132.62 -    private static volatile boolean ready;
  132.63 -
  132.64 -    static {
  132.65 -        making = true;
  132.66 -        try {
  132.67 -            System.setProperty("org.openide.util.Lookup", MockLookup.class.getName());
  132.68 -            if (Lookup.getDefault().getClass() != MockLookup.class) {
  132.69 -                // Someone else initialized lookup first. Try to force our way.
  132.70 -                Field defaultLookup = Lookup.class.getDeclaredField("defaultLookup");
  132.71 -                defaultLookup.setAccessible(true);
  132.72 -                defaultLookup.set(null, null);
  132.73 -            }
  132.74 -            assertEquals(MockLookup.class, Lookup.getDefault().getClass());
  132.75 -        } catch (Exception x) {
  132.76 -            throw new ExceptionInInitializerError(x);
  132.77 -        } finally {
  132.78 -            making = false;
  132.79 -        }
  132.80 -    }
  132.81 -
  132.82 -    /** Do not call this directly! */
  132.83 -    public MockLookup() {
  132.84 -        assertTrue(making);
  132.85 -        assertNull(DEFAULT);
  132.86 -        DEFAULT = this;
  132.87 -    }
  132.88 -
  132.89 -    /**
  132.90 -     * Just ensures that this lookup is default lookup, but does not actually change its content.
  132.91 -     * Useful mainly if you have some test utility method which calls foreign code which might use default lookup,
  132.92 -     * and you want to ensure that any users of mock lookup will see the correct default lookup right away,
  132.93 -     * even if they have not yet called {@link #setLookup} or {@link #setInstances}.
  132.94 -     */
  132.95 -    public static void init() {
  132.96 -        if (!ready) {
  132.97 -            setInstances();
  132.98 -        }
  132.99 -    }
 132.100 -
 132.101 -    /**
 132.102 -     * Sets the global default lookup with zero or more delegate lookups.
 132.103 -     * Caution: if you don't include Lookups.metaInfServices, you may have trouble,
 132.104 -     * e.g. {@link #makeScratchDir} will not work.
 132.105 -     * Most of the time you should use {@link #setInstances} instead.
 132.106 -     */
 132.107 -    public static void setLookup(Lookup... lookups) {
 132.108 -        ready = true;
 132.109 -        DEFAULT.setLookups(lookups);
 132.110 -    }
 132.111 -
 132.112 -    /**
 132.113 -     * Sets the global default lookup with some fixed instances.
 132.114 -     * Will also include (at a lower priority) a {@link ClassLoader},
 132.115 -     * and services found from <code>META-INF/services/*</code> in the classpath.
 132.116 -     */
 132.117 -    public static void setInstances(Object... instances) {
 132.118 -        ClassLoader l = MockLookup.class.getClassLoader();
 132.119 -        setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
 132.120 -    }
 132.121 -    /**
 132.122 -     * Sets the global default lookup with some fixed instances and
 132.123 -     * content read from Services folder from system file system.
 132.124 -     * Will also include (at a lower priority) a {@link ClassLoader},
 132.125 -     * and services found from <code>META-INF/services/*</code> in the classpath.
 132.126 -     */
 132.127 -    public static void setLayersAndInstances(Object... instances) {
 132.128 -        ClassLoader l = MockLookup.class.getClassLoader();
 132.129 -        if (l != Lookup.getDefault().lookup(ClassLoader.class)) {
 132.130 -            setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l));
 132.131 -        }
 132.132 -        Lookup projects = Lookups.forPath("Services");
 132.133 -        Collection<?> initialize = projects.lookupAll(Object.class);
 132.134 -        //System.err.println("all: " + initialize);
 132.135 -        setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l), projects);
 132.136 -    }
 132.137 -
 132.138 -}
   133.1 --- a/openide.util/test/unit/src/org/openide/util/test/MockLookupTest.java	Sat Oct 31 15:06:58 2009 +0100
   133.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.3 @@ -1,66 +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-2007 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 -
  133.45 -package org.openide.util.test;
  133.46 -
  133.47 -import junit.framework.TestCase;
  133.48 -import org.openide.util.Lookup;
  133.49 -
  133.50 -public class MockLookupTest extends TestCase {
  133.51 -
  133.52 -    // XXX test:
  133.53 -    // setLookup with one or more lookup args does not use M-I/s
  133.54 -    // still works if another Lookup.getDefault was set before
  133.55 -
  133.56 -    public MockLookupTest(String n) {
  133.57 -        super(n);
  133.58 -    }
  133.59 -
  133.60 -    public void testSetLookup() throws Exception {
  133.61 -        MockLookup.setInstances("hello");
  133.62 -        assertEquals("initial lookup works", "hello", Lookup.getDefault().lookup(String.class));
  133.63 -        MockLookup.setInstances("goodbye");
  133.64 -        assertEquals("modified lookup works", "goodbye", Lookup.getDefault().lookup(String.class));
  133.65 -        MockLookup.setInstances();
  133.66 -        assertEquals("cleared lookup works", null, Lookup.getDefault().lookup(String.class));
  133.67 -    }
  133.68 -
  133.69 -}