# HG changeset patch # User Jaroslav Tulach # Date 1265151870 -3600 # Node ID a2947558c9667f7c787f1474b068706416e100cc # Parent b3ae88304dd059b987d103e8d3552c0af70b815f Removing local copy of lookup. Will use openide-util for now and switch to org.openide.util.lookup when available. diff -r b3ae88304dd0 -r a2947558c966 anagramdemo/anagramapp/pom.xml --- a/anagramdemo/anagramapp/pom.xml Wed Jan 27 17:46:23 2010 -0500 +++ b/anagramdemo/anagramapp/pom.xml Wed Feb 03 00:04:30 2010 +0100 @@ -33,13 +33,13 @@ org.netbeans.api org-netbeans-modules-nbjunit - RELEASE65 + RELEASE68 test org.netbeans.modules org-netbeans-insane - RELEASE65 + RELEASE68 test diff -r b3ae88304dd0 -r a2947558c966 anagramdemo/anagrambase/pom.xml --- a/anagramdemo/anagrambase/pom.xml Wed Jan 27 17:46:23 2010 -0500 +++ b/anagramdemo/anagrambase/pom.xml Wed Feb 03 00:04:30 2010 +0100 @@ -44,11 +44,6 @@ - org.apidesign - lookup - 7.22.0 - - org.springframework spring-core 2.5.6 diff -r b3ae88304dd0 -r a2947558c966 anagramdemo/simplescrambler/pom.xml --- a/anagramdemo/simplescrambler/pom.xml Wed Jan 27 17:46:23 2010 -0500 +++ b/anagramdemo/simplescrambler/pom.xml Wed Feb 03 00:04:30 2010 +0100 @@ -44,11 +44,6 @@ anagram-spring-lookup 1.0 - - org.apidesign - lookup - 7.22.0 - Simple Scrambler Replaces two letters in provided words. diff -r b3ae88304dd0 -r a2947558c966 anagramdemo/staticwordlibrary/pom.xml --- a/anagramdemo/staticwordlibrary/pom.xml Wed Jan 27 17:46:23 2010 -0500 +++ b/anagramdemo/staticwordlibrary/pom.xml Wed Feb 03 00:04:30 2010 +0100 @@ -19,15 +19,10 @@ test - org.apidesign - lookup - 7.22.0 - - org.apidesign anagram-spring-lookup 1.0 - + Static Word Library Provides an implementation of WordLibrary interface and registers it diff -r b3ae88304dd0 -r a2947558c966 lookup/apichanges.xml --- a/lookup/apichanges.xml Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ - - - - - - - - - - Separate module for Lookup API - - - - -

- Runtime compatibility remains, compile time compatibility is - mostly preserved too. It is however recommended to upgrade - dependencies of your modules. Try running - ant fix-dependencies in your Ant module. -

-
- -

- Lookup - and its associated interfaces are now available as a - separate module. -

-
- -
-

- Runtime compatibility remains, compile time compatibility is - mostly preserved too. It is however recommended to upgrade - dependencies of your modules. Try running - ant fix-dependencies in your Ant module. -

- - -

- Lookup - and its associated interfaces are now available as a - separate module. -

-
- - - - - - - - - - - - - - - - - - - - - - - - - ErrorManager.isNotifiable added - - - - - Existing code which assumes (incorrectly) that isLoggable - can be used for this purpose, or which calls notify at a low - level such as INFORMATIONAL without first checking - isNotifiable for efficiency, should be revised. - - - The method ErrorManager.isNotifiable was added to capture - the fact that an error manager implementation might be more aggressive - about displaying stack traces than log messages. - - - - - - - - ServiceType.createClone added - - Subclasses are encouraged to implement Cloneable. - - public final ServiceType createClone() added. - - - -
- - -Change History for the Lookup API - - - - -

Introduction

-

What do the Dates Mean?

-

The supplied dates indicate when the API change was made, on the CVS -trunk. From this you can generally tell whether the change should be -present in a given build or not; for trunk builds, simply whether it -was made before or after the change; for builds on a stabilization -branch, whether the branch was made before or after the given date. In -some cases corresponding API changes have been made both in the trunk -and in an in-progress stabilization branch, if they were needed for a -bug fix; this ought to be marked in this list.

-
    -
  • The release41 branch was made on Apr 03 '05 for use in the NetBeans 4.1 release. -Specification versions: 6.0 begins after this point.
  • -
  • The release40 branch was made on Nov 01 '04 for use in the NetBeans 4.0 release. -Specification versions: 5.0 begins after this point.
  • -
-
- -
-

@FOOTER@

- -
-
diff -r b3ae88304dd0 -r a2947558c966 lookup/arch.xml --- a/lookup/arch.xml Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,615 +0,0 @@ - - - -]> - - - - &api-questions; - - -

- This module defines the - Lookup which is the NetBeans way for dynamic registration - - - - -

- There is a lot of unit tests in - version control - system. -

-
- - -

- The module has been around since 1997 and is continously being improved - from time to time. -

-
- - - - - META-INF/services directory and it - services - your want or null depending on result of - - - - - -

- Described in the overall answer. -

- - - - - url="@org-openide-util@/org/openide/util/doc-files/api.html#service-lookup" - -

- This module has no settings. -

-
- - - - -

- Currently JRE 1.5 is needed. -

-
- - - - -

- JRE is enough. -

-
- - - -

N/A

-
- - -

- Platform independent. -

-
- - - -

- Nothing. -

-
- - - - -

- - the JAR file is located in platform cluster under lib/org-openide-util-lookup.jar - . -

-
- - -

- Module is on real java classpath and as such it has to be in the shared directory. -

-
- - - -

- No. -

-
- - - - -

- No, we do not create own classloader. -

-
- - - - -

- No. -

-
- - -

- No external processes executed. -

-
- - - -
    -
-
- - - - -

-

-
- - -

- Everything is synchronous, except pluggable use of java.util.concurrent.Executor - that allows to make calls asynchronous. The default implementation only delivers - changes from metaInfServices - lookup in asynchronous thread. -

-
- - - - -

- Not used. -

-
- - - - -

- The same as for clipboard. -

-
- - -

- No. -

-
- - - - -
    - -
  • - singleton subclasses of SharedClassObject - are searched for using Lookup. - .
  • - -
  • - Nearly all resource looking functions and reflective code - uses ClassLoader - obtained from Lookup.getDefault() - for loading system wide resources. - .
  • - -
-
- - - - -

- No. -

-
- - - - - -

- No. -

-
- - - - - -

- Nothing. -

-
- - - - - -

- No. -

-
- - - - - -

-

-
- - - - - -

- There are no big data structures. -

-
- - - - - -

- There are no menus. -

-
- - - - - -

- No. -

-
- - - - - -

- Lookup code scales linearily. -

-
- - - - - -

- No enforcing is done. -

-
- - - - - -

- No. -

-
- - - - - -

- No. -

-
- - - - - -

- No. -

-
- - - - - -

- No. -

-
- - - - - -

- No. -

-
- - - - - -

- No. -

-
- - - - - -

- No security permitions manipulated. -

-
- - - - - -

- No security permissions manipulated. -

-
- - - - - - - - - - - - - - -

- XXX no answer for compat-deprecation -

-
- - - - - -

- XXX no answer for resources-preferences -

-
- -
diff -r b3ae88304dd0 -r a2947558c966 lookup/manifest.mf --- a/lookup/manifest.mf Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: org.openide.util.lookup -OpenIDE-Module-Implementation-Version: 1 -OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties - diff -r b3ae88304dd0 -r a2947558c966 lookup/pom.xml --- a/lookup/pom.xml Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ - - 4.0.0 - org.apidesign - lookup - jar - 7.29.0 - http://lookup.apidesign.org - - org.apidesign - all-lookup - .. - 2.0 - - - hudson - http://hudson.apidesign.org/hudson/job/lookup - - - issuezilla - http://platform.netbeans.org/issues/ - - - - Using the NetBeans Platform - http://openide.netbeans.org/servlets/SummarizeList?listName=dev - dev@openide.netbeans.org - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.0.2 - - - default - - compile - - process-resources - - -proc:none - - - - - 1.5 - 1.5 - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.5 - - org.netbeans.modules.openide.util - ${basedir}/src/main/java/org/openide/util/lookup/doc-files/index.html - - - - - - - org.netbeans.api - org-netbeans-modules-nbjunit - RELEASE65 - test - - - org.netbeans.modules - org-netbeans-insane - RELEASE65 - test - - - Lookup Library - Lookup library is a general tool for component injection as well as -adaptable pattern. Originating from the heart of NetBeans project, -it is a general purpose library that can be used in any application. - -See http://lookup.apidesign.org - - diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/netbeans/modules/openide/util/AbstractServiceProviderProcessor.java --- a/lookup/src/main/java/org/netbeans/modules/openide/util/AbstractServiceProviderProcessor.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,296 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2009 Sun Microsystems, Inc. - */ - -package org.netbeans.modules.openide.util; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; -import javax.tools.Diagnostic.Kind; -import javax.tools.FileObject; -import javax.tools.StandardLocation; - -/** - * Infrastructure for generating {@code META-INF/services/*} and - * {@code META-INF/namedservices/*} registrations from annotations. - */ -public abstract class AbstractServiceProviderProcessor extends AbstractProcessor { - - private final Map>> outputFilesByProcessor = new WeakHashMap>>(); - private final Map>> originatingElementsByProcessor = new WeakHashMap>>(); - private final Map verifiedClasses = new WeakHashMap(); - - /** For access by subclasses. */ - protected AbstractServiceProviderProcessor() {} - - public @Override final boolean process(Set annotations, RoundEnvironment roundEnv) { - if (roundEnv.errorRaised()) { - return false; - } - if (roundEnv.processingOver()) { - writeServices(); - outputFilesByProcessor.clear(); - originatingElementsByProcessor.clear(); - return true; - } else { - return handleProcess(annotations, roundEnv); - } - } - - /** - * The regular body of {@link #process}. - * Called during regular rounds if there are no outstanding errors. - * In the last round, one of the processors will write out generated registrations. - * @param annotations as in {@link #process} - * @param roundEnv as in {@link #process} - * @return as in {@link #process} - */ - protected abstract boolean handleProcess(Set annotations, RoundEnvironment roundEnv); - - /** - * Register a service. - * If the class does not have an appropriate signature, an error will be printed and the registration skipped. - * @param clazz the service implementation type - * @param annotation the (top-level) annotation registering the service, for diagnostic purposes - * @param type the type to which the implementation must be assignable - * @param path a path under which to register, or "" if inapplicable - * @param position a position at which to register, or {@link Integer#MAX_VALUE} to skip - * @param supersedes possibly empty list of implementation to supersede - */ - protected final void register(TypeElement clazz, Class annotation, - TypeMirror type, String path, int position, String[] supersedes) { - Boolean verify = verifiedClasses.get(clazz); - if (verify == null) { - verify = verifyServiceProviderSignature(clazz, annotation); - verifiedClasses.put(clazz, verify); - } - if (!verify) { - return; - } - String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString(); - String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString(); - if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) { - AnnotationMirror ann = findAnnotationMirror(clazz, annotation); - processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface, - clazz, ann, findAnnotationValue(ann, "service")); - return; - } - processingEnv.getMessager().printMessage(Kind.NOTE, - impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : "")); - String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface; - { - Map> originatingElements = originatingElementsByProcessor.get(processingEnv); - if (originatingElements == null) { - originatingElements = new HashMap>(); - originatingElementsByProcessor.put(processingEnv, originatingElements); - } - List origEls = originatingElements.get(rsrc); - if (origEls == null) { - origEls = new ArrayList(); - originatingElements.put(rsrc, origEls); - } - origEls.add(clazz); - } - Map> outputFiles = outputFilesByProcessor.get(processingEnv); - if (outputFiles == null) { - outputFiles = new HashMap>(); - outputFilesByProcessor.put(processingEnv, outputFiles); - } - List lines = outputFiles.get(rsrc); - if (lines == null) { - lines = new ArrayList(); - try { - try { - FileObject in = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", rsrc); - in.openInputStream().close(); - processingEnv.getMessager().printMessage(Kind.ERROR, - "Cannot generate " + rsrc + " because it already exists in sources: " + in.toUri()); - return; - } catch (NullPointerException ex) { - // trying to prevent java.lang.NullPointerException - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1078) - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1054) - // at com.sun.tools.javac.processing.JavacFiler.getResource(JavacFiler.java:434) - // at org.netbeans.modules.openide.util.AbstractServiceProviderProcessor.register(AbstractServiceProviderProcessor.java:163) - // at org.netbeans.modules.openide.util.ServiceProviderProcessor.register(ServiceProviderProcessor.java:99) - } catch (FileNotFoundException x) { - // Good. - } - try { - FileObject in = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", rsrc); - InputStream is = in.openInputStream(); - try { - BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8")); - String line; - while ((line = r.readLine()) != null) { - lines.add(line); - } - } finally { - is.close(); - } - } catch (FileNotFoundException x) { - // OK, created for the first time - } - } catch (IOException x) { - processingEnv.getMessager().printMessage(Kind.ERROR, x.toString()); - return; - } - outputFiles.put(rsrc, lines); - } - int idx = lines.indexOf(impl); - if (idx != -1) { - lines.remove(idx); - while (lines.size() > idx && lines.get(idx).matches("#position=.+|#-.+")) { - lines.remove(idx); - } - } - lines.add(impl); - if (position != Integer.MAX_VALUE) { - lines.add("#position=" + position); - } - for (String exclude : supersedes) { - lines.add("#-" + exclude); - } - } - - /** - * @param element a source element - * @param annotation a type of annotation - * @return the instance of that annotation on the element, or null if not found - */ - private AnnotationMirror findAnnotationMirror(Element element, Class annotation) { - for (AnnotationMirror ann : element.getAnnotationMirrors()) { - if (processingEnv.getElementUtils().getBinaryName((TypeElement) ann.getAnnotationType().asElement()). - contentEquals(annotation.getName())) { - return ann; - } - } - return null; - } - - /** - * @param annotation an annotation instance (null permitted) - * @param name the name of an attribute of that annotation - * @return the corresponding value if found - */ - private AnnotationValue findAnnotationValue(AnnotationMirror annotation, String name) { - if (annotation != null) { - for (Map.Entry entry : annotation.getElementValues().entrySet()) { - if (entry.getKey().getSimpleName().contentEquals(name)) { - return entry.getValue(); - } - } - } - return null; - } - - private final boolean verifyServiceProviderSignature(TypeElement clazz, Class annotation) { - AnnotationMirror ann = findAnnotationMirror(clazz, annotation); - if (!clazz.getModifiers().contains(Modifier.PUBLIC)) { - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must be public", clazz, ann); - return false; - } - if (clazz.getModifiers().contains(Modifier.ABSTRACT)) { - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must not be abstract", clazz, ann); - return false; - } - { - boolean hasDefaultCtor = false; - for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) { - if (constructor.getModifiers().contains(Modifier.PUBLIC) && constructor.getParameters().isEmpty()) { - hasDefaultCtor = true; - break; - } - } - if (!hasDefaultCtor) { - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must have a public no-argument constructor", clazz, ann); - return false; - } - } - return true; - } - - private void writeServices() { - for (Map.Entry>> outputFiles : outputFilesByProcessor.entrySet()) { - for (Map.Entry> entry : outputFiles.getValue().entrySet()) { - try { - FileObject out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", entry.getKey(), - originatingElementsByProcessor.get(outputFiles.getKey()).get(entry.getKey()).toArray(new Element[0])); - OutputStream os = out.openOutputStream(); - try { - PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8")); - for (String line : entry.getValue()) { - w.println(line); - } - w.flush(); - w.close(); - } finally { - os.close(); - } - } catch (IOException x) { - processingEnv.getMessager().printMessage(Kind.ERROR, "Failed to write to " + entry.getKey() + ": " + x.toString()); - } - } - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/netbeans/modules/openide/util/ActiveQueue.java --- a/lookup/src/main/java/org/netbeans/modules/openide/util/ActiveQueue.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -package org.netbeans.modules.openide.util; - -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Implementation of the active reference queue. - */ -public final class ActiveQueue extends ReferenceQueue implements Runnable { - - private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.')); - private static ActiveQueue activeReferenceQueue; - - /** number of known outstanding references */ - private int count; - private boolean deprecated; - - ActiveQueue(boolean deprecated) { - super(); - this.deprecated = deprecated; - } - - public static synchronized ReferenceQueue queue() { - if (activeReferenceQueue == null) { - activeReferenceQueue = new ActiveQueue(false); - } - - activeReferenceQueue.ping(); - - return activeReferenceQueue; - } - - @Override - public Reference poll() { - throw new UnsupportedOperationException(); - } - - @Override - public Reference remove(long timeout) throws IllegalArgumentException, InterruptedException { - throw new InterruptedException(); - } - - @Override - public Reference remove() throws InterruptedException { - throw new InterruptedException(); - } - - public void run() { - while (true) { - try { - Reference ref = super.remove(0); - LOGGER.finer("dequeued reference"); - if (!(ref instanceof Runnable)) { - LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass()); - continue; - } - if (deprecated) { - LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue"); - } - // do the cleanup - try { - ((Runnable) ref).run(); - } catch (ThreadDeath td) { - throw td; - } catch (Throwable t) { - // Should not happen. - // If it happens, it is a bug in client code, notify! - LOGGER.log(Level.WARNING, null, t); - } finally { - // to allow GC - ref = null; - } - } catch (InterruptedException ex) { - // Can happen during VM shutdown, it seems. Ignore. - continue; - } - synchronized (this) { - assert count > 0; - count--; - if (count == 0) { - // We have processed all we have to process (for now at least). - // Could be restarted later if ping() called again. - // This could also happen in case someone called queue() once and tried - // to use it for several references; in that case run() might never be called on - // the later ones to be collected. Can't really protect against that situation. - // See issue #86625 for details. - LOGGER.fine("stopping thread"); - break; - } - } - } - } - - synchronized void ping() { - if (count == 0) { - Thread t = new Thread(this, "Active Reference Queue Daemon"); - t.setPriority(Thread.MIN_PRIORITY); - t.setDaemon(true); - t.start(); - LOGGER.fine("starting thread"); - } else { - LOGGER.finer("enqueuing reference"); - } - count++; - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/netbeans/modules/openide/util/NamedServicesProvider.java --- a/lookup/src/main/java/org/netbeans/modules/openide/util/NamedServicesProvider.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. - * - * Portions Copyrighted 2006 Sun Microsystems, Inc. - */ - -package org.netbeans.modules.openide.util; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.openide.util.Lookup; -import org.openide.util.lookup.Lookups; - -/** Interface for core/startup and core/settings - * to provide lookup over system filesystem. - * - * @author Jaroslav Tulach - */ -public abstract class NamedServicesProvider { - - private static final Map> map = Collections.synchronizedMap(new HashMap>()); - - public abstract Lookup create(String path); - - public static Lookup find(String path) { - if (!path.endsWith("/")) { - path = path + "/"; - } - - Reference ref = map.get(path); - Lookup lkp = ref == null ? null : ref.get(); - if (lkp != null) { - return lkp; - } - NamedServicesProvider prov = Lookup.getDefault().lookup(NamedServicesProvider.class); - if (prov != null && - /* avoid stack overflow during initialization */ - !path.startsWith( - "URLStreamHandler/" - /*URLStreamHandlerRegistrationProcessor.REGISTRATION_PREFIX*/ - ) - ) { - lkp = prov.create(path); - } else { - ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class); - if (l == null) { - l = Thread.currentThread().getContextClassLoader(); - if (l == null) { - l = NamedServicesProvider.class.getClassLoader(); - } - } - lkp = Lookups.metaInfServices(l, "META-INF/namedservices/" + path); - } - - map.put(path, new WeakReference(lkp)); - return lkp; - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/netbeans/modules/openide/util/ServiceProviderProcessor.java --- a/lookup/src/main/java/org/netbeans/modules/openide/util/ServiceProviderProcessor.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2008 Sun Microsystems, Inc. - */ - -package org.netbeans.modules.openide.util; - -import java.lang.annotation.Annotation; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import javax.annotation.processing.Completion; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.MirroredTypeException; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import org.openide.util.lookup.ServiceProvider; -import org.openide.util.lookup.ServiceProviders; - -@SupportedSourceVersion(SourceVersion.RELEASE_6) -public class ServiceProviderProcessor extends AbstractServiceProviderProcessor { - - public @Override Set getSupportedAnnotationTypes() { - return new HashSet(Arrays.asList( - ServiceProvider.class.getCanonicalName(), - ServiceProviders.class.getCanonicalName() - )); - } - - /** public for ServiceLoader */ - public ServiceProviderProcessor() {} - - protected boolean handleProcess(Set annotations, RoundEnvironment roundEnv) { - for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) { - TypeElement clazz = (TypeElement) el; - ServiceProvider sp = clazz.getAnnotation(ServiceProvider.class); - register(clazz, ServiceProvider.class, sp); - } - for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProviders.class)) { - TypeElement clazz = (TypeElement) el; - ServiceProviders spp = clazz.getAnnotation(ServiceProviders.class); - for (ServiceProvider sp : spp.value()) { - register(clazz, ServiceProviders.class, sp); - } - } - return true; - } - - private void register(TypeElement clazz, Class annotation, ServiceProvider svc) { - try { - svc.service(); - assert false; - return; - } catch (MirroredTypeException e) { - register(clazz, annotation, e.getTypeMirror(), svc.path(), svc.position(), svc.supersedes()); - } - } - - @Override - public Iterable getCompletions(Element annotated, AnnotationMirror annotation, ExecutableElement attr, String userText) { - if (processingEnv == null || annotated == null || !annotated.getKind().isClass()) { - return Collections.emptyList(); - } - - if ( annotation == null - || !"org.openide.util.lookup.ServiceProvider".contentEquals(((TypeElement) annotation.getAnnotationType().asElement()).getQualifiedName())) { - return Collections.emptyList(); - } - - if (!"service".contentEquals(attr.getSimpleName())) { - return Collections.emptyList(); - } - - TypeElement jlObject = processingEnv.getElementUtils().getTypeElement("java.lang.Object"); - - if (jlObject == null) { - return Collections.emptyList(); - } - - Collection result = new LinkedList(); - List toProcess = new LinkedList(); - - toProcess.add((TypeElement) annotated); - - while (!toProcess.isEmpty()) { - TypeElement c = toProcess.remove(0); - - result.add(new TypeCompletion(c.getQualifiedName().toString() + ".class")); - - List parents = new LinkedList(); - - parents.add(c.getSuperclass()); - parents.addAll(c.getInterfaces()); - - for (TypeMirror tm : parents) { - if (tm == null || tm.getKind() != TypeKind.DECLARED) { - continue; - } - - TypeElement type = (TypeElement) processingEnv.getTypeUtils().asElement(tm); - - if (!jlObject.equals(type)) { - toProcess.add(type); - } - } - } - - return result; - } - - private static final class TypeCompletion implements Completion { - - private final String type; - - public TypeCompletion(String type) { - this.type = type; - } - - public String getValue() { - return type; - } - - public String getMessage() { - return null; - } - - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/Lookup.java --- a/lookup/src/main/java/org/openide/util/Lookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,544 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import org.openide.util.lookup.Lookups; -import org.openide.util.lookup.ProxyLookup; -import org.openide.util.lookup.ServiceProvider; - -/** - * A general registry permitting clients to find instances of services - * (implementation of a given interface). - * This class is inspired by the - * Jini - * registration and lookup mechanism. The difference is that the methods do - * not throw checked exceptions (as they usually work only locally and not over the network) - * and that the Lookup API concentrates on the lookup, not on the registration - * (although {@link Lookup#getDefault} is strongly encouraged to support - * {@link Lookups#metaInfServices} for registration in addition to whatever - * else it decides to support). - *

- * For a general talk about the idea behind the lookup pattern please see - *

- * - * @see org.openide.util.lookup.AbstractLookup - * @see Lookups - * @see LookupListener - * @see LookupEvent - * @author Jaroslav Tulach - */ -public abstract class Lookup { - /** A dummy lookup that never returns any results. - */ - public static final Lookup EMPTY = new Empty(); - - /** default instance */ - private static Lookup defaultLookup; - - /** Empty constructor for use by subclasses. */ - public Lookup() { - } - - /** Static method to obtain the global lookup in the whole system. - * The actual returned implementation can be different in different - * systems, but the default one is based on - * {@link org.openide.util.lookup.Lookups#metaInfServices} - * with the context classloader of the first caller. Each system is - * adviced to honor this and include some form of metaInfServices - * implementation in the returned lookup as usage of META-INF/services - * is a JDK standard. - * - * @return the global lookup in the system - * @see ServiceProvider - */ - public static synchronized Lookup getDefault() { - if (defaultLookup != null) { - return defaultLookup; - } - - // You can specify a Lookup impl using a system property if you like. - String className = System.getProperty("org.openide.util.Lookup" // NOI18N - ); - - if ("-".equals(className)) { // NOI18N - - // Suppress even MetaInfServicesLookup. - return EMPTY; - } - - ClassLoader l = Thread.currentThread().getContextClassLoader(); - - try { - if (className != null) { - defaultLookup = (Lookup) Class.forName(className, true, l).newInstance(); - - return defaultLookup; - } - } catch (Exception e) { - // do not use ErrorManager because we are in the startup code - // and ErrorManager might not be ready - e.printStackTrace(); - } - - // OK, none specified (successfully) in a system property. - // Try MetaInfServicesLookup as a default, which may also - // have a org.openide.util.Lookup line specifying the lookup. - Lookup misl = Lookups.metaInfServices(l); - defaultLookup = misl.lookup(Lookup.class); - - if (defaultLookup != null) { - return defaultLookup; - } - - // You may also specify a Lookup.Provider. - Lookup.Provider prov = misl.lookup(Lookup.Provider.class); - - if (prov != null) { - defaultLookup = Lookups.proxy(prov); - - return defaultLookup; - } - - DefLookup def = new DefLookup(); - def.init(l, misl, false); - defaultLookup = def; - def.init(l, misl, true); - return defaultLookup; - } - - private static final class DefLookup extends ProxyLookup { - public DefLookup() { - super(new Lookup[0]); - } - - public void init(ClassLoader loader, Lookup metaInfLookup, boolean addPath) { - // Had no such line, use simple impl. - // It does however need to have ClassLoader available or many things will break. - // Use the thread context classloader in effect now. - Lookup clLookup = Lookups.singleton(loader); - List arr = new ArrayList(); - arr.add(metaInfLookup); - arr.add(clLookup); - String paths = System.getProperty("org.openide.util.Lookup.paths"); // NOI18N - if (addPath && paths != null) { - for (String p : paths.split(":")) { // NOI18N - arr.add(Lookups.forPath(p)); - } - } - setLookups(arr.toArray(new Lookup[0])); - } - } - - /** Called from MockServices to reset default lookup in case services change - */ - private static void resetDefaultLookup() { - if (defaultLookup instanceof DefLookup) { - DefLookup def = (DefLookup)defaultLookup; - ClassLoader l = Thread.currentThread().getContextClassLoader(); - def.init(l, Lookups.metaInfServices(l), true); - } - } - - /** Look up an object matching a given interface. - * This is the simplest method to use. - * If more than one object matches, the first will be returned. - * The template class may be a class or interface; the instance is - * guaranteed to be assignable to it. - * - * @param clazz class of the object we are searching for - * @return an object implementing the given class or null if no such - * implementation is found - */ - public abstract T lookup(Class clazz); - - /** The general lookup method. Callers can get list of all instances and classes - * that match the given template, request more info about - * them in form of {@link Lookup.Item} and attach a listener to - * this be notified about changes. The general interface does not - * specify whether subsequent calls with the same template produce new - * instance of the {@link Lookup.Result} or return shared instance. The - * prefered behaviour however is to return shared one. - * - * @param template a template describing the services to look for - * @return an object containing the results - */ - public abstract Result lookup(Template template); - - /** Look up the first item matching a given template. - * Includes not only the instance but other associated information. - * @param template the template to check - * @return a matching item or null - * - * @since 1.8 - */ - public Item lookupItem(Template template) { - Result res = lookup(template); - Iterator> it = res.allItems().iterator(); - return it.hasNext() ? it.next() : null; - } - - /** - * Find a result corresponding to a given class. - * Equivalent to calling {@link #lookup(Lookup.Template)} but slightly more convenient. - * Subclasses may override this method to produce the same semantics more efficiently. - * @param clazz the supertype of the result - * @return a live object representing instances of that type - * @since org.openide.util 6.10 - */ - public Lookup.Result lookupResult(Class clazz) { - return lookup(new Lookup.Template(clazz)); - } - - /** - * Find all instances corresponding to a given class. - * Equivalent to calling {@link #lookupResult} and asking for {@link Lookup.Result#allInstances} but slightly more convenient. - * Subclasses may override this method to produce the same semantics more efficiently. - *
- *

Example usage:

- *
-     * for (MyService svc : Lookup.getDefault().lookupAll(MyService.class)) {
-     *     svc.useMe();
-     * }
-     * 
- *
- * @param clazz the supertype of the result - * @return all currently available instances of that type - * @since org.openide.util 6.10 - */ - public Collection lookupAll(Class clazz) { - return lookupResult(clazz).allInstances(); - } - - /** - * Objects implementing interface Lookup.Provider are capable of - * and willing to provide a lookup (usually bound to the object). - * @since 3.6 - */ - public interface Provider { - /** - * Returns lookup associated with the object. - * @return fully initialized lookup instance provided by this object - */ - Lookup getLookup(); - } - - /* - * I expect this class to grow in the future, but for now, it is - * enough to start with something simple. - */ - - /** Template defining a pattern to filter instances by. - */ - public static final class Template extends Object { - /** cached hash code */ - private int hashCode; - - /** type of the service */ - private Class type; - - /** identity to search for */ - private String id; - - /** instance to search for */ - private T instance; - - /** General template to find all possible instances. - * @deprecated Use new Template (Object.class) which - * is going to be better typed with JDK1.5 templates and should produce - * the same result. - */ - @Deprecated - public Template() { - this(null); - } - - /** Create a simple template matching by class. - * @param type the class of service we are looking for (subclasses will match) - */ - public Template(Class type) { - this(type, null, null); - } - - /** Constructor to create new template. - * @param type the class of service we are looking for or null to leave unspecified - * @param id the ID of the item/service we are looking for or null to leave unspecified - * @param instance a specific known instance to look for or null to leave unspecified - */ - public Template(Class type, String id, T instance) { - this.type = extractType(type); - this.id = id; - this.instance = instance; - } - - @SuppressWarnings("unchecked") - private Class extractType(Class type) { - return (type == null) ? (Class)Object.class : type; - } - - /** Get the class (or superclass or interface) to search for. - * If it was not specified in the constructor, Object is used as - * this will match any instance. - * @return the class to search for - */ - public Class getType() { - return type; - } - - /** Get the persistent identifier being searched for, if any. - * @return the ID or null - * @see Lookup.Item#getId - * - * @since 1.8 - */ - public String getId() { - return id; - } - - /** Get the specific instance being searched for, if any. - * Most useful for finding an Item when the instance - * is already known. - * - * @return the object to find or null - * - * @since 1.8 - */ - public T getInstance() { - return instance; - } - - /* Computes hashcode for this template. The hashcode is cached. - * @return hashcode - */ - @Override - public int hashCode() { - if (hashCode != 0) { - return hashCode; - } - - hashCode = ((type == null) ? 1 : type.hashCode()) + ((id == null) ? 2 : id.hashCode()) + - ((instance == null) ? 3 : 0); - - return hashCode; - } - - /* Checks whether two templates represent the same query. - * @param obj another template to check - * @return true if so, false otherwise - */ - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Template)) { - return false; - } - - Template t = (Template) obj; - - if (hashCode() != t.hashCode()) { - // this is an optimalization - the hashCodes should have been - // precomputed - return false; - } - - if (type != t.type) { - return false; - } - - if (id == null) { - if (t.id != null) { - return false; - } - } else { - if (!id.equals(t.id)) { - return false; - } - } - - if (instance == null) { - return (t.instance == null); - } else { - return instance.equals(t.instance); - } - } - - /* for debugging */ - @Override - public String toString() { - return "Lookup.Template[type=" + type + ",id=" + id + ",instance=" + instance + "]"; // NOI18N - } - } - - /** Result of a lookup request. - * Allows access to all matching instances at once. - * Also permits listening to changes in the result. - * Result can contain duplicate items. - */ - public static abstract class Result extends Object { - /** Registers a listener that is invoked when there is a possible - * change in this result. - * - * @param l the listener to add - */ - public abstract void addLookupListener(LookupListener l); - - /** Unregisters a listener previously added. - * @param l the listener to remove - */ - public abstract void removeLookupListener(LookupListener l); - - /** Get all instances in the result. The return value type - * should be List instead of Collection, but it is too late to change it. - * @return unmodifiable collection of all instances that will never change its content - */ - public abstract Collection allInstances(); - - /** Get all classes represented in the result. - * That is, the set of concrete classes - * used by instances present in the result. - * All duplicate classes will be omitted. - * @return unmodifiable set of Class objects that will never change its content - * - * @since 1.8 - */ - public Set> allClasses() { - return Collections.emptySet(); - } - - /** Get all registered items. - * This should include all pairs of instances together - * with their classes, IDs, and so on. The return value type - * should be List instead of Collection, but it is too late to change it. - * @return unmodifiable collection of {@link Lookup.Item} that will never change its content - * - * @since 1.8 - */ - public Collection> allItems() { - return Collections.emptyList(); - } - } - - /** A single item in a lookup result. - * This wrapper provides unified access to not just the instance, - * but its class, a possible persistent identifier, and so on. - * - * @since 1.25 - */ - public static abstract class Item extends Object { - /** Get the instance itself. - * @return the instance or null if the instance cannot be created - */ - public abstract T getInstance(); - - /** Get the implementing class of the instance. - * @return the class of the item - */ - public abstract Class getType(); - - // XXX can it be null?? - - /** Get a persistent indentifier for the item. - * This identifier should uniquely represent the item - * within its containing lookup (and if possible within the - * global lookup as a whole). For example, it might represent - * the source of the instance as a file name. The ID may be - * persisted and in a later session used to find the same instance - * as was encountered earlier, by means of passing it into a - * lookup template. - * - * @return a string ID of the item - */ - public abstract String getId(); - - /** Get a human presentable name for the item. - * This might be used when summarizing all the items found in a - * lookup result in some part of a GUI. - * @return the string suitable for presenting the object to a user - */ - public abstract String getDisplayName(); - - /* show ID for debugging */ - @Override - public String toString() { - return getId(); - } - } - - // - // Implementation of the default lookup - // - private static final class Empty extends Lookup { - private static final Result NO_RESULT = new Result() { - public void addLookupListener(LookupListener l) { - } - - public void removeLookupListener(LookupListener l) { - } - - public Collection allInstances() { - return Collections.EMPTY_SET; - } - }; - - Empty() { - } - - public T lookup(Class clazz) { - return null; - } - - @SuppressWarnings("unchecked") - public Result lookup(Template template) { - return NO_RESULT; - } - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/LookupEvent.java --- a/lookup/src/main/java/org/openide/util/LookupEvent.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util; - -import java.util.*; - - -/** An event describing the change in the lookup's result. - * - * @author Jaroslav Tulach - */ -public final class LookupEvent extends EventObject { - /** Create a new lookup event. - * @param source the lookup result which has changed - */ - public LookupEvent(Lookup.Result source) { - super(source); - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/LookupListener.java --- a/lookup/src/main/java/org/openide/util/LookupListener.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util; - -import java.util.*; - - -/** General listener for changes in lookup. - * - * @author Jaroslav Tulach - */ -public interface LookupListener extends EventListener { - /** A change in lookup occured. Please note that this method - * should never block since it might be called from lookup implementation - * internal threads. If you block here you are in risk that the thread - * you wait for might in turn to wait for the lookup internal thread to - * finish its work. - * @param ev event describing the change - */ - public void resultChanged(LookupEvent ev); -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/ALPairComparator.java --- a/lookup/src/main/java/org/openide/util/lookup/ALPairComparator.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util.lookup; - -import java.util.Comparator; -import org.openide.util.lookup.AbstractLookup.Pair; - - -/** Implementation of comparator for AbstractLookup.Pair - * - * @author Jaroslav Tulach - */ -final class ALPairComparator implements Comparator> { - public static final Comparator> DEFAULT = new ALPairComparator(); - - /** Creates a new instance of ALPairComparator */ - private ALPairComparator() { - } - - /** Compares two items. - */ - public int compare(Pair i1, Pair i2) { - int result = i1.getIndex() - i2.getIndex(); - - if (result == 0) { - if (i1 != i2) { - java.io.ByteArrayOutputStream bs = new java.io.ByteArrayOutputStream(); - java.io.PrintStream ps = new java.io.PrintStream(bs); - - ps.println( - "Duplicate pair in tree" + // NOI18N - "Pair1: " + i1 + " pair2: " + i2 + " index1: " + i1.getIndex() + " index2: " + - i2.getIndex() // NOI18N - +" item1: " + i1.getInstance() + " item2: " + i2.getInstance() // NOI18N - +" id1: " + Integer.toHexString(System.identityHashCode(i1)) // NOI18N - +" id2: " + Integer.toHexString(System.identityHashCode(i2)) // NOI18N - ); - - // print (ps, false); - ps.close(); - - throw new IllegalStateException(bs.toString()); - } - - return 0; - } - - return result; - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/AbstractLookup.java --- a/lookup/src/main/java/org/openide/util/lookup/AbstractLookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1467 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util.lookup; - -import java.io.PrintStream; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; - -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import java.util.concurrent.Executor; -import org.netbeans.modules.openide.util.ActiveQueue; - - -/** Implementation of the lookup from OpenAPIs that is based on the - * introduction of Item. This class should provide the default way - * of how to store (Class, Object) pairs in the lookups. It offers - * protected methods for subclasses to register the pairs. - *

Serializable since 3.27. - * @author Jaroslav Tulach - * @since 1.9 - */ -public class AbstractLookup extends Lookup implements Serializable { - static final long serialVersionUID = 5L; - - /** lock for initialization of the maps of lookups */ - private static final Object treeLock = new Object(); - - /** the tree that registers all items (or Integer as a treshold size) */ - private Object tree; - - /** count of items in to lookup */ - private int count; - - /** Constructor to create this lookup and associate it with given - * Content. The content than allows the creator to invoke protected - * methods which are not accessible for any other user of the lookup. - * - * @param content the content to assciate with - * - * @since 1.25 - */ - public AbstractLookup(Content content) { - content.attach(this); - } - - /** Constructor for testing purposes that allows specification of storage - * as mechanism as well. - */ - AbstractLookup(Content content, Storage storage) { - this(content); - this.tree = storage; - initialize(); - } - - /** Constructor for testing purposes that allows specification of storage - * as mechanism as well. - * @param trashhold number of Pair to "remain small" - */ - AbstractLookup(Content content, Integer trashhold) { - this(content); - this.tree = trashhold; - } - - /** Default constructor for subclasses that do not need to provide a content - */ - protected AbstractLookup() { - } - - @Override - public String toString() { - if (tree instanceof Storage) { - return "AbstractLookup" + lookup(new Lookup.Template(Object.class)).allItems(); // NOI18N - } else { - return super.toString(); - } - } - - /** Entres the storage management system. - */ - @SuppressWarnings("unchecked") - private AbstractLookup.Storage enterStorage() { - for (;;) { - synchronized (treeLock) { - if (tree instanceof AbstractLookup.Storage) { - if (tree instanceof DelegatingStorage) { - // somebody is using the lookup right now - DelegatingStorage del = (DelegatingStorage) tree; - - // check whether there is not access from the same - // thread (can throw exception) - del.checkForTreeModification(); - - try { - treeLock.wait(); - } catch (InterruptedException ex) { - // ignore and go on - } - - continue; - } else { - // ok, tree is initialized and nobody is using it yet - tree = new DelegatingStorage((Storage) tree); - - return (Storage) tree; - } - } - - // first time initialization of the tree - if (tree instanceof Integer) { - tree = new ArrayStorage((Integer) tree); - } else { - tree = new ArrayStorage(); - } - } - - // the tree has not yet been initilized, initialize and go on again - initialize(); - } - } - - /** Exists tree ownership. - */ - private AbstractLookup.Storage exitStorage() { - synchronized (treeLock) { - AbstractLookup.Storage stor = ((DelegatingStorage) tree).exitDelegate(); - tree = stor; - treeLock.notifyAll(); - - return stor; - } - } - - /** Method for subclasses to initialize them selves. - */ - protected void initialize() { - } - - /** Notifies subclasses that a query is about to be processed. - * @param template the template - */ - protected void beforeLookup(Template template) { - } - - /** The method to add instance to the lookup with. - * @param pair class/instance pair - */ - protected final void addPair(Pair pair) { - addPairImpl(pair, null); - } - - /** The method to add instance to the lookup with. - * @param pair class/instance pair - * @param notifyIn the executor that will handle the notification of events - * @since 7.16 - */ - protected final void addPair(Pair pair, Executor notifyIn) { - addPairImpl(pair, notifyIn); - } - - private final void addPairImpl(Pair pair, Executor notifyIn) { - HashSet toNotify = new HashSet(); - - AbstractLookup.Storage t = enterStorage(); - Transaction transaction = null; - - try { - transaction = t.beginTransaction(-2); - - if (t.add(pair, transaction)) { - try { - pair.setIndex(t, count++); - } catch (IllegalStateException ex) { - // remove the pair - t.remove(pair, transaction); - - // rethrow the exception - throw ex; - } - - // if the pair is newly added and was not there before - t.endTransaction(transaction, toNotify); - } else { - // just finish the process by calling endTransaction - t.endTransaction(transaction, new HashSet()); - } - } finally { - exitStorage(); - } - - notifyIn(notifyIn, toNotify); - } - - /** Remove instance. - * @param pair class/instance pair - */ - protected final void removePair(Pair pair) { - removePairImpl(pair, null); - } - /** Remove instance. - * @param pair class/instance pair - * @param notifyIn the executor that will handle the notification of events - * @since 7.16 - */ - protected final void removePair(Pair pair, Executor notifyIn) { - removePairImpl(pair, notifyIn); - } - - private void removePairImpl(Pair pair, Executor notifyIn) { - HashSet toNotify = new HashSet(); - - AbstractLookup.Storage t = enterStorage(); - Transaction transaction = null; - - try { - transaction = t.beginTransaction(-1); - t.remove(pair, transaction); - t.endTransaction(transaction, toNotify); - } finally { - exitStorage(); - } - - notifyIn(notifyIn, toNotify); - } - - /** Changes all pairs in the lookup to new values. - * @param collection the collection of (Pair) objects - */ - protected final void setPairs(Collection collection) { - setPairs(collection, null); - } - - /** Changes all pairs in the lookup to new values, notifies listeners - * using provided executor. - * - * @param collection the collection of (Pair) objects - * @param notifyIn the executor that will handle the notification of events - * @since 7.16 - */ - protected final void setPairs(Collection collection, Executor notifyIn) { - HashSet listeners = setPairsAndCollectListeners(collection); - notifyIn(notifyIn, listeners); - } - - private final void notifyIn(Executor notifyIn, final HashSet listeners) { - NotifyListeners notify = new NotifyListeners(listeners); - if (notify.shallRun()) { - if (notifyIn == null) { - notify.run(); - } else { - notifyIn.execute(notify); - } - } - } - - /** Getter for set of pairs. Package private contract with MetaInfServicesLookup. - * @return a LinkedHashSet that can be modified - */ - final LinkedHashSet> getPairsAsLHS() { - AbstractLookup.Storage t = enterStorage(); - - try { - Enumeration> en = t.lookup(Object.class); - TreeSet> arr = new TreeSet>(ALPairComparator.DEFAULT); - while (en.hasMoreElements()) { - Pair item = en.nextElement(); - arr.add(item); - } - return new LinkedHashSet>(arr); - } finally { - exitStorage(); - } - } - - /** Collects listeners without notification. Needed in MetaInfServicesLookup - * right now, but maybe will become an API later. - */ - final HashSet setPairsAndCollectListeners(Collection collection) { - HashSet toNotify = new HashSet(27); - - AbstractLookup.Storage t = enterStorage(); - Transaction transaction = null; - - try { - // map between the Items and their indexes (Integer) - HashMap,Info> shouldBeThere = new HashMap,Info>(collection.size() * 2); - - count = 0; - - Iterator it = collection.iterator(); - transaction = t.beginTransaction(collection.size()); - - while (it.hasNext()) { - Pair item = (Pair) it.next(); - - if (t.add(item, transaction)) { - // the item has not been there yet - //t.endTransaction(transaction, toNotify); - } - - // remeber the item, because it should not be removed - shouldBeThere.put(item, new Info(count++, transaction)); - - // arr.clear (); - } - - // Object transaction = t.beginTransaction (); - // deletes all objects that should not be there and - t.retainAll(shouldBeThere, transaction); - - // collect listeners - t.endTransaction(transaction, toNotify); - - /* - // check consistency - Enumeration en = t.lookup (java.lang.Object.class); - boolean[] max = new boolean[count]; - int mistake = -1; - while (en.hasMoreElements ()) { - Pair item = (Pair)en.nextElement (); - - if (max[item.index]) { - mistake = item.index; - } - max[item.index] = true; - } - - if (mistake != -1) { - System.err.println ("Mistake at: " + mistake); - tree.print (System.err, true); - } - */ - } finally { - exitStorage(); - } - - return toNotify; - } - - private final void writeObject(ObjectOutputStream oos) - throws IOException { - AbstractLookup.Storage s = enterStorage(); - - try { - // #36830: Serializing only InheritanceTree no ArrayStorage - s.beginTransaction(Integer.MAX_VALUE); - - // #32040: don't write half-made changes - oos.defaultWriteObject(); - } finally { - exitStorage(); - } - } - - public final T lookup(Class clazz) { - Lookup.Item item = lookupItem(new Lookup.Template(clazz)); - return (item == null) ? null : item.getInstance(); - } - - @Override - public final Lookup.Item lookupItem(Lookup.Template template) { - AbstractLookup.this.beforeLookup(template); - - ArrayList> list = null; - AbstractLookup.Storage t = enterStorage(); - - try { - Enumeration> en; - - try { - en = t.lookup(template.getType()); - - return findSmallest(en, template, false); - } catch (AbstractLookup.ISE ex) { - // not possible to enumerate the exception, ok, copy it - // to create new - list = new ArrayList>(); - en = t.lookup(null); // this should get all the items without any checks - - // the checks will be done out side of the storage - while (en.hasMoreElements()) { - list.add(en.nextElement()); - } - } - } finally { - exitStorage(); - } - - return findSmallest(Collections.enumeration(list), template, true); - } - - private static Pair findSmallest(Enumeration> en, Lookup.Template template, boolean deepCheck) { - int smallest = InheritanceTree.unsorted(en) ? Integer.MAX_VALUE : Integer.MIN_VALUE; - Pair res = null; - - while (en.hasMoreElements()) { - Pair item = en.nextElement(); - - if (matches(template, item, deepCheck)) { - if (smallest == Integer.MIN_VALUE) { - // ok, sorted enumeration the first that matches is fine - return item; - } else { - // check for the smallest item - if (smallest > item.getIndex()) { - smallest = item.getIndex(); - res = item; - } - } - } - } - - return res; - } - - public final Lookup.Result lookup(Lookup.Template template) { - for (;;) { - AbstractLookup.ISE toRun = null; - - AbstractLookup.Storage t = enterStorage(); - - try { - R r = new R(); - ReferenceToResult newRef = new ReferenceToResult(r, this, template); - newRef.next = t.registerReferenceToResult(newRef); - - return r; - } catch (AbstractLookup.ISE ex) { - toRun = ex; - } finally { - exitStorage(); - } - - toRun.recover(this); - - // and try again - } - } - - /** Notifies listeners. - * @param allAffectedResults set of R - */ - static final class NotifyListeners implements Runnable { - private final ArrayList evAndListeners; - - public NotifyListeners(Set allAffectedResults) { - if (allAffectedResults.isEmpty()) { - evAndListeners = null; - return; - } - - evAndListeners = new ArrayList(); - { - for (R result : allAffectedResults) { - result.collectFires(evAndListeners); - } - } - } - - public boolean shallRun() { - return evAndListeners != null && !evAndListeners.isEmpty(); - } - - public void run() { - Iterator it = evAndListeners.iterator(); - while (it.hasNext()) { - LookupEvent ev = (LookupEvent)it.next(); - LookupListener l = (LookupListener)it.next(); - l.resultChanged(ev); - } - } - } - - /** - * Call resultChanged on all listeners. - * @param listeners array of listeners in the format used by - * javax.swing.EventListenerList. It means that there are Class - * objects on even positions and the listeners on odd positions - * @param ev the event to fire - */ - static void notifyListeners(Object[] listeners, LookupEvent ev, Collection evAndListeners) { - for (int i = listeners.length - 1; i >= 0; i--) { - if (! (listeners[i] instanceof LookupListener)) { - continue; - } - LookupListener ll = (LookupListener)listeners[i]; - - try { - if (evAndListeners != null) { - if (ll instanceof WaitableResult) { - WaitableResult wr = (WaitableResult)ll; - wr.collectFires(evAndListeners); - } else { - evAndListeners.add(ev); - evAndListeners.add(ll); - } - } else { - ll.resultChanged(ev); - } - } catch (StackOverflowError err) { - throw new CycleError(evAndListeners); // NOI18N - } catch (RuntimeException e) { - // Such as e.g. occurred in #32040. Do not halt other things. - e.printStackTrace(); - } - } - } - - private static class CycleError extends StackOverflowError { - private final Collection print; - public CycleError(Collection evAndListeners) { - this.print = evAndListeners; - } - - @Override - public String getMessage() { - StringBuilder sb = new StringBuilder(); - sb.append("StackOverflowError, here are the listeners:\n"); // NOI18N - for (Object o : print) { - sb.append('\n').append(o); - if (sb.length() > 10000) { - break; - } - } - return sb.toString(); - } - } // end of CycleError - - /** A method that defines matching between Item and Template. - * @param t template providing the criteria - * @param item the item to match - * @param deepCheck true if type of the pair should be tested, false if it is already has been tested - * @return true if item matches the template requirements, false if not - */ - static boolean matches(Template t, Pair item, boolean deepCheck) { - String id = t.getId(); - - if (id != null && !id.equals(item.getId())) { - return false; - } - - Object instance = t.getInstance(); - - if ((instance != null) && !item.creatorOf(instance)) { - return false; - } - - if (deepCheck) { - return item.instanceOf(t.getType()); - } else { - return true; - } - } - - /** - * Compares the array elements for equality. - * @return true if all elements in the arrays are equal - * (by calling equals(Object x) method) - */ - private static boolean compareArrays(Object[] a, Object[] b) { - // handle null values - if (a == null) { - return (b == null); - } else { - if (b == null) { - return false; - } - } - - if (a.length != b.length) { - return false; - } - - for (int i = 0; i < a.length; i++) { - // handle null values for individual elements - if (a[i] == null) { - if (b[i] != null) { - return false; - } - - // both are null --> ok, take next - continue; - } else { - if (b[i] == null) { - return false; - } - } - - // perform the comparison - if (!a[i].equals(b[i])) { - return false; - } - } - - return true; - } - - /** Method to be called when a result is cleared to signal that the list - * of all result should be checked for clearing. - * @param template the template the result was for - * @return true if the hash map with all items has been cleared - */ - boolean cleanUpResult(Lookup.Template template) { - AbstractLookup.Storage t = enterStorage(); - - try { - return t.cleanUpResult(template) == null; - } finally { - exitStorage(); - } - } - - /** Storage check for tests. */ - static boolean isSimple(AbstractLookup l) { - return DelegatingStorage.isSimple((Storage)l.tree); - } - - /** Generic support for listeners, so it can be used in other results - * as well. - * @param add true to add it, false to modify - * @param l listener to modify - * @param ref the value of the reference to listener or listener list - * @return new value to the reference to listener or list - */ - @SuppressWarnings("unchecked") - static Object modifyListenerList(boolean add, LookupListener l, Object ref) { - if (add) { - if (ref == null) { - return l; - } - - if (ref instanceof LookupListener) { - ArrayList arr = new ArrayList(); - arr.add(ref); - ref = arr; - } - - ((ArrayList) ref).add(l); - - return ref; - } else { - // remove - if (ref == null) { - return null; - } - - if (ref == l) { - return null; - } - - ArrayList arr = (ArrayList) ref; - arr.remove(l); - - if (arr.size() == 1) { - return arr.iterator().next(); - } else { - return arr; - } - } - } - - private static ReferenceQueue activeQueue() { - return ActiveQueue.queue(); - } - - /** Storage to keep the internal structure of Pairs and to answer - * different queries. - */ - interface Storage { - /** Initializes a modification operation by creating an object - * that will be passsed to all add, remove, retainAll methods - * and should collect enough information about the change to - * notify listeners about the transaction later - * - * @param ensure the amount of items that will appear in the storage - * after the modifications (-1 == remove one, -2 == add one, >= 0 - * the amount of objects at the end - * @return a token to identify the transaction - */ - public Transaction beginTransaction(int ensure); - - /** Collects all affected results R that were modified in the - * given transaction. - * - * @param modified place to add results R to - * @param transaction the transaction indentification - */ - public void endTransaction(Transaction transaction, Set modifiedResults); - - /** Adds an item into the storage. - * @param item to add - * @param transaction transaction token - * @return true if the Item has been added for the first time or false if some other - * item equal to this one already existed in the lookup - */ - public boolean add(AbstractLookup.Pair item, Transaction transaction); - - /** Removes an item. - */ - public void remove(AbstractLookup.Pair item, Transaction transaction); - - /** Removes all items that are not present in the provided collection. - * @param retain collection of Pairs to keep them in - * @param transaction the transaction context - */ - public void retainAll(Map retain, Transaction transaction); - - /** Queries for instances of given class. - * @param clazz the class to check - * @return enumeration of Item - * @see #unsorted - */ - public Enumeration> lookup(Class clazz); - - /** Registers another reference to a result with the storage. This method - * has also a special meaning. - * - * @param newRef the new reference to remember - * @return the previous reference that was kept (null if newRef is the first one) - * the applications is expected to link from newRef to this returned - * value to form a linked list - */ - public ReferenceToResult registerReferenceToResult(ReferenceToResult newRef); - - /** Given the provided template, Do cleanup the results. - * @param templ template of a result(s) that should be checked - * @return null if all references for this template were cleared or one of them - */ - public ReferenceToResult cleanUpResult(Lookup.Template templ); - } - - /** Extension to the default lookup item that offers additional information - * for the data structures use in AbstractLookup - */ - public static abstract class Pair extends Lookup.Item implements Serializable { - private static final long serialVersionUID = 1L; - - /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */ - private int index = -1; - - /** For use by subclasses. */ - protected Pair() { - } - - final int getIndex() { - return index; - } - - final void setIndex(AbstractLookup.Storage tree, int x) { - if (tree == null) { - this.index = x; - - return; - } - - if (this.index == -1) { - this.index = x; - } else { - throw new IllegalStateException("You cannot use " + this + " in more than one AbstractLookup. Prev: " + this.index + " new: " + x); // NOI18N - } - } - - /** Tests whether this item can produce object - * of class c. - */ - protected abstract boolean instanceOf(Class c); - - /** Method that can test whether an instance of a class has been created - * by this item. - * - * @param obj the instance - * @return if the item has already create an instance and it is the same - * as obj. - */ - protected abstract boolean creatorOf(Object obj); - } - - /** Result based on one instance returned. - */ - static final class R extends WaitableResult { - /** reference our result is attached to (do not modify) */ - public ReferenceToResult reference; - - /** listeners on the results or pointer to one listener */ - private Object listeners; - - public R() { - } - - /** Checks whether we have simple behaviour of complex. - */ - private boolean isSimple() { - Storage s = (Storage) reference.lookup.tree; - - return DelegatingStorage.isSimple(s); - } - - // - // Handling cache management for both cases, no caches - // for simple (but mark that we needed them, so refresh can - // be done in cloneList) and complex when all 3 types - // of result are cached - // - private Object getFromCache(int indx) { - if (isSimple()) { - return null; - } - - Object maybeArray = reference.caches; - - if (maybeArray instanceof Object[]) { - return ((Object[]) maybeArray)[indx]; - } - - return null; - } - - @SuppressWarnings("unchecked") - private Set> getClassesCache() { - return (Set>) getFromCache(0); - } - - private void setClassesCache(Set s) { - if (isSimple()) { - // mark it as being used - reference.caches = reference; - - return; - } - - if (!(reference.caches instanceof Object[])) { - reference.caches = new Object[3]; - } - - ((Object[]) reference.caches)[0] = s; - } - - @SuppressWarnings("unchecked") - private Collection getInstancesCache() { - return (Collection) getFromCache(1); - } - - private void setInstancesCache(Collection c) { - if (isSimple()) { - // mark it as being used - reference.caches = reference; - - return; - } - - if (!(reference.caches instanceof Object[])) { - reference.caches = new Object[3]; - } - - ((Object[]) reference.caches)[1] = c; - } - - @SuppressWarnings("unchecked") - private Pair[] getItemsCache() { - return (Pair[]) getFromCache(2); - } - - private void setItemsCache(Collection c) { - if (isSimple()) { - // mark it as being used - reference.caches = reference; - - return; - } - - if (!(reference.caches instanceof Object[])) { - reference.caches = new Object[3]; - } - - ((Object[]) reference.caches)[2] = c.toArray(new Pair[0]); - } - - private void clearCaches() { - if (reference.caches instanceof Object[]) { - reference.caches = new Object[3]; - } - } - - /** Ok, register listeners to all classes and super classes. - */ - public synchronized void addLookupListener(LookupListener l) { - listeners = modifyListenerList(true, l, listeners); - } - - /** Ok, register listeners to all classes and super classes. - */ - public synchronized void removeLookupListener(LookupListener l) { - listeners = modifyListenerList(false, l, listeners); - } - - /** Delete all cached values, the template changed. - */ - protected void collectFires(Collection evAndListeners) { - Object[] previousItems = getItemsCache(); - clearCaches(); - - if (previousItems != null) { - Object[] newArray = allItemsWithoutBeforeLookup().toArray(); - - if (compareArrays(previousItems, newArray)) { - // do not fire any change if nothing has been changed - return; - } - } - - LookupListener[] arr; - - synchronized (this) { - if (listeners == null) { - return; - } - - if (listeners instanceof LookupListener) { - arr = new LookupListener[] { (LookupListener) listeners }; - } else { - ArrayList l = (ArrayList) listeners; - arr = l.toArray(new LookupListener[l.size()]); - } - } - - final LookupListener[] ll = arr; - final LookupEvent ev = new LookupEvent(this); - notifyListeners(ll, ev, evAndListeners); - } - - public Collection allInstances() { - reference.lookup.beforeLookup(reference.template); - - Collection s = getInstancesCache(); - - if (s != null) { - return s; - } - - Collection> items = allItemsWithoutBeforeLookup(); - ArrayList list = new ArrayList(items.size()); - - Iterator> it = items.iterator(); - - while (it.hasNext()) { - Pair item = it.next(); - T obj = item.getInstance(); - - if (reference.template.getType().isInstance(obj)) { - list.add(obj); - } - } - - s = Collections.unmodifiableList(list); - setInstancesCache(s); - - return s; - } - - /** Set of all classes. - * - */ - @Override - public Set> allClasses() { - reference.lookup.beforeLookup(reference.template); - - Set> s = getClassesCache(); - - if (s != null) { - return s; - } - - s = new HashSet>(); - - for (Pair item : allItemsWithoutBeforeLookup()) { - Class clazz = item.getType(); - - if (clazz != null) { - s.add(clazz); - } - } - - s = Collections.unmodifiableSet(s); - setClassesCache(s); - - return s; - } - - /** Items are stored directly in the allItems. - */ - @Override - public Collection> allItems() { - reference.lookup.beforeLookup(reference.template); - - return allItemsWithoutBeforeLookup(); - } - - /** Implements the search for allItems, but without asking for before lookup */ - private Collection> allItemsWithoutBeforeLookup() { - Pair[] c = getItemsCache(); - - if (c != null) { - return Collections.unmodifiableList(Arrays.asList(c)); - } - - ArrayList> saferCheck = null; - AbstractLookup.Storage t = reference.lookup.enterStorage(); - - try { - try { - return Collections.unmodifiableCollection(initItems(t)); - } catch (AbstractLookup.ISE ex) { - // do less effective evaluation of items outside of the - // locked storage - saferCheck = new ArrayList>(); - - Enumeration> en = t.lookup(null); // get all Pairs - - while (en.hasMoreElements()) { - Pair i = en.nextElement(); - saferCheck.add(i); - } - } - } finally { - reference.lookup.exitStorage(); - } - return extractPairs(saferCheck); - } - - @SuppressWarnings("unchecked") - private Collection> extractPairs(final ArrayList> saferCheck) { - TreeSet> items = new TreeSet>(ALPairComparator.DEFAULT); - for (Pair i : saferCheck) { - if (matches(reference.template, i, false)) { - items.add((Pair)i); - } - } - return Collections.unmodifiableCollection(items); - } - - /** Initializes items. - */ - private Collection> initItems(Storage t) { - // manipulation with the tree must be synchronized - Enumeration> en = t.lookup(reference.template.getType()); - - // InheritanceTree is comparator for AbstractLookup.Pairs - TreeSet> items = new TreeSet>(ALPairComparator.DEFAULT); - - while (en.hasMoreElements()) { - Pair i = en.nextElement(); - - if (matches(reference.template, i, false)) { - items.add(i); - } - } - - // create a correctly sorted copy using the tree as the comparator - setItemsCache(items); - - return items; - } - - /** Used by proxy results to synchronize before lookup. - */ - protected void beforeLookup(Lookup.Template t) { - if (t.getType() == reference.template.getType()) { - reference.lookup.beforeLookup(t); - } - } - - /* Do not need to implement it, the default way is ok. - public boolean equals(java.lang.Object obj) { - return obj == this; - } - */ - @Override - public String toString() { - return super.toString() + " for " + reference.template; - } - } - // end of R - - /** A class that can be used by the creator of the AbstractLookup to - * control its content. It can be passed to AbstractLookup constructor - * and used to add and remove pairs. - * - * @since 1.25 - */ - public static class Content extends Object implements Serializable { - private static final long serialVersionUID = 1L; - - // one of them is always null (except attach stage) - - /** abstract lookup we are connected to */ - private AbstractLookup al; - private transient Object notifyIn; - - /** Default constructor. - */ - public Content() { - this(null); - } - - /** Creates a content associated with an executor to handle dispatch - * of changes. - * @param notifyIn the executor to notify changes in - * @since 7.16 - */ - public Content(Executor notifyIn) { - this.notifyIn = notifyIn; - } - - /** for testing purposes */ - final void attachExecutor(Executor notifyIn) { - this.notifyIn = notifyIn; - } - - /** A lookup attaches to this object. - */ - final synchronized void attach(AbstractLookup al) { - if (this.al == null) { - this.al = al; - - ArrayList ep = getEarlyPairs(); - if (ep != null) { - notifyIn = null; - setPairs(ep); - } - } else { - throw new IllegalStateException( - "Trying to use content for " + al + " but it is already used for " + this.al - ); // NOI18N - } - } - - /** The method to add instance to the lookup with. - * @param pair class/instance pair - */ - public final void addPair(Pair pair) { - AbstractLookup a = al; - Executor e = getExecutor(); - - if (a != null || e != null) { - a.addPair(pair, e); - } else { - if (notifyIn == null) { - notifyIn = new ArrayList(3); - } - - getEarlyPairs().add(pair); - } - } - - /** Remove instance. - * @param pair class/instance pair - */ - public final void removePair(Pair pair) { - AbstractLookup a = al; - Executor e = getExecutor(); - - if (a != null || e != null) { - a.removePair(pair, e); - } else { - if (notifyIn == null) { - notifyIn = new ArrayList(3); - } - - getEarlyPairs().remove(pair); - } - } - - /** Changes all pairs in the lookup to new values. - * @param c the collection of (Pair) objects - */ - public final void setPairs(Collection c) { - AbstractLookup a = al; - Executor e = getExecutor(); - - if (a != null || e != null) { - a.setPairs(c, e); - } else { - notifyIn = new ArrayList(c); - } - } - - @SuppressWarnings("unchecked") - private ArrayList getEarlyPairs() { - Object o = notifyIn; - return o instanceof ArrayList ? (ArrayList)o : null; - } - - private Executor getExecutor() { - Object o = notifyIn; - return o instanceof Executor ? (Executor)o : null; - } - } - // end of Content - - /** Just a holder for index & modified values. - */ - final static class Info extends Object { - public int index; - public Object transaction; - - public Info(int i, Object t) { - index = i; - transaction = t; - } - } - - /** Reference to a result R - */ - static final class ReferenceToResult extends WeakReference> implements Runnable { - /** next refernece in chain, modified only from AbstractLookup or this */ - private ReferenceToResult next; - - /** the template for the result */ - public final Template template; - - /** the lookup we are attached to */ - public final AbstractLookup lookup; - - /** caches for results */ - public Object caches; - - /** Creates a weak refernece to a new result R in context of lookup - * for given template - */ - private ReferenceToResult(R result, AbstractLookup lookup, Template template) { - super(result, activeQueue()); - this.template = template; - this.lookup = lookup; - getResult().reference = this; - } - - /** Returns the result or null - */ - R getResult() { - return get(); - } - - /** Cleans the reference. Implements Runnable interface, do not call - * directly. - */ - public void run() { - lookup.cleanUpResult(this.template); - } - - /** Clones the reference list to given Storage. - * @param storage storage to clone to - */ - public void cloneList(AbstractLookup.Storage storage) { - ReferenceIterator it = new ReferenceIterator(this); - - while (it.next()) { - ReferenceToResult current = it.current(); - ReferenceToResult newRef = current.cloneRef(); - newRef.next = storage.registerReferenceToResult(newRef); - newRef.caches = current.caches; - - if (current.caches == current) { - current.getResult().initItems(storage); - } - } - } - - private ReferenceToResult cloneRef() { - return new ReferenceToResult(getResult(), lookup, template); - } - } - // end of ReferenceToResult - - /** Supporting class to iterate over linked list of ReferenceToResult - * Use: - *
-     *  ReferenceIterator it = new ReferenceIterator (this.ref);
-     *  while (it.next ()) {
-     *    it.current (): // do some work
-     *  }
-     *  this.ref = it.first (); // remember the first one
-     */
-    static final class ReferenceIterator extends Object {
-        private ReferenceToResult first;
-        private ReferenceToResult current;
-
-        /** hard reference to current result, so it is not GCed meanwhile */
-        private R currentResult;
-
-        /** Initializes the iterator with first reference.
-         */
-        public ReferenceIterator(ReferenceToResult first) {
-            this.first = first;
-        }
-
-        /** Moves the current to next possition */
-        public boolean next() {
-            ReferenceToResult prev;
-            ReferenceToResult ref;
-
-            if (current == null) {
-                ref = first;
-                prev = null;
-            } else {
-                prev = current;
-                ref = current.next;
-            }
-
-            while (ref != null) {
-                R result = ref.get();
-
-                if (result == null) {
-                    if (prev == null) {
-                        // move the head
-                        first = ref.next;
-                    } else {
-                        // skip over this reference
-                        prev.next = ref.next;
-                    }
-
-                    prev = ref;
-                    ref = ref.next;
-                } else {
-                    // we have found next item
-                    currentResult = result;
-                    current = ref;
-
-                    return true;
-                }
-            }
-
-            currentResult = null;
-            current = null;
-
-            return false;
-        }
-
-        /** Access to current reference.
-         */
-        public ReferenceToResult current() {
-            return current;
-        }
-
-        /** Access to reference that is supposed to be the first one.
-         */
-        public ReferenceToResult first() {
-            return first;
-        }
-    }
-
-    /** Signals that a lookup is being modified from a lookup query.
-     *
-     * @author  Jaroslav Tulach
-     */
-    static final class ISE extends IllegalStateException {
-        static final long serialVersionUID = 100L;
-        
-        /** list of jobs to execute. */
-        private java.util.List jobs;
-
-        /** @param msg message
-         */
-        public ISE(String msg) {
-            super(msg);
-        }
-
-        /** Registers a job to be executed partially out and partially in
-         * the lock over storage.
-         */
-        public void registerJob(Job job) {
-            if (jobs == null) {
-                jobs = new java.util.ArrayList();
-            }
-
-            jobs.add(job);
-        }
-
-        /** Executes the jobs outside, and then inside a locked session.
-         */
-        public void recover(AbstractLookup lookup) {
-            if (jobs == null) {
-                // no recovery plan, throw itself
-                throw this;
-            }
-
-            for (Job j : jobs) {
-                j.before();
-            }
-
-            AbstractLookup.Storage s = lookup.enterStorage();
-
-            try {
-                for (Job j : jobs) {
-                    j.inside();
-                }
-            } finally {
-                lookup.exitStorage();
-            }
-        }
-
-        /** A job to be executed partially outside and partially inside
-         * the storage lock.
-         */
-        static interface Job {
-            public void before();
-
-            public void inside();
-        }
-    }
-     // end of ISE
-}
diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/ArrayStorage.java
--- a/lookup/src/main/java/org/openide/util/lookup/ArrayStorage.java	Wed Jan 27 17:46:23 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,477 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common
- * Development and Distribution License("CDDL") (collectively, the
- * "License"). You may not use this file except in compliance with the
- * License. You can obtain a copy of the License at
- * http://www.netbeans.org/cddl-gplv2.html
- * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
- * specific language governing permissions and limitations under the
- * License.  When distributing the software, include this License Header
- * Notice in each file and include the License file at
- * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the GPL Version 2 section of the License file that
- * accompanied this code. If applicable, add the following below the
- * License Header, with the fields enclosed by brackets [] replaced by
- * your own identifying information:
- * "Portions Copyrighted [year] [name of copyright owner]"
- *
- * Contributor(s):
- *
- * The Original Software is NetBeans. The Initial Developer of the Original
- * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
- * Microsystems, Inc. All Rights Reserved.
- *
- * If you wish your version of this file to be governed by only the CDDL
- * or only the GPL Version 2, indicate your decision by adding
- * "[Contributor] elects to include this software in this distribution
- * under the [CDDL or GPL Version 2] license." If you do not indicate a
- * single choice of license, a recipient has the option to distribute
- * your version of this file under either the CDDL, the GPL Version 2 or
- * to extend the choice of license to its licensees as provided above.
- * However, if you add GPL Version 2 code and therefore, elected the GPL
- * Version 2 license, then the option applies only if the new code is
- * made subject to such option by the copyright holder.
- */
-package org.openide.util.lookup;
-
-import org.openide.util.Lookup;
-
-
-
-import java.util.*;
-import org.openide.util.lookup.AbstractLookup.Pair;
-
-
-/** ArrayStorage of Pairs from AbstractLookup.
- * @author  Jaroslav Tulach
- */
-final class ArrayStorage extends Object
-implements AbstractLookup.Storage {
-    /** default trashold */
-    static final Integer DEFAULT_TRASH = new Integer(11);
-
-    /** list of items */
-    private Object content;
-
-    /** linked list of refernces to results */
-    private transient AbstractLookup.ReferenceToResult results;
-
-    /** Constructor
-     */
-    public ArrayStorage() {
-        this(DEFAULT_TRASH);
-    }
-
-    /** Constructs new ArrayStorage */
-    public ArrayStorage(Integer treshhold) {
-        this.content = treshhold;
-    }
-
-    /** Adds an item into the tree.
-    * @param item to add
-    * @return true if the Item has been added for the first time or false if some other
-    *    item equal to this one already existed in the lookup
-    */
-    public boolean add(AbstractLookup.Pair item, Transaction changed) {
-        Object[] arr = changed.current;
-
-        if (changed.arr == null) {
-            // just simple add of one item
-            for (int i = 0; i < arr.length; i++) {
-                if (arr[i] == null) {
-                    arr[i] = item;
-                    changed.add(item);
-
-                    return true;
-                }
-
-                if (arr[i].equals(item)) {
-                    // reassign the item number
-                    item.setIndex(null, ((AbstractLookup.Pair) arr[i]).getIndex());
-
-                    // already there, but update it
-                    arr[i] = item;
-
-                    return false;
-                }
-            }
-
-            // cannot happen as the beginTransaction ensured we can finish 
-            // correctly
-            throw new IllegalStateException();
-        } else {
-            // doing remainAll after that, let Transaction hold the new array
-            int newIndex = changed.addPair(item);
-
-            for (int i = 0; i < arr.length; i++) {
-                if (arr[i] == null) {
-                    changed.add(item);
-
-                    return true;
-                }
-
-                if (arr[i].equals(item)) {
-                    // already there
-                    if (i != newIndex) {
-                        // change in index
-                        changed.add(item);
-
-                        return false;
-                    } else {
-                        // no change
-                        return false;
-                    }
-                }
-            }
-
-            // if not found in the original array
-            changed.add(item);
-
-            return true;
-        }
-    }
-
-    /** Removes an item.
-    */
-    public void remove(AbstractLookup.Pair item, Transaction changed) {
-        Object[] arr = changed.current;
-        if (arr == null) {
-            return;
-        }
-
-        int found = -1;
-
-        for (int i = 0; i < arr.length;) {
-            if (arr[i] == null) {
-                // end of task
-                return;
-            }
-
-            if ((found == -1) && arr[i].equals(item)) {
-                // already there
-                Pair p = (Pair)arr[i];
-                p.setIndex(null, -1);
-                changed.add(p);
-                found = i;
-            }
-
-            i++;
-
-            if (found != -1) {
-                if (i < arr.length && !(arr[i] instanceof Integer)) {
-                    // moving the array
-                    arr[i - 1] = arr[i];
-                } else {
-                    arr[i - 1] = null;
-                }
-            }
-        }
-    }
-
-    /** Removes all items that are not present in the provided collection.
-    * @param retain Pair -> AbstractLookup.Info map
-    * @param notify set of Classes that has possibly changed
-    */
-    public void retainAll(Map retain, Transaction changed) {
-        Object[] arr = changed.current;
-
-        for (int from = 0; from < arr.length; from++) {
-            if (!(arr[from] instanceof AbstractLookup.Pair)) {
-                // end of content
-                break;
-            }
-
-            AbstractLookup.Pair p = (AbstractLookup.Pair) arr[from];
-
-            AbstractLookup.Info info = (AbstractLookup.Info) retain.get(p);
-
-            if (info == null) {
-                // was removed
-
-                /*
-                if (info != null) {
-                if (info.index < arr.length) {
-                    newArr[info.index] = p;
-                }
-
-                if (p.getIndex() != info.index) {
-                    p.setIndex (null, info.index);
-                    changed.add (p);
-                }
-                } else {
-                // removed
-                 */
-                changed.add(p);
-            }
-        }
-    }
-
-    /** Queries for instances of given class.
-    * @param clazz the class to check
-    * @return enumeration of Item
-    * @see #unsorted
-    */
-    public  Enumeration> lookup(final Class clazz) {
-        if (content instanceof Object[]) {
-            final Enumeration all = InheritanceTree.arrayEn((Object[]) content);
-            class JustPairs implements Enumeration> {
-                private Pair next;
-
-                @SuppressWarnings("unchecked")
-                private Pair findNext() {
-                    for (;;) {
-                        if (next != null) {
-                            return next;
-                        }
-                        if (!all.hasMoreElements()) {
-                            return null;
-                        }
-                        Object o = all.nextElement();
-                        boolean ok;
-                        if (o instanceof AbstractLookup.Pair) {
-                            ok = (clazz == null) || ((AbstractLookup.Pair) o).instanceOf(clazz);
-                        } else {
-                            ok = false;
-                        }
-
-                        next = ok ? (Pair) o : null;
-                    }
-                }
-                
-                public boolean hasMoreElements() {
-                    return findNext() != null;
-                }
-
-                public Pair nextElement() {
-                    Pair r = findNext();
-                    if (r == null) {
-                        throw new NoSuchElementException();
-                    }
-                    next = null;
-                    return r;
-                }
-            } // end of JustPairs
-            return new JustPairs();
-        } else {
-            return InheritanceTree.emptyEn();
-        }
-    }
-
-    /** Associates another result with this storage.
-     */
-    public AbstractLookup.ReferenceToResult registerReferenceToResult(AbstractLookup.ReferenceToResult newRef) {
-        AbstractLookup.ReferenceToResult prev = this.results;
-        this.results = newRef;
-
-        return prev;
-    }
-
-    /** Cleanup the references
-     */
-    public AbstractLookup.ReferenceToResult cleanUpResult(Lookup.Template templ) {
-        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
-
-        while (it.next()) {
-            // empty
-        }
-
-        return this.results = it.first();
-    }
-
-    /** We use a hash set of all modified Pair to handle the transaction */
-    public Transaction beginTransaction(int ensure) {
-        return new Transaction(ensure, content);
-    }
-
-    /** Extract all results.
-     */
-    public void endTransaction(Transaction changed, Set modified) {
-        AbstractLookup.ReferenceIterator it = new AbstractLookup.ReferenceIterator(this.results);
-
-        if (changed.arr == null) {
-            // either add or remove, only check the content of check HashSet
-            while (it.next()) {
-                AbstractLookup.ReferenceToResult ref = it.current();
-                Iterator> pairs = changed.iterator();
-
-                while (pairs.hasNext()) {
-                    AbstractLookup.Pair p = (AbstractLookup.Pair) pairs.next();
-
-                    if (AbstractLookup.matches(ref.template, p, true)) {
-                        modified.add(ref.getResult());
-                    }
-                }
-            }
-        } else {
-            // do full check of changes
-            while (it.next()) {
-                AbstractLookup.ReferenceToResult ref = it.current();
-
-                int oldIndex = -1;
-                int newIndex = -1;
-
-                for (;;) {
-                    oldIndex = findMatching(ref.template, changed.current, oldIndex);
-                    newIndex = findMatching(ref.template, changed.arr, newIndex);
-
-                    if ((oldIndex == -1) && (newIndex == -1)) {
-                        break;
-                    }
-
-                    if (
-                        (oldIndex == -1) || (newIndex == -1) ||
-                            !changed.current[oldIndex].equals(changed.arr[newIndex])
-                    ) {
-                        modified.add(ref.getResult());
-
-                        break;
-                    }
-                }
-            }
-        }
-
-        this.results = it.first();
-        this.content = changed.newContent(this.content);
-    }
-
-    private static int findMatching(Lookup.Template t, Object[] arr, int from) {
-        while (++from < arr.length) {
-            if (arr[from] instanceof AbstractLookup.Pair) {
-                if (AbstractLookup.matches(t, (AbstractLookup.Pair) arr[from], true)) {
-                    return from;
-                }
-            }
-        }
-
-        return -1;
-    }
-
-    /** HashSet with additional field for new array which is callocated
-     * in case we are doing replace to hold all new items.
-     */
-    static final class Transaction extends HashSet> {
-        /** array with current objects */
-        public final Object[] current;
-
-        /** array with new objects */
-        public final Object[] arr;
-
-        /** number of objects in the array */
-        private int cnt;
-
-        public Transaction(int ensure, Object currentContent) {
-            Integer trashold;
-            Object[] _arr;
-
-            if (currentContent instanceof Integer) {
-                trashold = (Integer) currentContent;
-                _arr = null;
-            } else {
-                _arr = (Object[]) currentContent;
-
-                if (_arr[_arr.length - 1] instanceof Integer) {
-                    trashold = (Integer) _arr[_arr.length - 1];
-                } else {
-                    // nowhere to grow we have reached the limit
-                    trashold = null;
-                }
-            }
-
-            int maxSize = (trashold == null) ? _arr.length : trashold.intValue();
-
-            if (ensure > maxSize) {
-                throw new UnsupportedOperationException();
-            }
-
-            if (ensure == -1) {
-                // remove => it is ok
-                this.current = currentContent instanceof Integer ? null : (Object[]) currentContent;
-                this.arr = null;
-
-                return;
-            }
-
-            if (ensure == -2) {
-                // adding one
-                if (_arr == null) {
-                    // first time add, let's allocate the array
-                    _arr = new Object[2];
-                    _arr[1] = trashold;
-                } else {
-                    if (_arr[_arr.length - 1] instanceof AbstractLookup.Pair) {
-                        // we are full
-                        throw new UnsupportedOperationException();
-                    } else {
-                        // ensure we have allocated enough space
-                        if (_arr.length < 2 || _arr[_arr.length - 2] != null) {
-                            // double the array
-                            int newSize = (_arr.length - 1) * 2;
-                            
-                            if (newSize <= 1) {
-                                newSize = 2;
-                            }
-
-                            if (newSize > maxSize) {
-                                newSize = maxSize;
-
-                                if (newSize <= _arr.length) {
-                                    // no space to get in
-                                    throw new UnsupportedOperationException();
-                                }
-
-                                _arr = new Object[newSize];
-                            } else {
-                                // still a lot of space
-                                _arr = new Object[newSize + 1];
-                                _arr[newSize] = trashold;
-                            }
-
-                            // copy content of original array without the last Integer into 
-                            // the new one
-                            System.arraycopy(currentContent, 0, _arr, 0, ((Object[]) currentContent).length - 1);
-                        }
-                    }
-                }
-
-                this.current = _arr;
-                this.arr = null;
-            } else {
-                // allocate array for complete replacement
-                if (ensure == maxSize) {
-                    this.arr = new Object[ensure];
-                } else {
-                    this.arr = new Object[ensure + 1];
-                    this.arr[ensure] = trashold;
-                }
-
-                this.current = (currentContent instanceof Object[]) ? (Object[]) currentContent : new Object[0];
-            }
-        }
-
-        public int addPair(AbstractLookup.Pair p) {
-            p.setIndex(null, cnt);
-            arr[cnt++] = p;
-
-            return p.getIndex();
-        }
-
-        public Object newContent(Object prev) {
-            if (arr == null) {
-                if (current == null) {
-                    return prev;
-                } else {
-                    return current;
-                }
-            } else {
-                return arr;
-            }
-        }
-    }
-     // end of Transaction
-}
diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/Bundle.properties
--- a/lookup/src/main/java/org/openide/util/lookup/Bundle.properties	Wed Jan 27 17:46:23 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-OpenIDE-Module-Name=Lookup
diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/DelegatingStorage.java
--- a/lookup/src/main/java/org/openide/util/lookup/DelegatingStorage.java	Wed Jan 27 17:46:23 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common
- * Development and Distribution License("CDDL") (collectively, the
- * "License"). You may not use this file except in compliance with the
- * License. You can obtain a copy of the License at
- * http://www.netbeans.org/cddl-gplv2.html
- * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
- * specific language governing permissions and limitations under the
- * License.  When distributing the software, include this License Header
- * Notice in each file and include the License file at
- * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the GPL Version 2 section of the License file that
- * accompanied this code. If applicable, add the following below the
- * License Header, with the fields enclosed by brackets [] replaced by
- * your own identifying information:
- * "Portions Copyrighted [year] [name of copyright owner]"
- *
- * Contributor(s):
- *
- * The Original Software is NetBeans. The Initial Developer of the Original
- * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
- * Microsystems, Inc. All Rights Reserved.
- *
- * If you wish your version of this file to be governed by only the CDDL
- * or only the GPL Version 2, indicate your decision by adding
- * "[Contributor] elects to include this software in this distribution
- * under the [CDDL or GPL Version 2] license." If you do not indicate a
- * single choice of license, a recipient has the option to distribute
- * your version of this file under either the CDDL, the GPL Version 2 or
- * to extend the choice of license to its licensees as provided above.
- * However, if you add GPL Version 2 code and therefore, elected the GPL
- * Version 2 license, then the option applies only if the new code is
- * made subject to such option by the copyright holder.
- */
-package org.openide.util.lookup;
-
-import org.openide.util.Lookup;
-
-import java.io.*;
-
-import java.lang.ref.WeakReference;
-
-import java.util.*;
-import org.openide.util.lookup.AbstractLookup.Pair;
-
-
-/** Storages that can switch between another storages.
- * @author  Jaroslav Tulach
- */
-final class DelegatingStorage extends Object
-implements Serializable, AbstractLookup.Storage {
-    /** object to delegate to */
-    private AbstractLookup.Storage delegate;
-
-    /** thread just accessing the storage */
-    private Thread owner;
-
-    public DelegatingStorage(AbstractLookup.Storage d) {
-        this.delegate = d;
-        this.owner = Thread.currentThread();
-    }
-
-    /** Never serialize yourself, always put there the delegate */
-    public Object writeReplace() {
-        return this.delegate;
-    }
-
-    /** Method to check whether there is not multiple access from the same thread.
-     */
-    public void checkForTreeModification() {
-        if (Thread.currentThread() == owner) {
-            throw new AbstractLookup.ISE("You are trying to modify lookup from lookup query!"); // NOI18N
-        }
-    }
-
-    /** Checks whether we have simple behaviour or complex.
-     */
-    public static boolean isSimple(AbstractLookup.Storage s) {
-        if (s instanceof DelegatingStorage) {
-            return ((DelegatingStorage) s).delegate instanceof ArrayStorage;
-        } else {
-            return s instanceof ArrayStorage;
-        }
-    }
-
-    /** Exits from the owners ship of the storage.
-     */
-    public AbstractLookup.Storage exitDelegate() {
-        if (Thread.currentThread() != owner) {
-            throw new IllegalStateException("Onwer: " + owner + " caller: " + Thread.currentThread()); // NOI18N
-        }
-
-        AbstractLookup.Storage d = delegate;
-        delegate = null;
-
-        return d;
-    }
-
-    public boolean add(AbstractLookup.Pair item, Transaction transaction) {
-        return delegate.add(item, transaction);
-    }
-
-    public void remove(org.openide.util.lookup.AbstractLookup.Pair item, Transaction transaction) {
-        delegate.remove(item, transaction);
-    }
-
-    public void retainAll(Map retain, Transaction transaction) {
-        delegate.retainAll(retain, transaction);
-    }
-
-    /** A special method to change the backing storage.
-     * In fact it is not much typesafe as it changes the
-     * type of Transaction but we know that nobody is currently
-     * holding a transaction object, so there cannot be inconsitencies.
-     */
-    @SuppressWarnings("unchecked")
-    private void changeDelegate(InheritanceTree st) {
-        delegate = (AbstractLookup.Storage)st;
-    }
-
-    public Transaction beginTransaction(int ensure) {
-        try {
-            return delegate.beginTransaction(ensure);
-        } catch (UnsupportedOperationException ex) {
-            // let's convert to InheritanceTree
-            ArrayStorage arr = (ArrayStorage) delegate;
-            InheritanceTree inh = new InheritanceTree();
-            changeDelegate(inh);
-
-            //
-            // Copy content
-            //
-            Enumeration> en = arr.lookup(Object.class);
-
-            while (en.hasMoreElements()) {
-                if (!inh.add(en.nextElement(), new ArrayList())) {
-                    throw new IllegalStateException("All objects have to be accepted"); // NOI18N
-                }
-            }
-
-            //
-            // Copy listeners
-            //
-            AbstractLookup.ReferenceToResult ref = arr.cleanUpResult(null);
-
-            if (ref != null) {
-                ref.cloneList(inh);
-            }
-
-            // we have added the current content and now we can start transaction
-            return delegate.beginTransaction(ensure);
-        }
-    }
-
-    public org.openide.util.lookup.AbstractLookup.ReferenceToResult cleanUpResult(
-        org.openide.util.Lookup.Template templ
-    ) {
-        return delegate.cleanUpResult(templ);
-    }
-
-    public void endTransaction(Transaction transaction, Set modified) {
-        delegate.endTransaction(transaction, modified);
-    }
-
-    public  Enumeration> lookup(Class clazz) {
-        return delegate.lookup(clazz);
-    }
-
-    public org.openide.util.lookup.AbstractLookup.ReferenceToResult registerReferenceToResult(
-        org.openide.util.lookup.AbstractLookup.ReferenceToResult newRef
-    ) {
-        return delegate.registerReferenceToResult(newRef);
-    }
-}
diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/ExcludingLookup.java
--- a/lookup/src/main/java/org/openide/util/lookup/ExcludingLookup.java	Wed Jan 27 17:46:23 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,428 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common
- * Development and Distribution License("CDDL") (collectively, the
- * "License"). You may not use this file except in compliance with the
- * License. You can obtain a copy of the License at
- * http://www.netbeans.org/cddl-gplv2.html
- * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
- * specific language governing permissions and limitations under the
- * License.  When distributing the software, include this License Header
- * Notice in each file and include the License file at
- * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the GPL Version 2 section of the License file that
- * accompanied this code. If applicable, add the following below the
- * License Header, with the fields enclosed by brackets [] replaced by
- * your own identifying information:
- * "Portions Copyrighted [year] [name of copyright owner]"
- *
- * Contributor(s):
- *
- * The Original Software is NetBeans. The Initial Developer of the Original
- * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
- * Microsystems, Inc. All Rights Reserved.
- *
- * If you wish your version of this file to be governed by only the CDDL
- * or only the GPL Version 2, indicate your decision by adding
- * "[Contributor] elects to include this software in this distribution
- * under the [CDDL or GPL Version 2] license." If you do not indicate a
- * single choice of license, a recipient has the option to distribute
- * your version of this file under either the CDDL, the GPL Version 2 or
- * to extend the choice of license to its licensees as provided above.
- * However, if you add GPL Version 2 code and therefore, elected the GPL
- * Version 2 license, then the option applies only if the new code is
- * made subject to such option by the copyright holder.
- */
-package org.openide.util.lookup;
-
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import org.openide.util.Lookup;
-import org.openide.util.LookupListener;
-
-import java.util.*;
-import org.openide.util.LookupEvent;
-
-
-/** Allows exclusion of certain instances from lookup.
- *
- * @author Jaroslav Tulach
- */
-final class ExcludingLookup extends org.openide.util.Lookup {
-    /** the other lookup that we delegate to */
-    private Lookup delegate;
-
-    /** classes to exclude (Class[]) or just one class (Class) */
-    private Object classes;
-
-    /**
-     * Creates new Result object with supplied instances parameter.
-     * @param instances to be used to return from the lookup
-     */
-    ExcludingLookup(Lookup delegate, Class[] classes) {
-        this.delegate = delegate;
-
-        for (Class c : classes) {
-            if (c == null) {
-                throw new NullPointerException();
-            }
-        }
-        if (classes.length == 1) {
-            this.classes = classes[0];
-        } else {
-            this.classes = classes;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "ExcludingLookup: " + delegate + " excludes: " + Arrays.asList(classes()); // NOI18N
-    }
-
-    public  Result lookup(Template template) {
-        if (template == null) {
-            throw new NullPointerException();
-        }
-
-        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
-            // empty result
-            return Lookup.EMPTY.lookup(template);
-        }
-
-        return new R(template.getType(), delegate.lookup(template));
-    }
-
-    public  T lookup(Class clazz) {
-        if (areSubclassesOfThisClassAlwaysExcluded(clazz)) {
-            return null;
-        }
-
-        T res = delegate.lookup(clazz);
-
-        if (isObjectAccessible(clazz, res, 0)) {
-            return res;
-        } else {
-            return null;
-        }
-    }
-
-    @Override
-    public  Lookup.Item lookupItem(Lookup.Template template) {
-        if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) {
-            return null;
-        }
-
-        Lookup.Item retValue = delegate.lookupItem(template);
-
-        if (isObjectAccessible(template.getType(), retValue, 2)) {
-            return retValue;
-        } else {
-            return null;
-        }
-    }
-
-    /** @return true if the instance of class c shall never be returned from this lookup
-     */
-    private boolean areSubclassesOfThisClassAlwaysExcluded(Class c) {
-        Class[] arr = classes();
-
-        for (int i = 0; i < arr.length; i++) {
-            if (arr[i].isAssignableFrom(c)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /** Returns the array of classes this lookup filters.
-     */
-    final Class[] classes() {
-        if (classes instanceof Class[]) {
-            return (Class[]) classes;
-        } else {
-            return new Class[] { (Class) classes };
-        }
-    }
-
-    /** Does a check whether two classes are accessible (in the super/sub class)
-     * releation ship without walking thru any of the classes mentioned in the
-     * barrier.
-     */
-    private static boolean isAccessible(Class[] barriers, Class from, Class to) {
-        if ((to == null) || !from.isAssignableFrom(to)) {
-            // no way to reach each other by walking up
-            return false;
-        }
-
-        for (int i = 0; i < barriers.length; i++) {
-            if (to == barriers[i]) {
-                return false;
-            }
-        }
-
-        if (from == to) {
-            return true;
-        }
-
-        //
-        // depth first search
-        //
-        if (isAccessible(barriers, from, to.getSuperclass())) {
-            return true;
-        }
-
-        Class[] interfaces = to.getInterfaces();
-
-        for (int i = 0; i < interfaces.length; i++) {
-            if (isAccessible(barriers, from, interfaces[i])) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /** based on type decides whether the class accepts or not anObject
-     * @param from the base type of the query
-     * @param to depending on value of type either Object, Class or Item
-     * @param type 0,1,2 for Object, Class or Item
-     * @return true if we can access the to from from by walking around the bariers
-     */
-    private final boolean isObjectAccessible(Class from, Object to, int type) {
-        if (to == null) {
-            return false;
-        }
-
-        return isObjectAccessible(classes(), from, to, type);
-    }
-
-    /** based on type decides whether the class accepts or not anObject
-     * @param barriers classes to avoid when testing reachability
-     * @param from the base type of the query
-     * @param to depending on value of type either Object, Class or Item
-     * @param type 0,1,2 for Object, Class or Item
-     * @return true if we can access the to from from by walking around the bariers
-     */
-    static final boolean isObjectAccessible(Class[] barriers, Class from, Object to, int type) {
-        if (to == null) {
-            return false;
-        }
-
-        switch (type) {
-        case 0:
-            return isAccessible(barriers, from, to.getClass());
-
-        case 1:
-            return isAccessible(barriers, from, (Class) to);
-
-        case 2: {
-            Item item = (Item) to;
-
-            return isAccessible(barriers, from, item.getType());
-        }
-
-        default:
-            throw new IllegalStateException("Type: " + type);
-        }
-    }
-
-    /** Filters collection accroding to set of given filters.
-     */
-    final > T filter(
-        Class[] arr, Class from, T c, int type, T prototype
-    ) {
-        T ret = null;
-
-
-// optimistic strategy expecting we will not need to filter
-TWICE: 
-        for (;;) {
-            Iterator it = c.iterator();
-BIG: 
-            while (it.hasNext()) {
-                E res = it.next();
-
-                if (!isObjectAccessible(arr, from, res, type)) {
-                    if (ret == null) {
-                        // we need to restart the scanning again 
-                        // as there is an active filter
-                        ret = prototype;
-                        continue TWICE;
-                    }
-
-                    continue BIG;
-                }
-
-                if (ret != null) {
-                    // if we are running the second round from TWICE
-                    ret.add(res);
-                }
-            }
-
-            // ok, processed
-            break TWICE;
-        }
-
-        return (ret != null) ? ret : c;
-    }
-
-    /** Delegating result that filters unwanted items and instances.
-     */
-    private final class R extends WaitableResult implements LookupListener {
-        private Result result;
-        private WeakResult weak;
-        private Object listeners;
-        private Class from;
-
-        R(Class from, Result delegate) {
-            this.from = from;
-            this.result = delegate;
-            this.weak = new WeakResult(this, delegate);
-        }
-
-        protected void beforeLookup(Template t) {
-            if (result instanceof WaitableResult) {
-                ((WaitableResult) result).beforeLookup(t);
-            }
-        }
-
-        public void addLookupListener(LookupListener l) {
-            boolean add;
-
-            synchronized (this) {
-                listeners = AbstractLookup.modifyListenerList(true, l, listeners);
-                add = listeners != null;
-            }
-
-            if (add) {
-                result.addLookupListener(weak);
-            }
-        }
-
-        public void removeLookupListener(LookupListener l) {
-            boolean remove;
-
-            synchronized (this) {
-                listeners = AbstractLookup.modifyListenerList(false, l, listeners);
-                remove = listeners == null;
-            }
-
-            if (remove) {
-                result.removeLookupListener(weak);
-            }
-        }
-
-        public Collection allInstances() {
-            return openCol(result.allInstances(), 0);
-        }
-
-        private  Collection openCol(Collection c, int type) {
-            return filter(classes(), from, c, type, new ArrayList(c.size()));
-        }
-
-        @Override
-        public Set> allClasses() {
-            return filter(classes(), from, result.allClasses(), 1, new HashSet>());
-        }
-
-        @Override
-        public Collection> allItems() {
-            return openCol(result.allItems(), 2);
-        }
-
-        public void resultChanged(org.openide.util.LookupEvent ev) {
-            if (ev.getSource() == result) {
-                collectFires(null);
-            }
-        }
-
-        protected void collectFires(Collection evAndListeners) {
-            LookupListener[] arr;
-
-            synchronized (this) {
-                if (listeners == null) {
-                    return;
-                }
-
-                if (listeners instanceof LookupListener) {
-                    arr = new LookupListener[] { (LookupListener) listeners };
-                } else {
-                    ArrayList l = (ArrayList) listeners;
-                    arr = l.toArray(new LookupListener[l.size()]);
-                }
-            }
-
-            final LookupListener[] ll = arr;
-            final org.openide.util.LookupEvent newev = new org.openide.util.LookupEvent(this);
-            AbstractLookup.notifyListeners(ll, newev, evAndListeners);
-        }
-    } // end of R
-    
-    private final class WeakResult extends WaitableResult implements LookupListener {
-        private Lookup.Result source;
-        private Reference> result;
-        
-        public WeakResult(R r, Lookup.Result s) {
-            this.result = new WeakReference>(r);
-            this.source = s;
-        }
-        
-        protected void beforeLookup(Lookup.Template t) {
-            R r = (R)result.get();
-            if (r != null) {
-                r.beforeLookup(t);
-            } else {
-                source.removeLookupListener(this);
-            }
-        }
-
-        protected void collectFires(Collection evAndListeners) {
-            R r = result.get();
-            if (r != null) {
-                r.collectFires(evAndListeners);
-            } else {
-                source.removeLookupListener(this);
-            }
-        }
-
-        public void addLookupListener(LookupListener l) {
-            assert false;
-        }
-
-        public void removeLookupListener(LookupListener l) {
-            assert false;
-        }
-
-        public Collection allInstances() {
-            assert false;
-            return null;
-        }
-
-        public void resultChanged(LookupEvent ev) {
-            R r = (R)result.get();
-            if (r != null) {
-                r.resultChanged(ev);
-            } else {
-                source.removeLookupListener(this);
-            }
-        }
-
-        @Override
-        public Collection> allItems() {
-            assert false;
-            return null;
-        }
-
-        @Override
-        public Set> allClasses() {
-            assert false;
-            return null;
-        }
-    } // end of WeakResult
-}
diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/InheritanceTree.java
--- a/lookup/src/main/java/org/openide/util/lookup/InheritanceTree.java	Wed Jan 27 17:46:23 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1276 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common
- * Development and Distribution License("CDDL") (collectively, the
- * "License"). You may not use this file except in compliance with the
- * License. You can obtain a copy of the License at
- * http://www.netbeans.org/cddl-gplv2.html
- * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
- * specific language governing permissions and limitations under the
- * License.  When distributing the software, include this License Header
- * Notice in each file and include the License file at
- * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the GPL Version 2 section of the License file that
- * accompanied this code. If applicable, add the following below the
- * License Header, with the fields enclosed by brackets [] replaced by
- * your own identifying information:
- * "Portions Copyrighted [year] [name of copyright owner]"
- *
- * Contributor(s):
- *
- * The Original Software is NetBeans. The Initial Developer of the Original
- * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
- * Microsystems, Inc. All Rights Reserved.
- *
- * If you wish your version of this file to be governed by only the CDDL
- * or only the GPL Version 2, indicate your decision by adding
- * "[Contributor] elects to include this software in this distribution
- * under the [CDDL or GPL Version 2] license." If you do not indicate a
- * single choice of license, a recipient has the option to distribute
- * your version of this file under either the CDDL, the GPL Version 2 or
- * to extend the choice of license to its licensees as provided above.
- * However, if you add GPL Version 2 code and therefore, elected the GPL
- * Version 2 license, then the option applies only if the new code is
- * made subject to such option by the copyright holder.
- */
-package org.openide.util.lookup;
-
-import org.openide.util.Lookup;
-import org.openide.util.lookup.AbstractLookup.Pair;
-import org.openide.util.lookup.AbstractLookup.ReferenceIterator;
-import org.openide.util.lookup.AbstractLookup.ReferenceToResult;
-
-import java.io.*;
-
-import java.lang.ref.WeakReference;
-
-import java.util.*;
-
-
-/** A tree to represent classes with inheritance. Description of the
- * data structure by Petr Nejedly:
- * 

- * So pretend I'm Lookup implementation. I've got a bunch of Items (e.g. - * setPairs() method), - * didn't do anything on them yet (no startup penalty) so I know nothing - * about them. - * Then I'll be asked for all instances implementing given interface or a - * class. I surely need - * to check all the Items now, as I don't know anything abou them. I surely - * don't want to call - * Item.getClass() as it will dismiss the whole effort. So all I have is - * Item.instanceOf() - * and I'll call it on every Item. I'll cache results, so the next time - * you'll ask me for - * the same interface/class, I'll answer immediatelly. But what if you ask - * me for another - * interface/class? I'll have to scan all Items for it again, unless I can - * be sure some - * of them can't implement it. The only source of this knowledge are the - * previous questions - * and my rulings on them. Here the algorithm have to be split into two - * paths. If you - * previously asked me for interfaces only, I'll have no hint for - * subsequent queries, - * but if you asked me for a class in history, and then for another class - * and these classes - * are not in inheritance relation (I can check hierarchy of lookup - * arguments, because - * they are already resolved/loaded) I can tell that those returned in - * previous query can't - * implement the newly asked class (they are in different hierarchy branch) - * and I need to - * ask less Items. - *

- * So if we use mostly classes for asking for services (and it is a trend - * to use - * abstract classes for this purpose in IDE anyway), this could be usable. - *

- * The data structure for separating the Items based on previous queries is - * simple - * tree, with every node tagged with one class. The tree's root is, - * naturally, - * java.lang.Object, is marked invited and initially contains all the - * Items. - * For every class query, the missing part of class hierarchy tree is - * created, - * the node of the class looked up is marked as invited and all Items from - * nearest - * invited parent (sperclass) are dragged to this node. The result are then - * all - * Items from this node and all the nodes deeper in hierarchy. Because it - * may - * be too complicated to walk through the children nodes, the results could - * be - * cached in the map. - * For interface lookup, there is a little hint in reality (interfaces - * and superinterfaces), but it would be harder to exploit it, so we could - * fall-back - * to walking through all the Items and cache results. - * - * - * @author Jaroslav Tulach - */ -final class InheritanceTree extends Object -implements Serializable, AbstractLookup.Storage> { - private static final long serialVersionUID = 1L; - - /** the root item (represents Object) */ - private transient Node object; - - /** Map of queried interfaces. - *

Type: Map<Class, (Collection<AbstractLookup.Pair> | AbstractLookup.Pair)> - */ - private transient Map interfaces; - - /** Map (Class, ReferenceToResult) of all listeners that are waiting in - * changes in class Class - */ - private transient Map reg; - - /** Constructor - */ - public InheritanceTree() { - object = new Node(java.lang.Object.class); - } - - private void writeObject(ObjectOutputStream oos) throws IOException { - oos.writeObject(object); - - if (interfaces != null) { - Iterator it = interfaces.entrySet().iterator(); - - while (it.hasNext()) { - Map.Entry e = (Map.Entry) it.next(); - Class c = (Class) e.getKey(); - oos.writeObject(c.getName()); - - Object o = e.getValue(); - - if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) { - throw new ClassCastException(String.valueOf(o)); - } - - oos.writeObject(o); - } - } - - oos.writeObject(null); - } - - private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { - object = (Node) ois.readObject(); - interfaces = new WeakHashMap(); - - String clazz; - ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class); - - while ((clazz = (String) ois.readObject()) != null) { - Object o = ois.readObject(); - - if (!(o instanceof Collection) && !(o instanceof AbstractLookup.Pair)) { - throw new ClassCastException(String.valueOf(o)); - } - - Class c = Class.forName(clazz, false, l); - interfaces.put(c, o); - } - } - - /** Adds an item into the tree. - * @param item to add - * @return true if the Item has been added for the first time or false if some other - * item equal to this one already existed in the lookup - */ - public boolean add(AbstractLookup.Pair item, ArrayList affected) { - Node node = registerClass(object, item); - - affected.add(node.getType()); - - if (node.assignItem(this, item)) { - // this is the first item added to n.items - // ok, we have to test interfaces too - } else { - // equal item is already there => stop processing - return false; - } - - boolean registeredAsInterface = registerInterface(item, affected); - - return registeredAsInterface; - } - - /** Removes an item. - */ - public void remove(AbstractLookup.Pair item, ArrayList affected) { - Node n = removeClass(object, item); - - if (n != null) { - affected.add(n.getType()); - } - - removeInterface(item, affected); - } - - /** Removes all items that are not present in the provided collection. - * @param retain collection of Pairs to keep them in - * @param notify set of Classes that has possibly changed - */ - public void retainAll(Map retain, ArrayList notify) { - retainAllInterface(retain, notify); - retainAllClasses(object, retain, notify); - } - - /** Queries for instances of given class. - * @param clazz the class to check - * @return enumeration of Item - * @see #unsorted - */ - @SuppressWarnings("unchecked") - public Enumeration> lookup(Class clazz) { - if ((clazz != null) && clazz.isInterface()) { - return (Enumeration)searchInterface(clazz); - } else { - return (Enumeration)searchClass(object, clazz); - } - } - - /** A method to check whether the enumeration returned from - * lookup method is sorted or is not - * @param en enumeration to check - * @return true if it is unsorted and needs to be sorted to find - * pair with smallest index - */ - public static boolean unsorted(Enumeration en) { - return en instanceof NeedsSortEnum; - } - - /** Prints debug messages. - * @param out stream to output to - * @param instances print also instances of the - */ - public void print(java.io.PrintStream out, boolean instances) { - printNode(object, "", out, instances); // NOI18N - } - - // - // methods to work on classes which are not interfaces - // - - /** Searches the subtree and register the item where necessary. - * @return the node that should contain the item - */ - private static Node registerClass(Node n, AbstractLookup.Pair item) { - if (!n.accepts(item)) { - return null; - } - - if (n.children != null) { - Iterator it = n.children.iterator(); - - for (;;) { - Node ch = extractNode(it); - - if (ch == null) { - break; - } - - Node result = registerClass(ch, item); - - if (result != null) { - // it is in subclass, in case of classes, it cannot - // be any other class - return result; - } - } - } - - // ok, nobody of our subclasses wants the class, I'll take it - return n; - } - - /** Removes the item from the tree of objects. - * @return most narrow class that this item was removed from - */ - private static Node removeClass(Node n, AbstractLookup.Pair item) { - if (!n.accepts(item)) { - return null; - } - - if ((n.items != null) && n.items.remove(item)) { - // this node really contains the item - return n; - } - - if (n.children != null) { - Iterator it = n.children.iterator(); - - for (;;) { - Node ch = extractNode(it); - - if (ch == null) { - break; - } - - Node result = removeClass(ch, item); - - // If the children node was emptied, remove it if possible. - if (((ch.items == null) || ch.items.isEmpty()) && ((ch.children == null) || ch.children.isEmpty())) { - it.remove(); - } - - if (result != null) { - // it is in subclass, in case of classes, it cannot - // be any other class - return result; - } - } - } - - // nobody found - return null; - } - - /** Finds a node that represents a class. - * @param n node to search from - * @param clazz the clazz to find - * @return node that represents clazz in the tree or null if the clazz is not - * represented under the node n - */ - private Node classToNode(final Node n, final Class clazz) { - if (!n.accepts(clazz)) { - // nothing from us - return null; - } - - if (n.getType() == clazz) { - // we have found what we need - return n; - } - - if (n.children != null) { - // have to proceed to children - Iterator it = n.children.iterator(); - - for (;;) { - final Node ch = extractNode(it); - - if (ch == null) { - break; - } - - Node found = classToNode(ch, clazz); - - if ((found != null) && ch.deserialized()) { - class VerifyJob implements AbstractLookup.ISE.Job { - private AbstractLookup.Pair[] pairs; - private boolean[] answers; - - public VerifyJob(Collection items) { - if (items != null) { - pairs = items.toArray(new AbstractLookup.Pair[0]); - } - } - - public void before() { - // make sure the node is converted into deserialized state - ch.deserialized(); - - if (pairs != null) { - answers = new boolean[pairs.length]; - - for (int i = 0; i < pairs.length; i++) { - answers[i] = pairs[i].instanceOf(clazz); - } - } - } - - public void inside() { - if (pairs != null) { - for (int i = 0; i < pairs.length; i++) { - if (answers[i]) { - ch.assignItem(InheritanceTree.this, pairs[i]); - n.items.remove(pairs[i]); - } - } - } - - if (n.children != null) { - // consolidate all nodes that represent the same class - HashMap nodes = new HashMap(n.children.size() * 3); - - Iterator child = n.children.iterator(); - - while (child.hasNext()) { - Node node = extractNode(child); - if (node == null) { - continue; - } - Node prev = nodes.put(node.getType(), node); - - if (prev != null) { - child.remove(); - nodes.put(node.getType(), prev); - - // mark as being deserialized - prev.markDeserialized(); - - if (prev.children == null) { - prev.children = node.children; - } else { - if (node.children != null) { - prev.children.addAll(node.children); - } - } - - if (node.items != null) { - Iterator items = node.items.iterator(); - - while (items.hasNext()) { - AbstractLookup.Pair item = (AbstractLookup.Pair) items.next(); - prev.assignItem(InheritanceTree.this, item); - } - } - } - } - } - } - } - - VerifyJob verify = new VerifyJob(n.items); - - try { - verify.before(); - } catch (AbstractLookup.ISE ex) { - // mark deserialized again - ch.markDeserialized(); - ex.registerJob(verify); - throw ex; - } - - verify.inside(); - - found = classToNode(ch, clazz); - } - - if (found != null) { - // class found in one of subnodes - return found; - } - } - } - - class TwoJobs implements AbstractLookup.ISE.Job { - private AbstractLookup.Pair[] pairs; - private boolean[] answers; - private Node newNode; - - public void before() { - // have to create new subnode and possibly reparent one of my own - // but all changes can be done only if we will not be interrupted from - // outside - e.g. instanceOf methods will not throw exception - // first of all let's compute the answers to method instanceOf - AbstractLookup.Pair[] arr = null; - boolean[] boolArr = null; - - if (n.items != null) { - arr = new AbstractLookup.Pair[n.items.size()]; - boolArr = new boolean[n.items.size()]; - - int i = 0; - Iterator it = n.items.iterator(); - - while (it.hasNext()) { - AbstractLookup.Pair item = it.next(); - arr[i] = item; - boolArr[i] = item.instanceOf(clazz); - i++; - } - } - - pairs = arr; - answers = boolArr; - } - - public void inside() { - // test if the query has not chagned since - if (pairs != null) { - if (!Arrays.equals(n.items.toArray(), pairs)) { - // ok, let try once more - return; - } - } - - internal(); - } - - public void internal() { - ArrayList reparent = null; - - if (n.children == null) { - n.children = new ArrayList(); - } else { - // scan thru all my nodes if some of them are not a subclass - // of clazz => then they would need to become child of newNode - Iterator it = n.children.iterator(); - - for (;;) { - Node r = extractNode(it); - - if (r == null) { - break; - } - - if (clazz.isAssignableFrom(r.getType())) { - if (reparent == null) { - reparent = new ArrayList(); - } - - reparent.add(r); - it.remove(); - } - } - } - - newNode = new Node(clazz); - n.children.add(newNode); - - if (reparent != null) { - // reassing reparent node as a child of newNode - newNode.children = reparent; - } - - // now take all my items that are instances of that class and - // reasign them - if (n.items != null) { - Iterator it = n.items.iterator(); - int i = 0; - - while (it.hasNext()) { - AbstractLookup.Pair item = (AbstractLookup.Pair) it.next(); - - if (answers[i]) { // answers[i] is precomputed value of item.instanceOf (clazz)) - it.remove(); - newNode.assignItem(InheritanceTree.this, pairs[i]); - } - - i++; - } - } - } - } - - TwoJobs j = new TwoJobs(); - - try { - j.before(); - } catch (AbstractLookup.ISE ex) { - // ok, it is not possible to call instanceOf now, let's - // schedule it for later - // so register recovery job - ex.registerJob(j); - throw ex; - } - - j.internal(); - - // newNode represents my clazz - return j.newNode; - } - - /** Search for a requested class. - * @return enumeration of Pair - */ - private Enumeration searchClass(Node n, Class clazz) { - if (clazz != null) { - n = classToNode(n, clazz); - } - - if (n == null) { - // not for us - return emptyEn(); - } else { - return nodeToEnum(n); - } - } - - /** Retains all classes. Removes nodes which items and children are emptied, works - * recursivelly from specified root node. - * @param node root node from which to start to process the tree - * @param retain a map from (Item, AbstractLookup.Info) that describes which items to retain - * and witch integer to assign them - * @param notify collection of classes will be changed - * @return true if some items were changed and node items and children are emptied, - * those nodes, excluding root, will be removed from tree */ - private boolean retainAllClasses(Node node, Map retain, Collection notify) { - boolean retained = false; - - if ((node.items != null) && (retain != null)) { - Iterator it = node.items.iterator(); - - while (it.hasNext()) { - AbstractLookup.Pair item = it.next(); - AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(item); - - if (n == null) { - // remove this item, it should not be there - it.remove(); - retained = true; - } else { - // change the index - if (item.getIndex() != n.index) { - item.setIndex(null, n.index); - - // notify.addAll ((ArrayList)n.transaction); - } - } - } - - if (retained && (notify != null)) { - // type of this node has been changed - notify.add(node.getType()); - } - } - - if (node.children != null) { - for (Iterator it = node.children.iterator();;) { - Node ch = extractNode(it); - - if (ch == null) { - break; - } - - boolean result = retainAllClasses(ch, retain, notify); - - if (result) { - // The children node was emptied and has no children -> remove it. - it.remove(); - } - } - } - - return retained && node.items.isEmpty() && ((node.children == null) || node.children.isEmpty()); - } - - /** A method that creates enumeration of all items under given node. - * - * @param n node to create enumeration for - * @return enumeration of Pairs - */ - private static Enumeration nodeToEnum(Node n) { - if (n.children == null) { - // create a simple enumeration because we do not have children - Enumeration e; - if (n.items == null) { - e = emptyEn(); - } else { - e = Collections.enumeration(n.items); - } - return e; - } - - // create enumeration of Items - return new NeedsSortEnum(n); - } - - // - // Methods to work on interfaces - // - - /** Registers an item with interfaces. - * @param item item to register - * @param affected list of classes that were affected - * @return false if similar item has already been registered - */ - @SuppressWarnings("unchecked") - private boolean registerInterface(AbstractLookup.Pair item, Collection affected) { - if (interfaces == null) { - return true; - } - - Iterator> it = interfaces.entrySet().iterator(); - - while (it.hasNext()) { - Map.Entry entry = it.next(); - Class iface = entry.getKey(); - - if (item.instanceOf(iface)) { - Object value = entry.getValue(); - - if (value instanceof Collection) { - Collection set = (Collection) value; - - if (!set.add(item)) { - // item is already there, probably (if everything is correct) is registered in - // all other ifaces too, so stop additional testing - return false; - } - } else { - // there is just one pair right now - if (value.equals(item)) { - // item is there => stop processing (same as above) - return false; - } - - // otherwise replace the single item with ArrayList - ArrayList ll = new ArrayList(3); - ll.add(value); - ll.add(item); - entry.setValue(ll); - } - - affected.add(iface); - } - } - - return true; - } - - /** Removes interface. - * @param item item to register - * @param affected list of classes that were affected - */ - @SuppressWarnings("unchecked") - private void removeInterface(AbstractLookup.Pair item, Collection affected) { - if (interfaces == null) { - return; - } - - Iterator it = interfaces.entrySet().iterator(); - - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - Object value = entry.getValue(); - - if (value instanceof Collection) { - Collection set = (Collection) value; - - if (set.remove(item)) { - if (set.size() == 1) { - // if there is just one item remaining change to single item mode - entry.setValue(set.iterator().next()); - } - - // adds the Class the item was register to into affected - affected.add(entry.getKey()); - } - } else { - // single item value - if (value.equals(item)) { - // Emptied -> remove. - it.remove(); - - affected.add(entry.getKey()); - } - } - } - } - - /** Retains some items. - * @param retainItems items to retain and their mapping to index numbers - * (AbstractLookup.Pair -> AbstractLookup.Info) - * @param affected list of classes that were affected - */ - @SuppressWarnings("unchecked") - private void retainAllInterface(Map retainItems, Collection affected) { - if (interfaces == null) { - return; - } - - Iterator it = interfaces.entrySet().iterator(); - - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - Object value = entry.getValue(); - - HashMap retain = new HashMap(retainItems); - - Iterator elems; - boolean multi = value instanceof Collection; - - if (multi) { - // collection mode - elems = ((Collection) value).iterator(); - } else { - // single item mode - elems = Collections.singleton(value).iterator(); - } - - boolean changed = false; - boolean reordered = false; - - while (elems.hasNext()) { - AbstractLookup.Pair p = (AbstractLookup.Pair) elems.next(); - - AbstractLookup.Info n = (AbstractLookup.Info) retain.remove(p); - - if (n == null) { - if (multi) { - // remove it - elems.remove(); - } - - changed = true; - } else { - if (p.getIndex() != n.index) { - // improve the index - p.setIndex(null, n.index); - - // affected.addAll ((ArrayList)n.transaction); - reordered = true; - } - } - } - - if (reordered && value instanceof List) { - // if reordered, than update the order in the collection - List l = (List) value; - Collections.sort(l, ALPairComparator.DEFAULT); - } - - if (changed) { - if (multi) { - Collection c = (Collection) value; - - if (c.size() == 1) { - // back to single item mode - entry.setValue(c.iterator().next()); - } - } else { - // remove in single mode => remove completely - it.remove(); - } - - // adds the Class the item was register to into affected - affected.add(entry.getKey()); - } - } - } - - /** Searches for a clazz between interfaces. - * @param clazz class to search for - * @return enumeration of Items - */ - @SuppressWarnings("unchecked") - private Enumeration searchInterface(final Class clazz) { - if (interfaces == null) { - // first call for interface, only initialize - interfaces = new WeakHashMap(); - } - - Object obj = interfaces.get(clazz); - - if (obj == null) { - // set of items - AbstractLookup.Pair one = null; - ArrayList items = null; - - Enumeration en = lookup(Object.class); - - while (en.hasMoreElements()) { - AbstractLookup.Pair it = (AbstractLookup.Pair) en.nextElement(); - - if (it.instanceOf(clazz)) { - // ok, this item implements given clazz - if (one == null) { - one = it; - } else { - if (items == null) { - items = new ArrayList(3); - items.add(one); - } - - items.add(it); - } - } - } - - if ((items == null) && (one != null)) { - // single item mode - interfaces.put(clazz, one); - - return singletonEn(one); - } else { - if (items == null) { - items = new ArrayList(2); - } - - interfaces.put(clazz, items); - - return Collections.enumeration(items); - } - } else { - if (obj instanceof Collection) { - return Collections.enumeration((Collection) obj); - } else { - // single item mode - return singletonEn((Pair)obj); - } - } - } - - /** Extracts a node from an iterator, returning null if no next element found - */ - private static Node extractNode(Iterator it) { - while (it.hasNext()) { - Node n = (Node) it.next(); - - if (n.get() == null) { - it.remove(); - } else { - return n; - } - } - - return null; - } - - /** Prints debug info about the node. - * @param n node to print - * @param sp spaces to add - * @param out where - * @param instances print also instances - */ - private static void printNode(Node n, String sp, java.io.PrintStream out, boolean instances) { - int i; - Iterator it; - - Class type = n.getType(); - - out.print(sp); - out.println("Node for: " + type + "\t" + ((type == null) ? null : type.getClassLoader())); // NOI18N - - if (n.items != null) { - i = 0; - it = new ArrayList(n.items).iterator(); - - while (it.hasNext()) { - AbstractLookup.Pair p = (AbstractLookup.Pair) it.next(); - out.print(sp); - out.print(" item (" + i++ + "): "); - out.print(p); // NOI18N - out.print(" id: " + Integer.toHexString(System.identityHashCode(p))); // NOI18N - out.print(" index: "); // NOI18N - out.print(p.getIndex()); - - if (instances) { - out.print(" I: " + p.getInstance()); - } - - out.println(); - } - } - - if (n.children != null) { - i = 0; - it = n.children.iterator(); - - while (it.hasNext()) { - Node ch = (Node) it.next(); - printNode(ch, sp + " ", out, instances); // NOI18N - } - } - } - - public ReferenceToResult registerReferenceToResult(ReferenceToResult newRef) { - if (reg == null) { - reg = new HashMap(); - } - - Class clazz = newRef.template.getType(); - - // initialize the data structures if not yet - lookup(clazz); - - // newRef will be the new head of the list - return reg.put(clazz, newRef); - } - - public ReferenceToResult cleanUpResult(Lookup.Template templ) { - collectListeners(null, templ.getType()); - - return (reg == null) ? null : reg.get(templ.getType()); - } - - public ArrayList beginTransaction(int ensure) { - return new ArrayList(); - } - - public void endTransaction(ArrayList list, Set allAffectedResults) { - if (list.size() == 1) { - // probably the most common case - collectListeners(allAffectedResults, list.get(0)); - } else { - Iterator it = list.iterator(); - - while (it.hasNext()) { - collectListeners(allAffectedResults, (Class) it.next()); - } - } - } - - /** Notifies all listeners that are interested in changes in this class. - * Should be called from synchronized places. - * @param allAffectedResults adds Results into this set - * @param c the class that has changed - */ - private void collectListeners(Set allAffectedResults, Class c) { - if (reg == null) { - return; - } - - while (c != null) { - ReferenceToResult first = reg.get(c); - ReferenceIterator it = new ReferenceIterator(first); - - while (it.next()) { - AbstractLookup.R result = it.current().getResult(); - - if (allAffectedResults != null) { - // add result - allAffectedResults.add(result); - } - } - - if (first != it.first()) { - if (it.first() == null) { - // we do not need have more results on this object - reg.remove(c); - } else { - // move the head of the list - reg.put(c, it.first()); - } - } - - c = c.getSuperclass(); - } - - if (reg.isEmpty()) { - // clean up the list of all results if we do not need them anymore - reg = null; - } - } - - /** Node in the tree. - */ - static final class Node extends WeakReference implements Serializable { - static final long serialVersionUID = 3L; - - /** children nodes */ - public ArrayList children; - - /** list of items assigned to this node (suspect to be subclasses) */ - public Collection items; - - /** Constructor. - */ - public Node(Class clazz) { - super(clazz); - } - - /** Returns true if the object was deserialized also clears the serialized flag. - * @return true if so. - */ - public boolean deserialized() { - if ((items == null) || items instanceof LinkedHashSet) { - return false; - } - - if (items.isEmpty()) { - items = null; - } else { - items = new LinkedHashSet(items); - } - - return true; - } - - /** Marks this item as being deserialized. - */ - public void markDeserialized() { - if (items == null || items == Collections.EMPTY_LIST) { - items = Collections.emptyList(); - } else { - items = Collections.synchronizedCollection(items); - } - } - - /** Getter for the type associated with this node. - */ - public Class getType() { - Class c = get(); - - // if garbage collected, then return a garbage - return (c == null) ? Void.TYPE : c; - } - - /** Checks whether a node can represent an class. - */ - public boolean accepts(Class clazz) { - if (getType() == Object.class) { - return true; - } - - return getType().isAssignableFrom(clazz); - } - - /** Checks whether item is instance of this node. - */ - public boolean accepts(AbstractLookup.Pair item) { - if (getType() == Object.class) { - // Object.class - return true; - } - - return item.instanceOf(getType()); - } - - /** Assings an item to this node. - * @param item the item - * @return true if item has been added as new - */ - public boolean assignItem(InheritanceTree tree, AbstractLookup.Pair item) { - if ((items == null) || (items == Collections.EMPTY_LIST)) { - items = new LinkedHashSet(); - items.add(item); - - return true; - } - - if (items.contains(item)) { - Iterator it = items.iterator(); - Pair old; - for (;;) { - old = it.next(); - if (item.equals(old)) { - break; - } - } - - if (old != item) { - // replace the items there - item.setIndex(tree, old.getIndex()); - } - - it.remove(); - items.add(item); - - return false; - } - - items.add(item); - - return true; - } - - private Object writeReplace() { - return new R(this); - } - - @Override - public String toString() { - return "Node for " + get(); - } - } - // End of class Node. - - private static final class R implements Serializable { - static final long serialVersionUID = 1L; - private static ClassLoader l; - private String clazzName; - private transient Class clazz; - private ArrayList children; - private Collection items; - - public R(Node n) { - this.clazzName = n.getType().getName(); - this.children = n.children; - - if (n.items instanceof LinkedHashSet || (n.items == null)) { - this.items = n.items; - } else { - this.items = new LinkedHashSet(n.items); - } - } - - private void readObject(ObjectInputStream ois) - throws IOException, ClassNotFoundException { - ois.defaultReadObject(); - - if (l == null) { - l = Lookup.getDefault().lookup(ClassLoader.class); - } - - clazz = Class.forName(clazzName, false, l); - } - - private Object readResolve() throws ObjectStreamException { - Node n = new Node(clazz); - n.children = children; - n.items = items; - n.markDeserialized(); - - return n; - } - } - // end of R - - static Enumeration arrayEn(Object[] object) { - return Collections.enumeration(Arrays.asList(object)); - } - static Enumeration singletonEn(T object) { - return Collections.enumeration(Collections.singleton(object)); - } - static Enumeration emptyEn() { - return Collections.enumeration(Collections.emptyList()); - } - - /** Just a marker class to be able to do instanceof and find out - * that this enumeration is not sorted - */ - private static final class NeedsSortEnum extends LinkedList - implements Enumeration { - private Enumeration en; - - public NeedsSortEnum(Node n) { - add(n); - } - - private boolean ensureNext() { - for (;;) { - if (en != null && en.hasMoreElements()) { - return true; - } - if (isEmpty()) { - return false; - } - - Node n2 = poll(); - if (n2.children != null) { - addAll(n2.children); - } - - if (n2.items != null && !n2.items.isEmpty()) { - en = Collections.enumeration(n2.items); - } - } - } - - public boolean hasMoreElements() { - return ensureNext(); - } - - public Pair nextElement() { - if (!ensureNext()) { - throw new NoSuchElementException(); - } - return en.nextElement(); - } - } - // end of NeedsSortEnum -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/InstanceContent.java --- a/lookup/src/main/java/org/openide/util/lookup/InstanceContent.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,378 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util.lookup; - -import org.openide.util.lookup.AbstractLookup.Pair; - -import java.lang.ref.WeakReference; - -import java.util.*; -import java.util.concurrent.Executor; -import org.openide.util.Lookup.Item; - - -/** A special content implementation that can be passed to AbstractLookup - * and provides methods for registration of instances and lazy instances. - *
- *      InstanceContent ic = new InstanceContent ();
- *      AbstractLookup al = new AbstractLookup (ic);
- *
- *      ic.add (new Object ());
- *      ic.add (new Dimension (...));
- *
- *      Dimension theDim = (Dimension)al.lookup (Dimension.class);
- * 
- * - * @author Jaroslav Tulach - * - * @since 1.25 - */ -public final class InstanceContent extends AbstractLookup.Content { - /** - * Create a new, empty content. - */ - public InstanceContent() { - } - - /** Creates a content associated with an executor to handle dispatch - * of changes. - * @param notifyIn the executor to notify changes in - * @since 7.16 - */ - public InstanceContent(Executor notifyIn) { - super(notifyIn); - } - /** The method to add instance to the lookup with. - * @param inst instance - */ - public final void add(Object inst) { - addPair(new SimpleItem(inst)); - } - - /** Adds a convertible instance into the lookup. The inst - * argument is just a key, not the actual value to appear in the lookup. - * The value will be created on demand, later when it is really needed - * by calling convertor methods. - *

- * This method is useful to delay creation of heavy weight objects. - * Instead just register lightweight key and a convertor. - *

- * To remove registered object from lookup use {@link #remove(java.lang.Object, org.openide.util.lookup.InstanceContent.Convertor)} - * with the same arguments. - * - * @param inst instance - * @param conv convertor which postponing an instantiation, - * if conv==null then the instance is registered directly. - */ - public final void add(T inst, Convertor conv) { - addPair(new ConvertingItem(inst, conv)); - } - - /** Remove instance. - * @param inst instance - */ - public final void remove(Object inst) { - removePair(new SimpleItem(inst)); - } - - /** Remove instance added with a convertor. - * @param inst instance - * @param conv convertor, if conv==null it is same like - * remove(Object) - */ - public final void remove(T inst, Convertor conv) { - removePair(new ConvertingItem(inst, conv)); - } - - /** Changes all pairs in the lookup to new values. Converts collection of - * instances to collection of pairs. - * @param col the collection of (Item) objects - * @param conv the convertor to use or null - */ - public final void set(Collection col, Convertor conv) { - ArrayList> l = new ArrayList>(col.size()); - Iterator it = col.iterator(); - - if (conv == null) { - while (it.hasNext()) { - l.add(new SimpleItem(it.next())); - } - } else { - while (it.hasNext()) { - l.add(new ConvertingItem(it.next(), conv)); - } - } - - setPairs(l); - } - - /** Convertor postpones an instantiation of an object. - * @since 1.25 - */ - public static interface Convertor { - /** Convert obj to other object. There is no need to implement - * cache mechanism. It is provided by - * {@link Item#getInstance()} method itself. However the - * method can be called more than once because instance is held - * just by weak reference. - * - * @param obj the registered object - * @return the object converted from this object - */ - public R convert(T obj); - - /** Return type of converted object. Accessible via - * {@link Item#getType()} - * @param obj the registered object - * @return the class that will be produced from this object (class or - * superclass of convert (obj)) - */ - public Class type(T obj); - - /** Computes the ID of the resulted object. Accessible via - * {@link Item#getId()}. - * @param obj the registered object - * @return the ID for the object - */ - public String id(T obj); - - /** The human presentable name for the object. Accessible via - * {@link Item#getDisplayName()}. - * @param obj the registered object - * @return the name representing the object for the user - */ - public String displayName(T obj); - } - - /** Instance of one item representing an object. - */ - final static class SimpleItem extends Pair { - private T obj; - - /** Create an item. - * @obj object to register - */ - public SimpleItem(T obj) { - if (obj == null) { - throw new NullPointerException(); - } - this.obj = obj; - } - - /** Tests whether this item can produce object - * of class c. - */ - public boolean instanceOf(Class c) { - return c.isInstance(obj); - } - - /** Get instance of registered object. If convertor is specified then - * method InstanceLookup.Convertor.convertor is used and weak reference - * to converted object is saved. - * @return the instance of the object. - */ - public T getInstance() { - return obj; - } - - @Override - public boolean equals(Object o) { - if (o instanceof SimpleItem) { - return obj.equals(((SimpleItem) o).obj); - } else { - return false; - } - } - - @Override - public int hashCode() { - return obj.hashCode(); - } - - /** An identity of the item. - * @return string representing the item, that can be used for - * persistance purposes to locate the same item next time - */ - public String getId() { - return "IL[" + obj.toString(); // NOI18N - } - - /** Getter for display name of the item. - */ - public String getDisplayName() { - return obj.toString(); - } - - /** Method that can test whether an instance of a class has been created - * by this item. - * - * @param obj the instance - * @return if the item has already create an instance and it is the same - * as obj. - */ - protected boolean creatorOf(Object obj) { - return obj == this.obj; - } - - /** The class of this item. - * @return the correct class - */ - @SuppressWarnings("unchecked") - public Class getType() { - return (Class)obj.getClass(); - } - } - // end of SimpleItem - - /** Instance of one item registered in the map. - */ - final static class ConvertingItem extends Pair { - /** registered object */ - private T obj; - - /** Reference to converted object. */ - private WeakReference ref; - - /** convertor to use */ - private Convertor conv; - - /** Create an item. - * @obj object to register - * @conv a convertor, can be null. - */ - public ConvertingItem(T obj, Convertor conv) { - this.obj = obj; - this.conv = conv; - } - - /** Tests whether this item can produce object - * of class c. - */ - public boolean instanceOf(Class c) { - return c.isAssignableFrom(getType()); - } - - /** Returns converted object or null if obj has not been converted yet - * or reference was cleared by garbage collector. - */ - private R getConverted() { - if (ref == null) { - return null; - } - - return ref.get(); - } - - /** Get instance of registered object. If convertor is specified then - * method InstanceLookup.Convertor.convertor is used and weak reference - * to converted object is saved. - * @return the instance of the object. - */ - public synchronized R getInstance() { - R converted = getConverted(); - - if (converted == null) { - converted = conv.convert(obj); - ref = new WeakReference(converted); - } - - return converted; - } - - @Override - public boolean equals(Object o) { - if (o instanceof ConvertingItem) { - return obj.equals(((ConvertingItem) o).obj); - } else { - return false; - } - } - - @Override - public int hashCode() { - return obj.hashCode(); - } - - /** An identity of the item. - * @return string representing the item, that can be used for - * persistance purposes to locate the same item next time - */ - public String getId() { - return conv.id(obj); - } - - /** Getter for display name of the item. - */ - public String getDisplayName() { - return conv.displayName(obj); - } - - /** Method that can test whether an instance of a class has been created - * by this item. - * - * @param obj the instance - * @return if the item has already create an instance and it is the same - * as obj. - */ - protected boolean creatorOf(Object obj) { - if (conv == null) { - return obj == this.obj; - } else { - return obj == getConverted(); - } - } - - /** The class of this item. - * @return the correct class - */ - @SuppressWarnings("unchecked") - public Class getType() { - R converted = getConverted(); - - if (converted == null) { - return conv.type(obj); - } - - return (Class)converted.getClass(); - } - } - // end of ConvertingItem -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/Lookups.java --- a/lookup/src/main/java/org/openide/util/lookup/Lookups.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,317 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.Arrays; -import org.netbeans.modules.openide.util.NamedServicesProvider; -import org.openide.util.Lookup; - -/** - * Static factory methods for creating common lookup implementations. - * - * @author David Strupl - * @since 2.21 - */ -public class Lookups { - - /** static methods only */ - private Lookups() {} - - /** - * Creates a singleton lookup. It means lookup that contains only - * one object specified via the supplied parameter. The lookup will - * either return the object or null if the supplied template does - * not match the class. If the specified argument is null the method - * will end with NullPointerException. - * @return Fully initialized lookup object ready to use - * @throws NullPointerException if the supplied argument is null - * @since 2.21 - */ - public static Lookup singleton(Object objectToLookup) { - if (objectToLookup == null) { - throw new NullPointerException(); - } - - return new SingletonLookup(objectToLookup); - } - - /** - * Creates a lookup that contains an array of objects specified via the - * parameter. The resulting lookup is fixed in the following sense: it - * contains only fixed set of objects passed in by the array parameter. - * Its contents never changes so registering listeners on such lookup - * does not have any observable effect (the listeners are never called). - * - * @param objectsToLookup list of objects to include - * @return Fully initialized lookup object ready to use - * @throws NullPointerException if the supplied argument is null - * @since 2.21 - * - */ - public static Lookup fixed(Object... objectsToLookup) { - if (objectsToLookup == null) { - throw new NullPointerException(); - } - - if (objectsToLookup.length == 0) { - return Lookup.EMPTY; - } - - if (objectsToLookup.length == 1) { - return singleton(objectsToLookup[0]); - } - - return new SimpleLookup(Arrays.asList(objectsToLookup)); - } - - /** - * Creates a lookup that contains an array of objects specified via the - * parameter. The resulting lookup is fixed in the following sense: it - * contains only fixed set of objects passed in by the array parameter. - * The objects returned from this lookup are converted to real objects - * before they are returned by the lookup. - * Its contents never changes so registering listeners on such lookup - * does not have any observable effect (the listeners are never called). - * - * @return Fully initialized lookup object ready to use - * @throws NullPointerException if the any of the arguments is null - * @since 2.21 - * - */ - public static Lookup fixed(T[] keys, InstanceContent.Convertor convertor) { - if (keys == null) { - throw new NullPointerException(); - } - - if (convertor == null) { - throw new NullPointerException(); - } - - return new SimpleLookup(Arrays.asList(keys), convertor); - } - - /** Creates a lookup that delegates to another one but that one can change - * from time to time. The returned lookup checks every time somebody calls - * lookup or lookupItem method whether the - * provider still returns the same lookup. If not, it updates state of - * all {@link org.openide.util.Lookup.Result}s - * that it created (and that still exists). - *

- * The user of this method has to implement its provider's getLookup - * method (must be thread safe and fast, will be called often and from any thread) - * pass it to this method and use the returned lookup. Whenever the user - * changes the return value from the getLookup method and wants - * to notify listeners on the lookup about that it should trigger the event - * firing, for example by calling lookup.lookup (Object.class) - * directly on the lookup returned by this method - * that forces a check of the return value of {@link org.openide.util.Lookup.Provider#getLookup}. - * - * @param provider the provider that returns a lookup to delegate to - * @return lookup delegating to the lookup returned by the provider - * @since 3.9 - */ - public static Lookup proxy(Lookup.Provider provider) { - return new SimpleProxyLookup(provider); - } - - /** Returns a lookup that implements the JDK1.3 JAR services mechanism and delegates - * to META-INF/services/name.of.class files. - *

Some extensions to the JAR services specification are implemented: - *

    - *
  1. An entry may be followed by a line of the form #position=integer - * to specify ordering. (Smaller numbers first, entries with unspecified position last.) - *
  2. A line of the form #-classname suppresses an entry registered - * in another file, so can be used to supersede one implementation with another. - *
- *

Note: It is not dynamic - so if you need to change the classloader or JARs, - * wrap it in a {@link ProxyLookup} and change the delegate when necessary. - * Existing instances will be kept if the implementation classes are unchanged, - * so there is "stability" in doing this provided some parent loaders are the same - * as the previous ones. - * @since 3.35 - * @see ServiceProvider - */ - public static Lookup metaInfServices(ClassLoader classLoader) { - return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N - } - - /** Returns a lookup that behaves exactly like {@link #metaInfServices(ClassLoader)} - * except that it does not read data from META-INF/services/, but instead - * from the specified prefix. - * @param classLoader class loader to use for loading - * @param prefix prefix to prepend to the class name when searching - * @since 7.9 - */ - public static Lookup metaInfServices(ClassLoader classLoader, String prefix) { - return new MetaInfServicesLookup(classLoader, prefix); - } - - /** Creates a named lookup. - * It is a lookup identified by a given path. - * Two lookups with the same path should have the same content. - *

It is expected that each named lookup - * will contain a superset of what would be created by: - * {@linkplain #metaInfServices(ClassLoader,String) metaInfServices}(theRightLoader, "META-INF/namedservices/" + path + "/") - * - *

Various environments can add their own - * extensions to its content. As such - * {@link Lookups#forPath(java.lang.String)} can combine lookups - * from several sources. In current NetBeans Runtime Container, two lookups are used: - *

- *
    - *
  • Lookups.metaInfServices("META-INF/namedservices/" + path)
  • - *
  • org.openide.loaders.FolderLookup(path)
  • - *
- *

- * Please note that these lookups differ in the way they inspect sub-folders. - * The first lookup just returns instances from the given path, ignoring - * sub-folders, the second one retrieves instances from the whole sub-tree. - *

- *

- * Read more about the usage of this method. - * - * @param path the path identifying the lookup, e.g. Projects/Actions - * @return lookup associated with this path - * @since 7.9 - */ - public static Lookup forPath(String path) { - return NamedServicesProvider.find(path); - } - - /** Creates a lookup that wraps another one and filters out instances - * of specified classes. If you have a lookup and - * you want to remove all instances of ActionMap you can use: - *

-     * l = Lookups.exclude(lookup, ActionMap.class);
-     * 
- * Then anybody who asks for l.lookup(ActionMap.class) or - * subclass will get null. Even if the original lookup contains the - * value. - * To create empty lookup (well, just an example, otherwise use {@link Lookup#EMPTY}) one could use: - *
-     * Lookup.exclude(anyLookup, Object.class);
-     * 
- * as any instance in any lookup is of type Object and thus would be excluded. - *

- * The complete behavior can be described as classes being - * a barrier. For an object not to be excluded, there has to be an inheritance - * path between the queried class and the actual class of the instance, - * that is not blocked by any of the excluded classes: - *

-     * interface A {}
-     * interface B {}
-     * class C implements A, B {}
-     * Object c = new C();
-     * Lookup l1 = Lookups.singleton(c);
-     * Lookup l2 = Lookups.exclude(l1, A.class);
-     * assertNull("A is directly excluded", l2.lookup(A.class));
-     * assertEquals("Returns C as A.class is not between B and C", c, l2.lookup(B.class));
-     * 
- * For more info check the - * - * excluding lookup tests and the discussion in issue - * 53058. - * - * @param lookup the original lookup that should be filtered - * @param classes array of classes those instances should be excluded - * @since 5.4 - */ - public static Lookup exclude(Lookup lookup, Class... classes) { - return new ExcludingLookup(lookup, classes); - } - - /** Creates Lookup.Item representing the instance passed in. - * - * @param instance the object for which Lookup.Item should be creted - * @param id unique identification of the object, for details see {@link org.openide.util.Lookup.Item#getId}, - * can be null - * @return lookup item representing instance - * @since 4.8 - */ - public static Lookup.Item lookupItem(T instance, String id) { - return new LookupItem(instance, id); - } - - private static class LookupItem extends Lookup.Item { - private String id; - private T instance; - - public LookupItem(T instance) { - this(instance, null); - } - - public LookupItem(T instance, String id) { - this.id = id; - this.instance = instance; - } - - public String getDisplayName() { - return getId(); - } - - public String getId() { - return (id == null) ? instance.toString() : id; - } - - public T getInstance() { - return instance; - } - - @SuppressWarnings("unchecked") - public Class getType() { - return (Class)instance.getClass(); - } - - public @Override boolean equals(Object object) { - if (object instanceof LookupItem) { - return instance == ((LookupItem) object).getInstance(); - } - - return false; - } - - public @Override int hashCode() { - return instance.hashCode(); - } - } - // End of LookupItem class -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/MetaInfServicesLookup.java --- a/lookup/src/main/java/org/openide/util/lookup/MetaInfServicesLookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,573 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.openide.util.Lookup; - -/** - * @author Jaroslav Tulach, Jesse Glick - * @see Lookups#metaInfServices(ClassLoader,String) - * @see "#14722" - */ -final class MetaInfServicesLookup extends AbstractLookup { - - private static final Logger LOGGER = Logger.getLogger(MetaInfServicesLookup.class.getName()); - static final Executor RP; - static { - Executor res = null; - try { - Class seek = Class.forName("org.openide.util.RequestProcessor"); - res = (Executor)seek.newInstance(); - } catch (Throwable t) { - res = Executors.newSingleThreadExecutor(); - } - RP = res; - } - /*TBD: Inject RequestProcessor somehow - new RequestProcessor(MetaInfServicesLookup.class.getName(), 1); - */ - private static int knownInstancesCount; - private static final List> knownInstances; - static { - knownInstances = new ArrayList>(); - for (int i = 0; i < 512; i++) { - knownInstances.add(null); - } - } - - /** A set of all requested classes. - * Note that classes that we actually succeeded on can never be removed - * from here because we hold a strong reference to the loader. - * However we also hold classes which are definitely not loadable by - * our loader. - */ - private final Map classes = new WeakHashMap(); - - /** class loader to use */ - private final ClassLoader loader; - /** prefix to prepend */ - private final String prefix; - - /** Create a lookup reading from a specified classloader. - */ - public MetaInfServicesLookup(ClassLoader loader, String prefix) { - this.loader = loader; - this.prefix = prefix; - - LOGGER.log(Level.FINE, "Created: {0}", this); - } - - @Override - public String toString() { - return "MetaInfServicesLookup[" + loader + "]"; // NOI18N - } - - /* Tries to load appropriate resources from manifest files. - */ - @Override - protected final void beforeLookup(Lookup.Template t) { - Class c = t.getType(); - - Collection> toAdd = null; - synchronized (this) { - if (classes.get(c) == null) { // NOI18N - toAdd = new ArrayList>(); - } else { - // ok, nothing needs to be done - return; - } - } - if (toAdd != null) { - search(c, toAdd); - } - synchronized (this) { - if (classes.put(c, "") == null) { // NOI18N - // Added new class, search for it. - LinkedHashSet> arr = getPairsAsLHS(); - arr.addAll(toAdd); - setPairs(arr, RP); - } - } - } - - /** Finds all pairs and adds them to the collection. - * - * @param clazz class to find - * @param result collection to add Pair to - */ - private void search(Class clazz, Collection> result) { - if (LOGGER.isLoggable(Level.FINER)) { - LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this); - } - - String res = prefix + clazz.getName(); // NOI18N - Enumeration en; - - try { - en = loader.getResources(res); - } catch (IOException ioe) { - // do not use ErrorManager because we are in the startup code - // and ErrorManager might not be ready - ioe.printStackTrace(); - - return; - } - - // Do not create multiple instances in case more than one JAR - // has the same entry in it (and they load to the same class). - // Probably would not happen, assuming JARs only list classes - // they own, but just in case... - List foundClasses = new ArrayList(); - Collection removeClasses = new ArrayList(); - - boolean foundOne = false; - - while (en.hasMoreElements()) { - if (!foundOne) { - foundOne = true; - - // Double-check that in fact we can load the *interface* class. - // For example, say class I is defined in two JARs, J1 and J2. - // There is also an implementation M1 defined in J1, and another - // implementation M2 defined in J2. - // Classloaders C1 and C2 are made from J1 and J2. - // A MetaInfServicesLookup is made from C1. Then the user asks to - // lookup I as loaded from C2. J1 has the services line and lists - // M1, and we can in fact make it. However it is not of the desired - // type to be looked up. Don't do this check, which could be expensive, - // unless we expect to be getting some results, however. - Class realMcCoy = null; - - try { - realMcCoy = loader.loadClass(clazz.getName()); - } catch (ClassNotFoundException cnfe) { - // our loader does not know about it, OK - } - - if (realMcCoy != clazz) { - // Either the interface class is not available at all in our loader, - // or it is not the same version as we expected. Don't provide results. - if (LOGGER.isLoggable(Level.WARNING)) { - if (realMcCoy != null) { - LOGGER.log(Level.WARNING, - clazz.getName() + " is not the real McCoy! Actually found it in " + - realMcCoy.getClassLoader() - ); // NOI18N - } else { - LOGGER.log(Level.WARNING, clazz.getName() + " could not be found in " + loader); // NOI18N - } - } - - return; - } - } - - URL url = en.nextElement(); - Item currentItem = null; - - try { - InputStream is = url.openStream(); - - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N - - while (true) { - String line = reader.readLine(); - - if (line == null) { - break; - } - - line = line.trim(); - - // is it position attribute? - if (line.startsWith("#position=")) { - if (currentItem == null) { - LOGGER.log(Level.WARNING, "Found line '{0}' in {1} but there is no item to associate it with", new Object[] {line, url}); - continue; - } - - try { - currentItem.position = Integer.parseInt(line.substring(10)); - } catch (NumberFormatException e) { - // do not use ErrorManager because we are in the startup code - // and ErrorManager might not be ready - e.printStackTrace(); - } - } - - if (currentItem != null) { - insertItem(currentItem, foundClasses); - currentItem = null; - } - - // Ignore blank lines and comments. - if (line.length() == 0) { - continue; - } - - boolean remove = false; - - if (line.charAt(0) == '#') { - if ((line.length() == 1) || (line.charAt(1) != '-')) { - continue; - } - - // line starting with #- is a sign to remove that class from lookup - remove = true; - line = line.substring(2); - } - - Class inst = null; - - try { - // Most lines are fully-qualified class names. - inst = Class.forName(line, false, loader); - } catch (ClassNotFoundException cnfe) { - if (remove) { - // if we are removing somthing and the something - // cannot be found it is ok to do nothing - continue; - } else { - // but if we are not removing just rethrow - throw cnfe; - } - } - - if (!clazz.isAssignableFrom(inst)) { - throw new ClassNotFoundException(clazzToString(inst) + " not a subclass of " + clazzToString(clazz)); // NOI18N - } - - if (remove) { - removeClasses.add(inst); - } else { - // create new item here, but do not put it into - // foundClasses array yet because following line - // might specify its position - currentItem = new Item(); - currentItem.clazz = inst; - } - } - - if (currentItem != null) { - insertItem(currentItem, foundClasses); - currentItem = null; - } - } finally { - is.close(); - } - } catch (ClassNotFoundException ex) { - LOGGER.log(Level.WARNING, null, ex); - } catch (IOException ex) { - LOGGER.log(Level.WARNING, null, ex); - } - } - - LOGGER.log(Level.FINER, "Found impls of {0}: {1} and removed: {2} from: {3}", new Object[] {clazz.getName(), foundClasses, removeClasses, this}); - - foundClasses.removeAll(removeClasses); - - for (Item item : foundClasses) { - if (removeClasses.contains(item.clazz)) { - continue; - } - - result.add(new P(item.clazz)); - } - } - private static String clazzToString(Class clazz) { - return clazz.getName() + "@" + clazz.getClassLoader() + ":" + clazz.getProtectionDomain().getCodeSource().getLocation(); // NOI18N - } - - /** - * Insert item to the list according to item.position value. - */ - private void insertItem(Item item, List list) { - // no position? -> add it to the end - if (item.position == -1) { - list.add(item); - - return; - } - - int index = -1; - for (Item i : list) { - index++; - - if (i.position == -1) { - list.add(index, item); - - return; - } else { - if (i.position > item.position) { - list.add(index, item); - - return; - } - } - } - - list.add(item); - } - - private static class Item { - private Class clazz; - private int position = -1; - @Override - public String toString() { - return "MetaInfServicesLookup.Item[" + clazz.getName() + "]"; // NOI18N - } - } - - /** Pair that holds name of a class and maybe the instance. - */ - private static final class P extends AbstractLookup.Pair { - /** May be one of three things: - * 1. The implementation class which was named in the services file. - * 2. An instance of it. - * 3. Null, if creation of the instance resulted in an error. - */ - private Object object; - - public P(Class clazz) { - this.object = clazz; - } - - /** Finds the class. - */ - private Class clazz() { - Object o = object; - - if (o instanceof Class) { - return (Class) o; - } else if (o != null) { - return o.getClass(); - } else { - // Broken. - return Object.class; - } - } - - @Override - public boolean equals(Object o) { - if (o instanceof P) { - return ((P) o).clazz().equals(clazz()); - } - - return false; - } - - @Override - public int hashCode() { - return clazz().hashCode(); - } - - protected boolean instanceOf(Class c) { - return c.isAssignableFrom(clazz()); - } - - public Class getType() { - return clazz(); - } - - public Object getInstance() { - Object o = object; // keeping local copy to avoid another - - // thread to modify it under my hands - if (o instanceof Class) { - synchronized (o) { // o is Class and we will not create - // 2 instances of the same class - - try { - Class c = ((Class) o); - o = null; - - synchronized (knownInstances) { // guards only the static cache - int size = knownInstances.size(); - int index = c.hashCode() % size; - for (int i = 0; i < size; i++) { - Reference ref = knownInstances.get(index); - Object obj = ref == null ? null : ref.get(); - if (obj == null) { - break; - } - if (c == obj.getClass()) { - o = obj; - break; - } - if (++index == size) { - index = 0; - } - } - } - - if (o == null) { - o = createInstance(c); - - synchronized (knownInstances) { // guards only the static cache - hashPut(o); - - int size = knownInstances.size(); - if (knownInstancesCount > size * 2 / 3) { - LOGGER.log(Level.CONFIG, "Cache of size {0} is 2/3 full. Rehashing.", size); - HashSet> all = new HashSet>(); - all.addAll(knownInstances); - for (int i = 0; i < size; i++) { - knownInstances.set(i, null); - } - for (int i = 0; i < size; i++) { - knownInstances.add(null); - } - knownInstancesCount = 0; - for (Reference r : all) { - if (r == null) { - continue; - } - Object instance = r.get(); - if (instance == null) { - continue; - } - hashPut(instance); - } - } - - } - } - - // Do not assign to instance var unless there is a complete synch - // block between the newInstance and this line. Otherwise we could - // be assigning a half-constructed instance that another thread - // could see and return immediately. - object = o; - } catch (Exception ex) { - LOGGER.log(Level.WARNING, "Cannot create " + object, ex); - object = null; - } catch (ExceptionInInitializerError x) { // #174055 - LOGGER.log(Level.WARNING, "Cannot create " + object, x); - object = null; - } - } - } - - return object; - } - - public String getDisplayName() { - return clazz().getName(); - } - - public String getId() { - return clazz().getName(); - } - - protected boolean creatorOf(Object obj) { - return obj == object; - } - - private static void hashPut(Object o) { - Class c = o.getClass(); - int size = knownInstances.size(); - int index = c.hashCode() % size; - for (int i = 0; i < size; i++) { - Reference ref = knownInstances.get(index); - Object obj = ref == null ? null : ref.get(); - if (obj == null) { - knownInstances.set(index, new WeakReference(o)); - knownInstancesCount++; - break; - } - if (++index == size) { - index = 0; - } - } - } - - private static boolean findSharedClassObjectSkip; - private static Method findSharedClassObject; - /** Basically does c.newInstance(), however the method is complicated - * with a special behaviour for old and almost obsoleted NetBeans - * class: SharedClassObject. - */ - private static Object createInstance(Class c) throws InstantiationException, IllegalAccessException { - if (!findSharedClassObjectSkip) { - try { - if (findSharedClassObject == null) { - Class sco; - try { - sco = Class.forName("org.openide.util.SharedClassObject"); // NOI18N - } catch (ClassNotFoundException ex) { - findSharedClassObjectSkip = true; - return c.newInstance(); - } - findSharedClassObject = sco.getMethod("findObject", Class.class, boolean.class); - } - if (findSharedClassObject.getReturnType().isAssignableFrom(c)) { - return findSharedClassObject.invoke(null, c, true); - } - } catch (Exception problem) { - throw (InstantiationException)new InstantiationException(problem.getMessage()).initCause(problem); - } - } - return c.newInstance(); - } - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/ProxyLookup.java --- a/lookup/src/main/java/org/openide/util/lookup/ProxyLookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,980 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.Executor; -import javax.swing.event.EventListenerList; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; - -/** Implementation of lookup that can delegate to others. - * - * @author Jaroslav Tulach - * @since 1.9 - */ -public class ProxyLookup extends Lookup { - /** data representing the state of the lookup */ - private ImmutableInternalData data; - - /** Create a proxy to some other lookups. - * @param lookups the initial delegates - */ - public ProxyLookup(Lookup... lookups) { - data = ImmutableInternalData.EMPTY.setLookupsNoFire(lookups, true); - } - - /** - * Create a lookup initially proxying to no others. - * Permits serializable subclasses. - * @since 3.27 - */ - protected ProxyLookup() { - data = ImmutableInternalData.EMPTY; - } - - @Override - public synchronized String toString() { - return "ProxyLookup(class=" + getClass() + ")->" + Arrays.asList(getData().getLookups(false)); // NOI18N - } - - /** Getter for the delegates. - * @return the array of lookups we delegate to - * @since 1.19 - */ - protected final Lookup[] getLookups() { - synchronized (ProxyLookup.this) { - return getData().getLookups(true); - } - } - - private Set identityHashSet(Collection current) { - Map map = new IdentityHashMap(); - for (Lookup lookup : current) { - map.put(lookup, null); - } - return map.keySet(); - } - - /** - * Changes the delegates. - * - * @param lookups the new lookups to delegate to - * @since 1.19 protected - */ - protected final void setLookups(Lookup... lookups) { - setLookups(null, lookups); - } - - /** - * Changes the delegates immediatelly, notifies the listeners in provided - * executor, potentially later. - * - * @param lookups the new lookups to delegate to - * @param notifyIn executor to deliver the notification to listeners or null - * @since 7.16 - */ - protected final void setLookups(Executor notifyIn, Lookup... lookups) { - Collection> arr; - Set newL; - Set current; - Lookup[] old; - - Map toRemove = new IdentityHashMap(); - Map toAdd = new IdentityHashMap(); - - ImmutableInternalData orig; - synchronized (ProxyLookup.this) { - orig = getData(); - ImmutableInternalData newData = getData().setLookupsNoFire(lookups, false); - if (newData == getData()) { - return; - } - arr = setData(newData, lookups, toAdd, toRemove); - } - - // better to do this later than in synchronized block - for (Map.Entry e : toRemove.entrySet()) { - e.getKey().removeLookupListener(e.getValue()); - } - for (Map.Entry e : toAdd.entrySet()) { - e.getKey().addLookupListener(e.getValue()); - } - - - // this cannot be done from the synchronized block - final ArrayList evAndListeners = new ArrayList(); - for (Reference ref : arr) { - R r = ref.get(); - if (r != null) { - r.collectFires(evAndListeners); - } - } - - class Notify implements Runnable { - public void run() { - Iterator it = evAndListeners.iterator(); - while (it.hasNext()) { - LookupEvent ev = (LookupEvent)it.next(); - LookupListener l = (LookupListener)it.next(); - l.resultChanged(ev); - } - } - } - Notify n = new Notify(); - if (notifyIn == null) { - n.run(); - } else { - notifyIn.execute(n); - } - } - - /** Notifies subclasses that a query is about to be processed. - * Subclasses can update its state before the actual processing - * begins. It is allowed to call setLookups method - * to change/update the set of objects the proxy delegates to. - * - * @param template the template of the query - * @since 1.31 - */ - protected void beforeLookup(Template template) { - } - - public final T lookup(Class clazz) { - beforeLookup(new Template(clazz)); - - Lookup[] tmpLkps; - synchronized (ProxyLookup.this) { - tmpLkps = getData().getLookups(false); - } - - for (int i = 0; i < tmpLkps.length; i++) { - T o = tmpLkps[i].lookup(clazz); - - if (o != null) { - return o; - } - } - - return null; - } - - @Override - public final Item lookupItem(Template template) { - beforeLookup(template); - - Lookup[] tmpLkps; - synchronized (ProxyLookup.this) { - tmpLkps = getData().getLookups(false); - } - - for (int i = 0; i < tmpLkps.length; i++) { - Item o = tmpLkps[i].lookupItem(template); - - if (o != null) { - return o; - } - } - - return null; - } - - @SuppressWarnings("unchecked") - private static R convertResult(R r) { - return (R)r; - } - - public final Result lookup(Lookup.Template template) { - synchronized (ProxyLookup.this) { - ImmutableInternalData[] res = { null }; - R newR = getData().findResult(this, res, template); - setData(res[0], getData().getLookups(false), null, null); - return newR; - } - } - - /** Unregisters a template from the has map. - */ - private final void unregisterTemplate(Template template) { - synchronized (ProxyLookup.this) { - ImmutableInternalData id = getData(); - if (id == null) { - return; - } - setData(id.removeTemplate(this, template), getData().getLookups(false), null, null); - } - } - - private ImmutableInternalData getData() { - assert Thread.holdsLock(this); - return data; - } - - private Collection> setData( - ImmutableInternalData newData, Lookup[] current, - Map toAdd, Map toRemove - ) { - assert Thread.holdsLock(ProxyLookup.this); - assert newData != null; - - ImmutableInternalData previous = this.getData(); - - if (previous == newData) { - return Collections.emptyList(); - } - - if (newData.isEmpty()) { - this.setData(newData); - // no affected results => exit - return Collections.emptyList(); - } - - Collection> arr = newData.references(); - - Set removed = identityHashSet(previous.getLookupsList()); - Set currentSet = identityHashSet(Arrays.asList(current)); - Set newL = identityHashSet(currentSet); - removed.removeAll(currentSet); // current contains just those lookups that have disappeared - newL.removeAll(previous.getLookupsList()); // really new lookups - - for (Reference ref : arr) { - R r = ref.get(); - if (r != null) { - r.lookupChange(newData, current, previous, newL, removed, toAdd, toRemove); - if (this.getData() != previous) { - // the data were changed by an re-entrant call - // skip any other change processing, as it is not needed - // anymore - } - } - } - for (Reference ref : arr) { - R r = ref.get(); - if (r != null) { - r.data = newData; - } - } - this.setData(newData); - return arr; - } - - private void setData(ImmutableInternalData data) { - this.data = data; - } - - /** Result of a lookup request. Allows access to single object - * that was found (not too useful) and also to all objects found - * (more useful). - */ - private static final class R extends WaitableResult { - /** weak listener & result */ - private final WeakResult weakL; - - /** list of listeners added */ - private javax.swing.event.EventListenerList listeners; - - /** collection of Objects */ - private Collection[] cache; - - - /** associated lookup */ - private ImmutableInternalData data; - - /** Constructor. - */ - public R(ProxyLookup proxy, Lookup.Template t) { - this.weakL = new WeakResult(proxy, this, t); - } - - private ProxyLookup proxy() { - return weakL.result.proxy; - } - - @SuppressWarnings("unchecked") - private Result[] newResults(int len) { - return new Result[len]; - } - - @Override - protected void finalize() { - weakL.result.run(); - } - - /** initializes the results - */ - private Result[] initResults() { - BIG_LOOP: for (;;) { - Lookup[] myLkps; - ImmutableInternalData current; - synchronized (proxy()) { - if (weakL.getResults() != null) { - return weakL.getResults(); - } - myLkps = data.getLookups(false); - current = data; - } - - Result[] arr = newResults(myLkps.length); - - for (int i = 0; i < arr.length; i++) { - arr[i] = myLkps[i].lookup(weakL.result.template); - } - - synchronized (proxy()) { - if (current != data) { - continue; - } - - Lookup[] currentLkps = data.getLookups(false); - if (currentLkps.length != myLkps.length) { - continue BIG_LOOP; - } - for (int i = 0; i < currentLkps.length; i++) { - if (currentLkps[i] != myLkps[i]) { - continue BIG_LOOP; - } - } - - // some other thread might compute the result mean while. - // if not finish the computation yourself - if (weakL.getResults() != null) { - return weakL.getResults(); - } - - weakL.setResults(arr); - } - for (int i = 0; i < arr.length; i++) { - arr[i].addLookupListener(weakL); - } - return arr; - } - } - - /** Called when there is a change in the list of proxied lookups. - * @param added set of added lookups - * @param remove set of removed lookups - * @param current array of current lookups - */ - final void lookupChange( - ImmutableInternalData newData, Lookup[] current, ImmutableInternalData oldData, - Set added, Set removed, - Map toAdd, Map toRemove - ) { - if (weakL.getResults() == null) { - // not computed yet, do not need to do anything - return; - } - - Lookup[] old = oldData.getLookups(false); - - // map (Lookup, Lookup.Result) - Map> map = new IdentityHashMap>(old.length * 2); - - for (int i = 0; i < old.length; i++) { - if (removed.contains(old[i])) { - // removed lookup - if (toRemove != null) { - toRemove.put(weakL.getResults()[i], weakL); - } - } else { - // remember the association - map.put(old[i], weakL.getResults()[i]); - } - } - - Lookup.Result[] arr = newResults(current.length); - - for (int i = 0; i < current.length; i++) { - if (added.contains(current[i])) { - // new lookup - arr[i] = current[i].lookup(weakL.result.template); - if (toAdd != null) { - toAdd.put(arr[i], weakL); - } - } else { - // old lookup - arr[i] = map.get(current[i]); - - if (arr[i] == null) { - // assert - throw new IllegalStateException(); - } - } - } - - // remember the new results - weakL.setResults(arr); - } - - /** Just delegates. - */ - public void addLookupListener(LookupListener l) { - synchronized (proxy()) { - if (listeners == null) { - listeners = new EventListenerList(); - } - } - - listeners.add(LookupListener.class, l); - initResults(); - } - - /** Just delegates. - */ - public void removeLookupListener(LookupListener l) { - if (listeners != null) { - listeners.remove(LookupListener.class, l); - } - } - - /** Access to all instances in the result. - * @return collection of all instances - */ - @SuppressWarnings("unchecked") - public java.util.Collection allInstances() { - return computeResult(0); - } - - /** Classes of all results. Set of the most concreate classes - * that are registered in the system. - * @return set of Class objects - */ - @SuppressWarnings("unchecked") - @Override - public java.util.Set> allClasses() { - return (java.util.Set>) computeResult(1); - } - - /** All registered items. The collection of all pairs of - * ii and their classes. - * @return collection of Lookup.Item - */ - @SuppressWarnings("unchecked") - @Override - public java.util.Collection> allItems() { - return computeResult(2); - } - - /** Computes results from proxied lookups. - * @param indexToCache 0 = allInstances, 1 = allClasses, 2 = allItems - * @return the collection or set of the objects - */ - private java.util.Collection computeResult(int indexToCache) { - // results to use - Lookup.Result[] arr = myBeforeLookup(); - - // if the call to beforeLookup resulted in deletion of caches - synchronized (proxy()) { - Collection[] cc = getCache(); - if (cc != null && cc != NO_CACHE) { - Collection result = cc[indexToCache]; - if (result != null) { - return result; - } - } - } - - // initialize the collection to hold result - Collection compute; - Collection ret; - - if (indexToCache == 1) { - HashSet s = new HashSet(); - compute = s; - ret = Collections.unmodifiableSet(s); - } else { - List l = new ArrayList(arr.length * 2); - compute = l; - ret = Collections.unmodifiableList(l); - } - - // fill the collection - for (int i = 0; i < arr.length; i++) { - switch (indexToCache) { - case 0: - compute.addAll(arr[i].allInstances()); - break; - case 1: - compute.addAll(arr[i].allClasses()); - break; - case 2: - compute.addAll(arr[i].allItems()); - break; - default: - assert false : "Wrong index: " + indexToCache; - } - } - - - - synchronized (proxy()) { - Collection[] cc = getCache(); - if (cc == null || cc == NO_CACHE) { - // initialize the cache to indicate this result is in use - setCache(cc = new Collection[3]); - } - - if (arr == weakL.getResults()) { - // updates the results, if the results have not been - // changed during the computation of allInstances - cc[indexToCache] = ret; - } - } - - return ret; - } - - /** When the result changes, fire the event. - */ - public void resultChanged(LookupEvent ev) { - collectFires(null); - } - - protected void collectFires(Collection evAndListeners) { - boolean modified = true; - - try { - // clear cached instances - Collection oldItems; - Collection oldInstances; - synchronized (proxy()) { - final Collection[] cc = getCache(); - if (cc == NO_CACHE) { - return; - } - - oldInstances = cc == null ? null : cc[0]; - oldItems = cc == null ? null : cc[2]; - - - if (listeners == null || listeners.getListenerCount() == 0) { - // clear the cache - setCache(new Collection[3]); - return; - } - - // ignore events if they arrive as a result of call to allItems - // or allInstances, bellow... - setCache(NO_CACHE); - } - - if (oldItems != null) { - Collection newItems = allItems(); - if (oldItems.equals(newItems)) { - modified = false; - } - } else { - if (oldInstances != null) { - Collection newInstances = allInstances(); - if (oldInstances.equals(newInstances)) { - modified = false; - } - } else { - synchronized (proxy()) { - if (getCache() == NO_CACHE) { - // we have to initialize the cache - // to show that the result has been initialized - setCache(new Collection[3]); - } - } - } - } - } finally { - synchronized (proxy()) { - if (getCache() == NO_CACHE) { - setCache(null); - } - } - } - - if (modified) { - LookupEvent ev = new LookupEvent(this); - AbstractLookup.notifyListeners(listeners.getListenerList(), ev, evAndListeners); - } - } - - /** Implementation of my before lookup. - * @return results to work on. - */ - private Lookup.Result[] myBeforeLookup() { - Template template = weakL.result.template; - - proxy().beforeLookup(template); - - Lookup.Result[] arr = initResults(); - - // invoke update on the results - for (int i = 0; i < arr.length; i++) { - if (arr[i] instanceof WaitableResult) { - WaitableResult w = (WaitableResult) arr[i]; - w.beforeLookup(template); - } - } - - return arr; - } - - /** Used by proxy results to synchronize before lookup. - */ - protected void beforeLookup(Lookup.Template t) { - if (t.getType() == weakL.result.template.getType()) { - myBeforeLookup(); - } - } - - private Collection[] getCache() { - return cache; - } - - private void setCache(Collection[] cache) { - assert Thread.holdsLock(proxy()); - this.cache = cache; - } - private static final Collection[] NO_CACHE = new Collection[0]; - } - private static final class WeakRef extends WeakReference implements Runnable { - final WeakResult result; - final ProxyLookup proxy; - final Template template; - - public WeakRef(R r, WeakResult result, ProxyLookup proxy, Template template) { - super(r); - this.result = result; - this.template = template; - this.proxy = proxy; - } - - public void run() { - result.removeListeners(); - proxy.unregisterTemplate(template); - } - } - - - private static final class WeakResult extends WaitableResult implements LookupListener, Runnable { - /** all results */ - private Lookup.Result[] results; - private final WeakRef result; - - public WeakResult(ProxyLookup proxy, R r, Template t) { - this.result = new WeakRef(r, this, proxy, t); - } - - final void removeListeners() { - Lookup.Result[] arr = this.getResults(); - if (arr == null) { - return; - } - - for(int i = 0; i < arr.length; i++) { - arr[i].removeLookupListener(this); - } - } - - protected void beforeLookup(Lookup.Template t) { - R r = result.get(); - if (r != null) { - r.beforeLookup(t); - } else { - removeListeners(); - } - } - - protected void collectFires(Collection evAndListeners) { - R r = result.get(); - if (r != null) { - r.collectFires(evAndListeners); - } else { - removeListeners(); - } - } - - public void addLookupListener(LookupListener l) { - assert false; - } - - public void removeLookupListener(LookupListener l) { - assert false; - } - - public Collection allInstances() { - assert false; - return null; - } - - public void resultChanged(LookupEvent ev) { - R r = result.get(); - if (r != null) { - r.resultChanged(ev); - } else { - removeListeners(); - } - } - - @Override - public Collection> allItems() { - assert false; - return null; - } - - @Override - public Set> allClasses() { - assert false; - return null; - } - - public void run() { - removeListeners(); - } - - private Lookup.Result[] getResults() { - return results; - } - - private void setResults(Lookup.Result[] results) { - this.results = results; - } - } // end of WeakResult - - static abstract class ImmutableInternalData extends Object { - static final ImmutableInternalData EMPTY = new EmptyInternalData(); - static final Lookup[] EMPTY_ARR = new Lookup[0]; - - - protected ImmutableInternalData() { - } - - public static ImmutableInternalData create(Object lkp, Map> results) { - if (results.size() == 0 && lkp == EMPTY_ARR) { - return EMPTY; - } - if (results.size() == 1) { - Entry> e = results.entrySet().iterator().next(); - return new SingleInternalData(lkp, e.getKey(), e.getValue()); - } - - return new RealInternalData(lkp, results); - } - - protected abstract boolean isEmpty(); - protected abstract Map> getResults(); - protected abstract Object getRawLookups(); - - final Collection> references() { - return getResults().values(); - } - - final ImmutableInternalData removeTemplate(ProxyLookup proxy, Template template) { - if (getResults().containsKey(template)) { - HashMap> c = new HashMap>(getResults()); - Reference ref = c.remove(template); - if (ref != null && ref.get() != null) { - // seems like there is a reference to a result for this template - // thta is still alive - return this; - } - return create(getRawLookups(), c); - } else { - return this; - } - } - - R findResult(ProxyLookup proxy, ImmutableInternalData[] newData, Template template) { - assert Thread.holdsLock(proxy); - - Map> map = getResults(); - - Reference ref = map.get(template); - R r = (ref == null) ? null : ref.get(); - - if (r != null) { - newData[0] = this; - return convertResult(r); - } - - HashMap> res = new HashMap>(map); - R newR = new R(proxy, template); - res.put(template, new java.lang.ref.SoftReference(newR)); - newR.data = newData[0] = create(getRawLookups(), res); - return newR; - } - final ImmutableInternalData setLookupsNoFire(Lookup[] lookups, boolean skipCheck) { - Object l; - - if (!skipCheck) { - Lookup[] previous = getLookups(false); - if (previous == lookups) { - return this; - } - - if (previous.length == lookups.length) { - int same = 0; - for (int i = 0; i < previous.length; i++) { - if (lookups[i] != previous[i]) { - break; - } - same++; - } - if (same == previous.length) { - return this; - } - } - } - - if (lookups.length == 1) { - l = lookups[0]; - assert l != null : "Cannot assign null delegate"; - } else { - if (lookups.length == 0) { - l = EMPTY_ARR; - } else { - l = lookups.clone(); - } - } - - if (isEmpty() && l == EMPTY_ARR) { - return this; - } - - return create(l, getResults()); - } - final Lookup[] getLookups(boolean clone) { - Object l = this.getRawLookups(); - if (l instanceof Lookup) { - return new Lookup[] { (Lookup)l }; - } else { - Lookup[] arr = (Lookup[])l; - if (clone) { - arr = arr.clone(); - } - return arr; - } - } - final List getLookupsList() { - return Arrays.asList(getLookups(false)); - } - - } // end of ImmutableInternalData - - private static final class SingleInternalData extends ImmutableInternalData { - /** lookups to delegate to (either Lookup or array of Lookups) */ - private final Object lookups; - private final Template template; - private final Reference result; - - public SingleInternalData(Object lookups, Template template, Reference result) { - this.lookups = lookups; - this.template = template; - this.result = result; - } - - protected final boolean isEmpty() { - return false; - } - - protected Map> getResults() { - return Collections.singletonMap(template, result); - } - - protected Object getRawLookups() { - return lookups; - } - } - private static final class RealInternalData extends ImmutableInternalData { - /** lookups to delegate to (either Lookup or array of Lookups) */ - private final Object lookups; - - /** map of templates to currently active results */ - private final Map> results; - - public RealInternalData(Object lookups, Map> results) { - this.results = results; - this.lookups = lookups; - } - - protected final boolean isEmpty() { - return false; - } - - protected Map> getResults() { - boolean strict = false; - assert strict = true; - return strict ? Collections.unmodifiableMap(results) : results; - } - - protected Object getRawLookups() { - return lookups; - } - } - - private static final class EmptyInternalData extends ImmutableInternalData { - EmptyInternalData() { - } - - protected final boolean isEmpty() { - return true; - } - - protected Map> getResults() { - return Collections.emptyMap(); - } - - @Override - protected Object getRawLookups() { - return EMPTY_ARR; - } - } // end of EmptyInternalData -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/ServiceProvider.java --- a/lookup/src/main/java/org/openide/util/lookup/ServiceProvider.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2008 Sun Microsystems, Inc. - */ - -package org.openide.util.lookup; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.openide.util.Lookup; - -/** - * Declarative registration of a singleton service provider. - * By marking an implementation class with this annotation, - * you automatically register that implementation, normally in {@link Lookup#getDefault}. - * The class must be public and have a public no-argument constructor. - *

Example of usage: - *

- * package my.module;
- * import org.netbeans.spi.whatever.Thing;
- * import org.openide.util.lookup.ServiceProvider;
- * @ServiceProvider(service=Thing.class)
- * public class MyThing implements Thing {...}
- * 
- *

would result in a resource file META-INF/services/org.netbeans.spi.whatever.Thing - * containing the single line of text: my.module.MyThing - * @see Lookups#metaInfServices(ClassLoader) - * @since org.openide.util 7.20 - */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.TYPE) -public @interface ServiceProvider { - - /** - * The interface (or abstract class) to register this implementation under. - * It is an error if the implementation class is not in fact assignable to the interface. - *

If you need to register one class under multiple interfaces, use {@link ServiceProviders}. - *

Requests to look up the specified interface should result in this implementation. - * Requests for any other types may or may not result in this implementation even if the - * implementation is assignable to those types. - */ - Class service(); - - /** - * An optional position in which to register this service relative to others. - * Lower-numbered services are returned in the lookup result first. - * Services with no specified position are returned last. - */ - int position() default Integer.MAX_VALUE; - - /** - * An optional list of implementations (given as fully-qualified class names) which this implementation supersedes. - * If specified, those implementations will not be loaded even if they were registered. - * Useful on occasion to cancel a generic implementation and replace it with a more advanced one. - */ - String[] supersedes() default {}; - - /** - * An optional path to register this implementation in. - * For example, Projects/sometype/Nodes could be used. - * This style of registration would be recognized by {@link Lookups#forPath} - * rather than {@link Lookup#getDefault}. - */ - String path() default ""; - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/ServiceProviders.java --- a/lookup/src/main/java/org/openide/util/lookup/ServiceProviders.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2008 Sun Microsystems, Inc. - */ - -package org.openide.util.lookup; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Similar to {@link ServiceProvider} but permits multiple registrations of one class. - * @since org.openide.util 7.20 - */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.TYPE) -public @interface ServiceProviders { - - /** - * List of service provider registrations. - */ - ServiceProvider[] value(); - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/SimpleLookup.java --- a/lookup/src/main/java/org/openide/util/lookup/SimpleLookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,250 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util.lookup; - -import org.openide.util.Lookup; -import org.openide.util.LookupListener; - -import java.util.*; - - -/** - * Simple lookup implementation. It can be used to create temporary lookups - * that do not change over time. The result stores references to all objects - * passed in the constructor. Those objecst are the only ones returned as - * result. - * @author David Strupl - */ -class SimpleLookup extends org.openide.util.Lookup { - /** This variable is initialized in constructor and thus null - * value is not allowed as its value. */ - private Collection> allItems; - - /** - * Creates new Result object with supplied instances parameter. - * @param instances to be used to return from the lookup - */ - SimpleLookup(Collection instances) { - allItems = new ArrayList>(instances.size()); - - for (Iterator i = instances.iterator(); i.hasNext();) { - allItems.add(new InstanceContent.SimpleItem(i.next())); - } - } - - SimpleLookup(Collection keys, InstanceContent.Convertor conv) { - allItems = new ArrayList>(keys.size()); - - for (T item : keys) { - allItems.add(new InstanceContent.ConvertingItem(item, conv)); - } - } - - public String toString() { - return "SimpleLookup" + lookup(new Template(Object.class)).allInstances(); - } - - public Result lookup(Template template) { - if (template == null) { - throw new NullPointerException(); - } - - return new SimpleResult(template); - } - - public T lookup(Class clazz) { - for (Iterator i = allItems.iterator(); i.hasNext();) { - Object o = i.next(); - - if (o instanceof AbstractLookup.Pair) { - AbstractLookup.Pair p = (AbstractLookup.Pair)o; - if (p.instanceOf(clazz)) { - Object ret = p.getInstance(); - if (clazz.isInstance(ret)) { - return clazz.cast(ret); - } - } - } - } - return null; - } - - /** A method that defines matching between Item and Template. - * @param item the item to match - * @return true if item matches the template requirements, false if not - */ - private static boolean matches(Template t, AbstractLookup.Pair item) { - if (!AbstractLookup.matches(t, item, true)) { - return false; - } - - Class type = t.getType(); - - if ((type != null) && !type.isAssignableFrom(item.getType())) { - return false; - } - - return true; - } - - /** - * Result used in SimpleLookup. It holds a reference to the collection - * passed in constructor. As the contents of this lookup result never - * changes the addLookupListener and removeLookupListener are empty. - */ - private class SimpleResult extends Lookup.Result { - /** can be null and is initialized lazily */ - private Set> classes; - - /** can be null and is initialized lazily */ - private Collection> items; - - /** Template used for this result. It is never null.*/ - private Template template; - - /** can be null and is initialized lazily */ - private Collection results; - - /** Just remembers the supplied argument in variable template.*/ - SimpleResult(Template template) { - this.template = template; - } - - /** - * Intentionally does nothing because the lookup does not change - * and no notification is needed. - */ - public void addLookupListener(LookupListener l) { - } - - /** - * Intentionally does nothing because the lookup does not change - * and no notification is needed. - */ - public void removeLookupListener(LookupListener l) { - } - - /** - * Lazy initializes the results collection. Uses a call to allItems - * to obtain the instances. - */ - public java.util.Collection allInstances() { - synchronized (this) { - if (results != null) { - return results; - } - } - - - Collection res = new ArrayList(allItems.size()); - - for (Item item : allItems()) { - res.add(item.getInstance()); - } - - synchronized (this) { - results = Collections.unmodifiableCollection(res); - } - - return results; - } - - /** - * Lazy initializes variable classes. Uses a call to allItems to - * compute the result. - */ - public Set> allClasses() { - synchronized (this) { - if (classes != null) { - return classes; - } - } - - Set> res = new HashSet>(); - - for (Item item : allItems()) { - res.add(item.getType()); - } - - synchronized (this) { - classes = Collections.unmodifiableSet(res); - } - - return classes; - } - - /** - * Lazy initializes variable items. Creates an item for each - * element in the instances collection. It puts either SimpleItem - * or ConvertingItem to the collection. - */ - public Collection> allItems() { - synchronized (this) { - if (items != null) { - return items; - } - } - - Collection> res = new ArrayList>(allItems.size()); - - for (Iterator> i = allItems.iterator(); i.hasNext();) { - Item o = i.next(); - - if (o instanceof AbstractLookup.Pair) { - if (matches(template, (AbstractLookup.Pair) o)) { - res.add(cast(o)); - } - } - } - - synchronized (this) { - items = Collections.unmodifiableCollection(res); - } - - return items; - } - - @SuppressWarnings("unchecked") - private Item cast(Item i) { - return (Item)i; - } - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/SimpleProxyLookup.java --- a/lookup/src/main/java/org/openide/util/lookup/SimpleProxyLookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,359 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util.lookup; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; - -import java.util.*; - - -/** - * Simple proxy lookup. Keeps reference to a lookup it delegates to and - * forwards all requests. - * - * @author Jaroslav Tulach - */ -final class SimpleProxyLookup extends org.openide.util.Lookup { - /** the provider to check for the status */ - private Provider provider; - - /** the lookup we currently delegate to */ - private Lookup delegate; - - /** map of all templates to Reference (results) associated to this lookup */ - private WeakHashMap,Reference>> results; - - /** - * @param provider provider to delegate to - */ - SimpleProxyLookup(Provider provider) { - this.provider = provider; - } - - /** Checks whether we still delegate to the same lookup */ - private Lookup checkLookup() { - Lookup l = provider.getLookup(); - - // iterator over Reference (ProxyResult) - Iterator>> toCheck = null; - - synchronized (this) { - if (l != delegate) { - this.delegate = l; - - if (results != null) { - toCheck = new ArrayList>>(results.values()).iterator(); - } - } - } - - if (toCheck != null) { - // update - ArrayList evAndListeners = new ArrayList(); - for (Iterator>> it = toCheck; it.hasNext(); ) { - java.lang.ref.Reference> ref = it.next(); - if (ref == null) { - continue; - } - - ProxyResult p = ref.get(); - - if (p != null && p.updateLookup(l)) { - p.collectFires(evAndListeners); - } - } - - for (Iterator it = evAndListeners.iterator(); it.hasNext(); ) { - LookupEvent ev = (LookupEvent)it.next(); - LookupListener ll = (LookupListener)it.next(); - ll.resultChanged(ev); - } - } - - return delegate; - } - - @SuppressWarnings("unchecked") - private static ProxyResult cast(ProxyResult p) { - return (ProxyResult)p; - } - - public Result lookup(Template template) { - synchronized (this) { - if (results == null) { - results = new WeakHashMap,Reference>>(); - } else { - Reference> ref = results.get(template); - - if (ref != null) { - ProxyResult p = ref.get(); - - if (p != null) { - return cast(p); - } - } - } - - ProxyResult p = new ProxyResult(template); - Reference> ref = new WeakReference>(p); - results.put(template, ref); - - return p; - } - } - - public T lookup(Class clazz) { - if (clazz == null) { - checkLookup(); - return null; - } - return checkLookup().lookup(clazz); - } - - public Item lookupItem(Template template) { - return checkLookup().lookupItem(template); - } - - /** - * Result used in SimpleLookup. It holds a reference to the collection - * passed in constructor. As the contents of this lookup result never - * changes the addLookupListener and removeLookupListener are empty. - */ - private final class ProxyResult extends WaitableResult implements LookupListener { - /** Template used for this result. It is never null.*/ - private Template template; - - /** result to delegate to */ - private Lookup.Result delegate; - - /** listeners set */ - private javax.swing.event.EventListenerList listeners; - private LookupListener lastListener; - - /** Just remembers the supplied argument in variable template.*/ - ProxyResult(Template template) { - this.template = template; - } - - /** Checks state of the result - */ - private Result checkResult() { - updateLookup(checkLookup()); - - return this.delegate; - } - - /** Updates the state of the lookup. - * @return true if the lookup really changed - */ - public boolean updateLookup(Lookup l) { - Collection> oldPairs = (delegate != null) ? delegate.allItems() : null; - - LookupListener removedListener; - - synchronized (this) { - if ((delegate != null) && (lastListener != null)) { - removedListener = lastListener; - delegate.removeLookupListener(lastListener); - } else { - removedListener = null; - } - } - - // cannot call to foreign code - Lookup.Result res = l.lookup(template); - - synchronized (this) { - if (removedListener == lastListener) { - delegate = res; - lastListener = new WeakResult(this, delegate); - delegate.addLookupListener(lastListener); - } - } - - if (oldPairs == null) { - // nobody knows about a change - return false; - } - - Collection> newPairs = delegate.allItems(); - - // See #34961 for explanation. - if (!(oldPairs instanceof List)) { - if (oldPairs == Collections.EMPTY_SET) { - // avoid allocation - oldPairs = Collections.emptyList(); - } else { - oldPairs = new ArrayList>(oldPairs); - } - } - - if (!(newPairs instanceof List)) { - newPairs = new ArrayList>(newPairs); - } - - return !oldPairs.equals(newPairs); - } - - public synchronized void addLookupListener(LookupListener l) { - if (listeners == null) { - listeners = new javax.swing.event.EventListenerList(); - } - - listeners.add(LookupListener.class, l); - } - - public synchronized void removeLookupListener(LookupListener l) { - if (listeners != null) { - listeners.remove(LookupListener.class, l); - } - } - - public java.util.Collection allInstances() { - return checkResult().allInstances(); - } - - public Set> allClasses() { - return checkResult().allClasses(); - } - - public Collection> allItems() { - return checkResult().allItems(); - } - - protected void beforeLookup(Lookup.Template t) { - Lookup.Result r = checkResult(); - - if (r instanceof WaitableResult) { - ((WaitableResult) r).beforeLookup(t); - } - } - - /** A change in lookup occured. - * @param ev event describing the change - * - */ - public void resultChanged(LookupEvent anEvent) { - collectFires(null); - } - - protected void collectFires(Collection evAndListeners) { - javax.swing.event.EventListenerList l = this.listeners; - - if (l == null) { - return; - } - - Object[] listeners = l.getListenerList(); - - if (listeners.length == 0) { - return; - } - - LookupEvent ev = new LookupEvent(this); - AbstractLookup.notifyListeners(listeners, ev, evAndListeners); - } - } - // end of ProxyResult - private final class WeakResult extends WaitableResult implements LookupListener { - private Lookup.Result source; - private Reference> result; - - public WeakResult(ProxyResult r, Lookup.Result s) { - this.result = new WeakReference>(r); - this.source = s; - } - - protected void beforeLookup(Lookup.Template t) { - ProxyResult r = (ProxyResult)result.get(); - if (r != null) { - r.beforeLookup(t); - } else { - source.removeLookupListener(this); - } - } - - protected void collectFires(Collection evAndListeners) { - ProxyResult r = result.get(); - if (r != null) { - r.collectFires(evAndListeners); - } else { - source.removeLookupListener(this); - } - } - - public void addLookupListener(LookupListener l) { - assert false; - } - - public void removeLookupListener(LookupListener l) { - assert false; - } - - public Collection allInstances() { - assert false; - return null; - } - - public void resultChanged(LookupEvent ev) { - ProxyResult r = (ProxyResult)result.get(); - if (r != null) { - r.resultChanged(ev); - } else { - source.removeLookupListener(this); - } - } - - public Collection> allItems() { - assert false; - return null; - } - - public Set> allClasses() { - assert false; - return null; - } - } // end of WeakResult -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/SingletonLookup.java --- a/lookup/src/main/java/org/openide/util/lookup/SingletonLookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2008 Sun Microsystems, Inc. - */ - -package org.openide.util.lookup; - -import java.util.Collection; -import java.util.Collections; -import java.util.Set; -import org.openide.util.Lookup; -import org.openide.util.LookupListener; - -/** - * Unmodifiable lookup that contains just one fixed object. - * - * @author Marian Petras - */ -class SingletonLookup extends Lookup { - - private final Object objectToLookup; - private final String id; - - SingletonLookup(Object objectToLookup) { - this(objectToLookup, null); - } - - SingletonLookup(Object objectToLookup, String id) { - if (objectToLookup == null) { - throw new IllegalArgumentException("null"); //NOI18N - } - - this.objectToLookup = objectToLookup; - this.id = id; - } - - @Override - public T lookup(Class clazz) { - if (clazz == null) { - throw new IllegalArgumentException("null"); //NOI18N - } - - return (clazz.isInstance(objectToLookup)) - ? clazz.cast(objectToLookup) - : null; - } - - @Override - public Result lookup(Template template) { - if (template == null) { - throw new IllegalArgumentException("null"); //NOI18N - } - - Lookup.Item item = lookupItem(template); - if (item != null) { - return new SingletonResult(item); - } else { - return Lookup.EMPTY.lookup(template); - } - } - - @Override - public Collection lookupAll(Class clazz) { - if (clazz == null) { - throw new IllegalArgumentException("null"); //NOI18N - } - - return (clazz.isInstance(objectToLookup)) - ? Collections.singletonList(clazz.cast(objectToLookup)) - : Collections.emptyList(); - } - - @Override - @SuppressWarnings("unchecked") - public Item lookupItem(Template template) { - if (template == null) { - throw new IllegalArgumentException("null"); //NOI18N - } - - String templateId = template.getId(); - if ((templateId != null) && !templateId.equals(id)) { - return null; - } - - Object templateInst = template.getInstance(); - if ((templateInst != null) && (objectToLookup != templateInst)) { - return null; - } - - Class clazz = template.getType(); - if ((clazz != null) && !clazz.isInstance(objectToLookup)) { - return null; - } - - Lookup.Item item; - if (clazz != null) { - item = Lookups.lookupItem(clazz.cast(objectToLookup), id); - } else { - item = Lookups.lookupItem((T) objectToLookup, id); - } - return item; - } - - static class SingletonResult extends Lookup.Result { - - private final Lookup.Item item; - - SingletonResult(Lookup.Item item) { - this.item = item; - } - - @Override - public void addLookupListener(LookupListener l) { - // this result never changes - no need to register a listener - } - - @Override - public void removeLookupListener(LookupListener l) { - // this result never changes - no need to register a listener - } - - @Override - public Set> allClasses() { - return Collections.>singleton(item.getType()); - } - - @Override - public Collection> allItems() { - return Collections.singletonList(item); - } - - @Override - public Collection allInstances() { - return Collections.singletonList(item.getInstance()); - } - - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/WaitableResult.java --- a/lookup/src/main/java/org/openide/util/lookup/WaitableResult.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util.lookup; - -import java.util.Collection; -import org.openide.util.Lookup; - - -/** A special subclass of lookup that is able to wait before queries. - * - * @author Jaroslav Tulach - */ -abstract class WaitableResult extends Lookup.Result { - /** Used by proxy results to synchronize before lookup. - */ - protected abstract void beforeLookup(Lookup.Template t); - - /** Needed to group notification of outside the package listeners - * after all AbstractLookup and ProxyLookups have been updated. - * @param evAndListeners LookupEvent, LookupListener, LookupEvent, LookupListener, etc. - */ - protected abstract void collectFires(Collection evAndListeners); - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/doc-files/index.html --- a/lookup/src/main/java/org/openide/util/lookup/doc-files/index.html Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,208 +0,0 @@ - - - - -Lookup Library - - - - -

- -This is the home page of the lookup library implementation, which -is intended to solve a general problem that every component-based system -has had to face: how different components register to the system -and how other parts of the system can look them up. -

-There already are libraries trying to solve this problem, usually by querying for -an interface and finding its appropriate implementaion. The most famous is -Jini, the platform for development of -distributed network services. Our library does something similar, but tries -to stay small and easy -to use. The NetBeans Lookup -Library's main focus is a modular application consisting of independent modules -that want to communicate with each other. It does not try to solve networking or -legacy application integration. It is simple but powerful. - -

Why would you want to use it?

- -A well-written modular program separates development -and deployment. -There are many situations where a component needs some functionality but -does not actually care about the implementation. It is up to the system -adminstrator that deploys (installs) the application to decide which -implementation to use. -

-The most simple and most often used method for allowing other implementations -to be plugged in is the system property pattern: - -

-    public Toolkit getDefaultToolkit () {
-        java.awt.Toolkit t = null;
-        String classname = System.getProperty ("java.awt.Toolkit");
-        if (classname != null) {
-            try {
-                Class c = Class.forName (classname);
-                t = (java.awt.Toolkit)c.newInstance ();
-            } catch (Exception ex) {
-                System.out.println ("Cannot initialize toolkit: " + classname);
-                ex.printStackTrace ();
-            }
-        }
-        // fallback 
-        if (t == null) {
-            t = new GenericAWTToolkit ();
-        }
-    }
-
- - -The idea is simple. The deployer can start the Java VM with the flag --Djava.awt.Toolkit=org.myorg.MyToolkit where the MyToolkit -is his class with default constructor and the code in the getDefaultToolkit -method will instantiate the class and use it. -

-In principle this is general enough of a solution and works well, except that writing the -code above is error prone and it also requires passing the arguments to the virtual machine. -It would be much nicer if the registation could be done just by putting a JAR file with the MyToolkit class -into the application classpath. -

-Actually this has been realized also by the JDK development team and addressed in -JDK 1.3 as part of the provider extension mechanism. -The MyToolkit could be registered by adding a file -/META-INF/services/java.awt.Toolkit with one line -org.myorg.MyToolkit into the JAR file that contains the -MyToolkit implementation. The code in getDefaultToolkit -will scan all JAR files in classpath and search for that file, -create an instance of MyToolkit and use it. -The deployer can influence which toolkit will be created by -adding the right JAR files into the classpath. -

-Of course the code to access the META-INF/services/ files is even -more error prone than the property pattern. And this is exactly the -place where the lookup library can help. It provides an implementation of -the search algorithm with an easy interface. Just write: -

-    import java.awt.Toolkit;
-    import org.openide.util.Lookup;;
-    Toolkit t = (Toolkit)Lookup.getDefault().lookup(Toolkit.class);
-
-and if the JAR with MyToolkit is in the class path, the simple call -above will do the rest. -

-So whenever one writes an application divided into several independent modules (jar files) -that are being developed and deployed independently, there is a need for registering -and discovering components. First of all, a set of interfaces can be defined to enable -inter-module communication (like the abstract class java.awt.Toolkit). -After that a set of modules providing implementation can written (MyToolkit and other concurent implementations) -and after that, whenever a module trying to utilitize the functionality wants to access -the Toolkit via lookup, the real implementation is returned. -

-It is the responsibility of lookup to find a suitable implementation of the -requested service and return an object implementing the service. This is the -the basic functionality and while the library provides you with a little bit -more, even this simple usage might be extremaly useful: the client code knows -nothing about the implementation and the implementation can be switched in -deployment time by simply replacing one implementation jar with other. There -is no code change required. - -

Local lookup usage

-The example in previous paragraph demostrated the usage of lookup as a global -registry (by using the Lookup.getDefault() call). One can also -consider another scenario where the lookup can help. -

-Let's switch hats to be an API designer for a while. The goal is to introduce a -new object into the system. But you either are not sure yet what all the roles -of the new object will be or you (more importantly) want to be able to add (or -change) roles of the object dynamically. So why not to introduce following -method to the object's interface: -

-public class  MorphingObject {
-    public Lookup getLookup() {
-        return myLookup;
-    }
-    ...
-}
-
-By exposing the method getLookup you can attach different functionality to the -MorphingObject at runtime and whoever gets a reference to your object can ask it -whether the object supports a given interface like this: -
-MorphingObject morph = ...
-AnInterface impl = (AnInterface)morph.getLookup().lookup(AnInterface.class);
-if (impl == null) {
-    return;/* AnInterface not supported now! */
-}
-impl.useIt();
-
- -

Additional functionality

-The NetBeans lookup library also provides: -
    -
  • Support for dynamically changing the lookup content.
  • -
  • The ability to return multiple results.
  • -
  • Notification of changes. After retrieving the result, the client can attach a -listener and be notified when the result of the lookup is changed.
  • -
  • Lazy initialization of the implementation. The implementation objects are -initialized only after someone asks for them. Even the implementation classes -are not loaded if they are not going to be used!
  • -
- -

Further information

- - - diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/doc-files/lookup-api.html --- a/lookup/src/main/java/org/openide/util/lookup/doc-files/lookup-api.html Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ - - - - -Lookup Library API - - - -

Lookup library API

-

-This document describes usage of the API provided by the Lookup Library. In this -document we assume that someone has already provided us with a lookup -implementation (for those seeking how to write a lookup implementation please -check the SPI document). - -

Getting the lookup

- -The first question you might ask is this: how can I get hold of a -lookup instance? There are basically two ways how you can get it. - -

Global lookup

-As you can see in the - -Lookup - -Javadoc there is a static method - -
public static Lookup getDefault()
- -The object returned from this method is -a global lookup that can serve as a central place for registering services. -The default implementation is a lookup that implements - -the JDK JAR services -mechanism and delegates to META-INF/services/name.of.Class files. -

-If you want to add your class to this lookup just create a file in your -jar file under the META-INF directory (e.g. META-INF/services/com.my.APIClass) -and let the file contain only one line of text - -

com.foo.impl.ImplOfTheAPI
- -

(This is more easily done using the @ServiceProvider annotation.)

- -The following code will return you a newly created instance of -com.foo.impl.ImplOfTheAPI: - -
-   import org.openide.util.Lookup;
-   return Lookup.getDefault().lookup(com.my.APIClass.class);
-
- -

Local lookup

- -This is just a reminder that whenever you find a method called getLookup -or similar returning a lookup instance, the provided lookup is not the -general lookup described in the previous paragraph. Rather, it is a private lookup -implementation that is usually bound to the object you invoked the method on. - -

Use of Lookup.Template and Lookup.Result

- -There are more ways how you can ask lookup besides the variant with one class -parameter. If you want more functionality, you have to implement the interface -Lookup.Template and pass an instance of such object to the lookup call. -

-Note: If you use Lookup.Template, the object returned from the lookup is -not the object you are looking for but rather a result object -(Lookup.Result). You can call methods on such a result object to get the actual -results. -

-Let's examine following example: - -

-        import org.openide.util.Lookup;
-
-        Lookup lookup = ...;
-        Lookup.Template template = new Lookup.Template(MyService.class);
-        Lookup.Result result = lookup.lookup(template);
-        Collection c = result.allInstances();
-        for (Iterator i = c.iterator(); i.hasNext(); ) {
-            MyService s = (MyService)i.next();
-            s.callMyService();
-        }
-
- -In this example the call to method lookup(...) returns immediately because the -result object can be constructed even without real results. The first time you -ask for the result object by calling r.allInstances(), the lookup has to supply you -the real results and this method can block until the required data are really -available. -

-If you are not interested in all objects as in the previous example, you can use the -template to ask for one resulting object (wrapped in special Item instance): -

-        import org.openide.util.Lookup;
-
-        Lookup lookup = ...;
-        Lookup.Template template = new Lookup.Template(MyService.class);
-        Lookup.Item item = lookup.lookupItem(template);
-        MyService s = (MyService)item.getInstance();
-        s.callMyService();
-
- -Again, the Item object can construct the real instance only if you call -getInstance. The item can be useful even without calling getInstance - you can get -its display name or an unique id. You can use this information, for example, for -constructing menu items without the need to instantiate (or even load!) -the class implementing the functionality. Only when the real functionality is -needed (e.g. the user has selected the menu item) you can call getInstance -and call the real meat of the implementation. - -

Listenning on lookup changes

-There is one additional piece of functionality bound to the Lookup.Result object worth -mentioning: you can attach a listener to it and be informed about any changes in -the lookup. This might be extremly usefull when the lookup dynamically changes -(from other threads). The listener can keep state of your object up-to-date even -in cases where the lookup changes asynchronously. -

-So here is some sample code using the listenner: - -

-        import org.openide.util.Lookup;
-        import org.openide.util.LookupListener;
-        import org.openide.util.LookupEvent;
-
-        Lookup lookup = ...;
-        Lookup.Template template = new Lookup.Template(MyService.class);
-        final Lookup.Result result = lookup.lookup(template);
-        result.addLookupListener(new LookupListener() {
-            public void resultChanged(LookupEvent e) {
-                reaction(result);
-            }
-        });
-        reaction(result);
-    }
-    private static void reaction(Lookup.Result r) {
-        for (Iterator i = r.allInstances().iterator(); i.hasNext(); ) {
-            MyService s = (MyService)i.next();
-            s.callMyService();
-        }
-    }
-
- -Please note that we first attach a listener and then call the reaction method. -This ensures that we always get the newest possible state. Also you must be -careful in the reaction method since it can be called from two different -threads simultaneously (your code has to be prepared for this). - - diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/doc-files/lookup-spi.html --- a/lookup/src/main/java/org/openide/util/lookup/doc-files/lookup-spi.html Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ - - - - -Lookup Library SPI - - - -

Lookup library SPI

-This document describe usage of the SPI provided by the Lookup Library -(for those seeking how to use lookup instance please -check the API document). -

-By using the SPI you can create lookups that can be used by the users of the -Lookup API. While the Lookup API consists of a couple of classes in the package -org.openide.util.*, -the SPI has its own package org.openide.util.lookup.*. - -

Simple lookups

-Let us start with the simplest case. You have decided that your newly created -object will provide an API in the form of a getLookup() method. You have to -return a functional lookup from this call. You can use static methods in class - -Lookups to create a lookup for you. If you want only one -object to be returned, just call - -Lookups.singleton(x) where x is the object to be -returned by the lookup. Or if you want to supply more objects, use a call to the method - -fixed(Object []x). - Note: The lookups returned from methods singleton(...) and -fixed(...) do -not support dynamic changes and attaching listeners. Their content is -fixed from the time you call the creating method. - -

ProxyLookup

-There can be situations where you get a lookup object from someone else and you -want your lookup to return exactly the instances from the original lookup plus -your own results. Here the class ProxyLookup comes into the play. -

-You simply create a new lookup like this: - -

-    import org.openide.util.Lookup;
-    import org.openide.util.lookup.*;
-
-    Lookup lookup1 = ...;
-
-    Lookup lookup2 = Lookups.singleton(MyService.class);
-    return new ProxyLookup(new Lookup[] { lookup, lookup2 });
-
- -

AbstractLookup

- - -

The most powerful way to provide a lookup is to directly define -what instances and items it should provide, by subclassing. For this, - -AbstractLookup - -is recommended as it is easiest to use. - -

The simplest way to use AbstractLookup is to use its -public constructor (in which case you need not subclass it). Here you -provide an - -AbstractLookup.Content - -object which you have created and hold on to privately, and which -keeps track of instances and permits them to be registered and -deregistered. Often - -InstanceContent - -is used as the content implementation. To add something to the lookup, -simply use - -add(Object) - -(and remove(Object) for the reverse). These may be called -at any time and will update the set of registered instances (firing -result changes as needed). - -

-    import org.openide.util.lookup.*;
-    InstanceContent ic = new InstanceContent ();
-    ic.add(firstObject);
-    return new AbstractLookup (ic);
-
- -

In case it is expensive to actually compute the object in the -lookup, but there is some cheap "key" which can easily generate it, -you may instead register the key by passing in an - -InstanceContent.Convertor. - -This convertor translates the key to the real instance that the lookup -client sees, if and when needed. For example, if you have a long list -of class names and wish to register default instances of each class, -you might actually register the class name as the key, and supply a -convertor which really loads the class and instantiates it. This makes -it easy to set up the lookup, but nothing is really loaded until -someone asks for it. - - - diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/lookup/package.html --- a/lookup/src/main/java/org/openide/util/lookup/package.html Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ - - - - -Support classes for the Registration and {@link org.openide.util.Lookup} extension mechanism. -Read more: Lookup Library - - diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/java/org/openide/util/package.html --- a/lookup/src/main/java/org/openide/util/package.html Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ - - - - - -Client API part of the -Lookup -interfaces. - - - diff -r b3ae88304dd0 -r a2947558c966 lookup/src/main/resources/META-INF/services/javax.annotation.processing.Processor --- a/lookup/src/main/resources/META-INF/services/javax.annotation.processing.Processor Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -org.netbeans.modules.openide.util.ServiceProviderProcessor diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/bar/Comparator2.java --- a/lookup/src/test/java/org/bar/Comparator2.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ - -package org.bar; - -public class Comparator2 implements java.util.Comparator { - public int compare(Object o1, Object o2) {return 0;} - public boolean equals(Object obj) {return true;} -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/bar/Comparator3.java --- a/lookup/src/test/java/org/bar/Comparator3.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ - -package org.bar; - -public class Comparator3 implements java.util.Comparator { - public int compare(Object o1, Object o2) {return 0;} - public boolean equals(Object obj) {return true;} -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/bar/Implementation2.java --- a/lookup/src/test/java/org/bar/Implementation2.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -package org.bar; -import org.foo.Interface; -public class Implementation2 implements Interface {} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/bar/Iterator2.java --- a/lookup/src/test/java/org/bar/Iterator2.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ - -package org.bar; - -public class Iterator2 implements java.util.Iterator { - public boolean hasNext() {return false;} - - public Object next() {return null;} - - public void remove() {} - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/foo/Interface.java --- a/lookup/src/test/java/org/foo/Interface.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -package org.foo; -public interface Interface {} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/foo/impl/Comparator1.java --- a/lookup/src/test/java/org/foo/impl/Comparator1.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ - -package org.foo.impl; - -public class Comparator1 implements java.util.Comparator { - public int compare(Object o1, Object o2) {return 0;} - public boolean equals(Object obj) {return true;} -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/foo/impl/Implementation1.java --- a/lookup/src/test/java/org/foo/impl/Implementation1.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -package org.foo.impl; -import org.foo.Interface; -public class Implementation1 implements Interface {} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/foo/impl/Iterator1.java --- a/lookup/src/test/java/org/foo/impl/Iterator1.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ - -package org.foo.impl; - -public class Iterator1 implements java.util.Iterator { - public boolean hasNext() {return false;} - - public Object next() {return null;} - - public void remove() {} - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/foo/impl/Runnable1.java --- a/lookup/src/test/java/org/foo/impl/Runnable1.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ - -package org.foo.impl; - -public class Runnable1 implements Runnable { - public void run () {} -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/netbeans/modules/openide/util/ActiveQueueTest.java --- a/lookup/src/test/java/org/netbeans/modules/openide/util/ActiveQueueTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2009 Sun Microsystems, Inc. - */ - -package org.netbeans.modules.openide.util; - -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.net.URL; -import java.net.URLClassLoader; -import org.netbeans.junit.NbTestCase; - -/** - * - * @author Jaroslav Tulach - */ -public class ActiveQueueTest extends NbTestCase{ - - public ActiveQueueTest(String name) { - super(name); - } - - public void testMemoryLeak() throws Exception { - final Class u1 = ActiveQueue.class; - class L extends URLClassLoader { - public L() { - super(new URL[] {u1.getProtectionDomain().getCodeSource().getLocation()}, u1.getClassLoader().getParent()); - } - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (name.equals(u1.getName()) || name.startsWith(u1.getName() + "$")) { - Class c = findLoadedClass(name); - if (c == null) { - c = findClass(name); - } - if (resolve) { - resolveClass(c); - } - return c; - } else { - return super.loadClass(name, resolve); - } - } - } - ClassLoader l = new L(); - Class u2 = l.loadClass(u1.getName()); - assertEquals(l, u2.getClassLoader()); - Object obj = new Object(); - @SuppressWarnings("unchecked") - ReferenceQueue q = (ReferenceQueue) u2.getMethod("queue").invoke(null); - RunnableRef ref = new RunnableRef(obj, q); - synchronized (ref) { - obj = null; - assertGC("Ref should be GC'ed as usual", ref); - ref.wait(); - assertTrue("Run method has been executed", ref.executed); - } - Reference r = new WeakReference(u2); - q = null; - u2 = null; - l = null; - assertGC("#86625: Utilities.class can also be collected now", r); - } - - - private static class RunnableRef extends WeakReference - implements Runnable { - public boolean wait; - public boolean entered; - public boolean executed; - - public RunnableRef (Object o) { - this(o, ActiveQueue.queue()); - } - - public RunnableRef(Object o, ReferenceQueue q) { - super(o, q); - } - - public synchronized void run () { - entered = true; - if (wait) { - // notify we are here - notify (); - try { - wait (); - } catch (InterruptedException ex) { - } - } - executed = true; - - notifyAll (); - } - } - -} \ No newline at end of file diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/netbeans/modules/openide/util/ServiceProviderProcessorTest.java --- a/lookup/src/test/java/org/netbeans/modules/openide/util/ServiceProviderProcessorTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2008 Sun Microsystems, Inc. - */ - -package org.netbeans.modules.openide.util; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import org.netbeans.junit.NbTestCase; -import org.openide.util.Lookup; -import org.openide.util.lookup.Lookups; -import org.openide.util.lookup.ServiceProvider; -import org.openide.util.lookup.ServiceProviders; -import org.openide.util.test.AnnotationProcessorTestUtils; - -public class ServiceProviderProcessorTest extends NbTestCase { - - public ServiceProviderProcessorTest(String n) { - super(n); - } - - private static List> classesOf(Iterable objects) { - List> cs = new ArrayList>(); - for (Object o : objects) { - cs.add(o.getClass()); - } - return cs; - } - - private static List> classesOfLookup(Class xface) { - return classesOf(Lookup.getDefault().lookupAll(xface)); - } - - private static List> sortClassList(List> classes) { - List> sorted = new ArrayList>(classes); - Collections.sort(sorted, new Comparator>() { - public int compare(Class c1, Class c2) { - return c1.getName().compareTo(c2.getName()); - } - }); - return sorted; - } - - public void testBasicUsage() throws Exception { - assertEquals(Collections.singletonList(Implementation.class), classesOfLookup(Interface.class)); - } - public interface Interface {} - @ServiceProvider(service=Interface.class) - public static class Implementation implements Interface {} - - public void testPosition() throws Exception { - assertEquals(Arrays.>asList(OrderedImpl3.class, OrderedImpl2.class, OrderedImpl1.class), classesOfLookup(OrderedInterface.class)); - } - public interface OrderedInterface {} - @ServiceProvider(service=OrderedInterface.class) - public static class OrderedImpl1 implements OrderedInterface {} - @ServiceProvider(service=OrderedInterface.class, position=200) - public static class OrderedImpl2 implements OrderedInterface {} - @ServiceProvider(service=OrderedInterface.class, position=100) - public static class OrderedImpl3 implements OrderedInterface {} - - public void testPath() throws Exception { - assertEquals(Collections.singletonList(PathImplementation.class), classesOf(Lookups.forPath("some/path").lookupAll(Interface.class))); - } - @ServiceProvider(service=Interface.class, path="some/path") - public static class PathImplementation implements Interface {} - - public void testSupersedes() throws Exception { - assertEquals(Arrays.>asList(Overrider.class, Unrelated.class), sortClassList(classesOfLookup(CancellableInterface.class))); - } - public interface CancellableInterface {} - @ServiceProvider(service=CancellableInterface.class) - public static class Overridden implements CancellableInterface {} - @ServiceProvider(service=CancellableInterface.class, supersedes="org.netbeans.modules.openide.util.ServiceProviderProcessorTest$Overridden") - public static class Overrider implements CancellableInterface {} - @ServiceProvider(service=CancellableInterface.class) - public static class Unrelated implements CancellableInterface {} - - public void testMultipleRegistrations() throws Exception { - assertEquals(Collections.singletonList(Multitasking.class), classesOfLookup(Interface1.class)); - assertEquals(Collections.singletonList(Multitasking.class), classesOfLookup(Interface2.class)); - } - public interface Interface1 {} - public interface Interface2 {} - @ServiceProviders({@ServiceProvider(service=Interface1.class), @ServiceProvider(service=Interface2.class)}) - public static class Multitasking implements Interface1, Interface2 {} - - public void testErrorReporting() throws Exception { - clearWorkDir(); - File src = new File(getWorkDir(), "src"); - File dest = new File(getWorkDir(), "classes"); - String xfaceName = Interface.class.getCanonicalName(); - - AnnotationProcessorTestUtils.makeSource(src, "p.C1", - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)", - "public class C1 implements " + xfaceName + " {}"); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - assertTrue(AnnotationProcessorTestUtils.runJavac(src, "C1", dest, null, baos)); - - AnnotationProcessorTestUtils.makeSource(src, "p.C2", - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)", - "class C2 implements " + xfaceName + " {}"); - baos = new ByteArrayOutputStream(); - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C2", dest, null, baos)); - assertTrue(baos.toString(), baos.toString().contains("public")); - - AnnotationProcessorTestUtils.makeSource(src, "p.C3", - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)", - "public class C3 implements " + xfaceName + " {", - "public C3(boolean x) {}", - "}"); - baos = new ByteArrayOutputStream(); - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C3", dest, null, baos)); - assertTrue(baos.toString(), baos.toString().contains("constructor")); - - AnnotationProcessorTestUtils.makeSource(src, "p.C4", - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)", - "public class C4 implements " + xfaceName + " {", - "C4() {}", - "}"); - baos = new ByteArrayOutputStream(); - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C4", dest, null, baos)); - assertTrue(baos.toString(), baos.toString().contains("constructor")); - - AnnotationProcessorTestUtils.makeSource(src, "p.C5", - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)", - "public abstract class C5 implements " + xfaceName + " {}"); - baos = new ByteArrayOutputStream(); - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C5", dest, null, baos)); - assertTrue(baos.toString(), baos.toString().contains("abstract")); - - AnnotationProcessorTestUtils.makeSource(src, "p.C6", - "@org.openide.util.lookup.ServiceProvider(service=" + xfaceName + ".class)", - "public class C6 {}"); - baos = new ByteArrayOutputStream(); - assertFalse(AnnotationProcessorTestUtils.runJavac(src, "C6", dest, null, baos)); - assertTrue(baos.toString(), baos.toString().contains("assignable")); - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/AbstractLookupArrayStorageTest.java --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupArrayStorageTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import junit.framework.*; -import org.netbeans.junit.*; -import org.openide.util.Lookup; - -public class AbstractLookupArrayStorageTest extends AbstractLookupBaseHid { - public AbstractLookupArrayStorageTest(java.lang.String testName) { - super(testName, null); - } - - public static TestSuite suite () { - NbTestSuite suite = new NbTestSuite (); - suite.addTest (new PL (2)); - suite.addTest (new AL (1)); - suite.addTest (new AL (-1)); - suite.addTest (new PL (-1)); - suite.addTest (new AL (5)); - suite.addTest (new PL (3)); - suite.addTest (new AL (2000)); - suite.addTest (new PL (2000)); - return suite; - } - - static final class AL extends ArrayTestSuite { - public AL (int trash) { - super (trash); - } - - public Lookup createLookup (Lookup lookup) { - return lookup; - } - - public void clearCaches () { - } - - } - - static final class PL extends ArrayTestSuite { - public PL (int trash) { - super (trash); - } - - public Lookup createLookup (Lookup lookup) { - return new ProxyLookup (new Lookup[] { lookup }); - } - - public void clearCaches () { - } - - } - - private static abstract class ArrayTestSuite extends NbTestSuite - implements AbstractLookupBaseHid.Impl { - private int trash; - - public ArrayTestSuite (int trash) { - super (AbstractLookupArrayStorageTest.class); - this.trash = trash; - - int cnt = this.countTestCases(); - for (int i = 0; i < cnt; i++) { - Object o = this.testAt (i); - AbstractLookupBaseHid t = (AbstractLookupBaseHid)o; - t.impl = this; - } - } - - public Lookup createInstancesLookup (InstanceContent ic) { - if (trash == -1) { - return new AbstractLookup (ic, new ArrayStorage ()); - } else { - return new AbstractLookup (ic, new ArrayStorage (new Integer (trash))); - } - } - - - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/AbstractLookupAsynchExecutorTest.java --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupAsynchExecutorTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executor; -import org.netbeans.junit.NbTestCase; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; - -public class AbstractLookupAsynchExecutorTest extends NbTestCase implements Executor { - private List toRun = new ArrayList(); - - - public AbstractLookupAsynchExecutorTest(java.lang.String testName) { - super(testName); - } - - public void testCanProxyLookupHaveWrongResults() { - final InstanceContent ic = new InstanceContent(this); - final AbstractLookup lookup = new AbstractLookup(ic); - - class L implements LookupListener { - ProxyLookup pl; - Lookup.Result original; - Lookup.Result wrapped; - boolean ok; - - public void test() { - pl = new ProxyLookup(lookup); - original = lookup.lookupResult(String.class); - - original.addLookupListener(this); - - wrapped = pl.lookupResult(String.class); - - assertEquals("Original empty", 0, original.allInstances().size()); - assertEquals("Wrapped empty", 0, wrapped.allInstances().size()); - - ic.add("Hello!"); - } - - public void resultChanged(LookupEvent ev) { - ok = true; - assertContainsHello(); - } - - public void assertContainsHello() { - assertEquals("Original has hello", 1, original.allInstances().size()); - assertEquals("Wrapped has hello", 1, wrapped.allInstances().size()); - } - - } - L listener = new L(); - listener.test(); - listener.assertContainsHello(); - for (Runnable r : toRun) { - r.run(); - } - assertTrue("Listener called", listener.ok); - } - - public void execute(Runnable command) { - toRun.add(command); - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/AbstractLookupBaseHid.java --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupBaseHid.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2088 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.lang.ref.WeakReference; -import java.lang.ref.Reference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import javax.swing.ActionMap; -import javax.swing.InputMap; -import org.netbeans.junit.NbTestCase; -import org.openide.util.Lookup; -import org.openide.util.Lookup.Template; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; - -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them -public class AbstractLookupBaseHid extends NbTestCase { - private static AbstractLookupBaseHid running; - - /** instance content to work with */ - InstanceContent ic; - /** the lookup to work on */ - protected Lookup instanceLookup; - /** the lookup created to work with */ - private Lookup lookup; - /** implementation of methods that can influence the behaviour */ - Impl impl; - - protected AbstractLookupBaseHid(String testName, Impl impl) { - super(testName); - if (impl == null && (this instanceof Impl)) { - impl = (Impl)this; - } - this.impl = impl; - } - - protected @Override void setUp() { - this.ic = new InstanceContent (); - - beforeActualTest(getName()); - - this.instanceLookup = createInstancesLookup (ic); - this.lookup = createLookup (instanceLookup); - running = this; - } - - protected @Override void tearDown() { - running = null; - } - - /** The methods to influence test behaviour */ - public static interface Impl { - /** Creates the initial abstract lookup. - */ - public Lookup createInstancesLookup (InstanceContent ic); - /** Creates an lookup for given lookup. This class just returns - * the object passed in, but subclasses can be different. - * @param lookup in lookup - * @return a lookup to use - */ - public Lookup createLookup (Lookup lookup); - - /** If the impl has any caches that would prevent the system - * to not garbage collect correctly, then clear them now. - */ - public void clearCaches (); - } - - private Lookup createInstancesLookup (InstanceContent ic) { - return impl.createInstancesLookup (ic); - } - - private Lookup createLookup (Lookup lookup) { - return impl.createLookup (lookup); - } - - /** instances that we register */ - private static Object[] INSTANCES = new Object[] { - new Integer (10), - new Object () - }; - - /** Test if first is really first. - */ - public void testFirst () { - Integer i1 = 1; - Integer i2 = 2; - - ic.add (i1); - ic.add (i2); - - Integer found = lookup.lookup(Integer.class); - if (found != i1) { - fail ("First object is not first: " + found + " != " + i1); - } - - List list = new ArrayList(); - list.add (i2); - list.add (i1); - ic.set (list, null); - - found = lookup.lookup (Integer.class); - if (found != i2) { - fail ("Second object is not first after reorder: " + found + " != " + i2); - } - - } - - public void testToString() { - String txt = lookup.toString(); - assertNotNull("Something is there", txt); - assertTrue("Something2: " + txt, txt.length() > 0); - } - - - /** Tests ordering of items in the lookup. - */ - public void testOrder () { - addInstances (INSTANCES); - - if (INSTANCES[0] != lookup.lookup (INSTANCES[0].getClass ())) { - fail ("First object in intances not found"); - } - - Iterator all = lookup.lookupAll(Object.class).iterator(); - checkIterator ("Difference between instances added and found", all, Arrays.asList (INSTANCES)); - } - - /** Checks the reorder of items in lookup reflects the result. - * Testing both classes and interfaces, because they are often treated - * especially. - */ - public void testReorder () { - String s1 = "s2"; - String s2 = "s1"; - Runnable r1 = new Runnable () { - public void run () {} - }; - Runnable r2 = new Runnable () { - public void run () {} - }; - List l = new ArrayList(); - - l.add (s1); - l.add (s2); - l.add (r1); - l.add (r2); - ic.set (l, null); - - assertEquals ("s1 is found", s1, lookup.lookup (String.class)); - assertEquals ("r1 is found", r1, lookup.lookup (Runnable.class)); - - Collections.reverse (l); - - ic.set (l, null); - - assertEquals ("s2 is found", s2, lookup.lookup (String.class)); - assertEquals ("r2 is found", r2, lookup.lookup (Runnable.class)); - } - - /** Tries to set empty collection to the lookup. - */ - public void testSetEmpty () { - ic.add ("A serializable string"); - lookup.lookup (Serializable.class); - - ic.set (Collections.emptyList(), null); - } - - /** Tests a more complex reorder on nodes. - */ - public void testComplexReorder () { - Integer i1 = 1; - Long i2 = 2L; - - List l = new ArrayList(); - l.add (i1); - l.add (i2); - ic.set (l, null); - - assertEquals ("Find integer", i1, lookup.lookup (Integer.class)); - assertEquals ("Find long", i2, lookup.lookup (Long.class)); - assertEquals ("Find number", i1, lookup.lookup (Number.class)); - - Collections.reverse (l); - - ic.set (l, null); - - assertEquals ("Find integer", i1, lookup.lookup (Integer.class)); - assertEquals ("Find long", i2, lookup.lookup (Long.class)); - assertEquals ("Find number", i2, lookup.lookup (Number.class)); - } - - /** Checks whether setPairs keeps the order. - */ - public void testSetPairs () { - // test setPairs method - List li = new ArrayList(); - li.addAll (Arrays.asList (INSTANCES)); - ic.set (li, null); - - Lookup.Result res = lookup.lookupResult(Object.class); - Iterator all = res.allInstances().iterator(); - checkIterator ("Original order not kept", all, li); - - // reverse the order - Collections.reverse (li); - - // change the pairs - LL listener = new LL (res); - res.addLookupListener (listener); - ic.set (li, null); - if (listener.getCount () != 1) { - fail ("Result has not changed even we set reversed order"); - } - - all = res.allInstances ().iterator (); - checkIterator ("Reversed order not kept", all, li); - } - - /** Checks whether setPairs fires correct events. - */ - public void testSetPairsFire () { - // test setPairs method - List li = new ArrayList(); - li.addAll (Arrays.asList (INSTANCES)); - ic.set (li, null); - - Lookup.Result res = lookup.lookupResult(Integer.class); - Iterator all = res.allInstances().iterator(); - checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0])); - - // change the pairs - LL listener = new LL (res); - res.addLookupListener (listener); - - List l2 = new ArrayList(li); - l2.remove (INSTANCES[0]); - ic.set (l2, null); - - all = lookup.lookupAll(Object.class).iterator(); - checkIterator ("The removed integer is not noticed", all, l2); - - if (listener.getCount () != 1) { - fail ("Nothing has not been fired"); - } - } - - /** Checks whether set pairs does not fire when they should not. - */ - public void testSetPairsDoesNotFire () { - Object tmp = new Object (); - - List li = new ArrayList(); - li.add (tmp); - li.addAll (Arrays.asList (INSTANCES)); - ic.set (li, null); - - Lookup.Result res = lookup.lookupResult(Integer.class); - Iterator all = res.allInstances ().iterator (); - checkIterator ("Integer is not there", all, Collections.nCopies (1, INSTANCES[0])); - - // change the pairs - LL listener = new LL (res); - res.addLookupListener (listener); - - List l2 = new ArrayList(li); - l2.remove (tmp); - ic.set (l2, null); - - all = lookup.lookupAll(Object.class).iterator(); - checkIterator ("The removed integer is not noticed", all, l2); - - if (listener.getCount () != 0) { - fail ("Something has been fired"); - } - } - - /** Test whether after registration it is possible to find registered objects - * - */ - public void testLookupAndAdd () throws Exception { - addInstances (INSTANCES); - - for (int i = 0; i < INSTANCES.length; i++) { - Object obj = INSTANCES[i]; - findAll (lookup, obj.getClass (), true); - } - } - - /** Tries to find all classes and superclasses in the lookup. - */ - private void findAll(Lookup lookup, Class clazz, boolean shouldBeThere) { - if (clazz == null) return; - - Object found = lookup.lookup (clazz); - if (found == null) { - if (shouldBeThere) { - // should find at either instance or something else, but must - // find at least something - fail ("Lookup (" + clazz.getName () + ") found nothing"); - } - } else { - if (!shouldBeThere) { - // should find at either instance or something else, but must - // find at least something - fail ("Lookup (" + clazz.getName () + ") found " + found); - } - } - - Lookup.Result res = lookup.lookupResult(clazz); - Collection collection = res.allInstances(); - - for (int i = 0; i < INSTANCES.length; i++) { - boolean isSubclass = clazz.isInstance (INSTANCES[i]); - boolean isThere = collection.contains (INSTANCES[i]); - - if (isSubclass != isThere) { - // a problem found - // should find at either instance or something else, but must - // find at least something - fail ("Lookup.Result (" + clazz.getName () + ") for " + INSTANCES[i] + " is subclass: " + isSubclass + " isThere: " + isThere); - } - } - - // go on for superclasses - - findAll (lookup, clazz.getSuperclass (), shouldBeThere); - - Class[] ies = clazz.getInterfaces (); - for (int i = 0; i < ies.length; i++) { - findAll (lookup, ies[i], shouldBeThere); - } - } - - /** Test if it is possible to remove a registered object. */ - public void testRemoveRegisteredObject() { - Integer inst = new Integer(10); - - ic.add(inst); - if (lookup.lookup(inst.getClass()) == null) { - // should find an instance - fail("Lookup (" + inst.getClass().getName () + ") found nothing"); - } - - ic.remove(inst); - if (lookup.lookup(inst.getClass()) != null) { - // should NOT find an instance - fail("Lookup (" + inst.getClass().getName () + - ") found an instance after remove operation"); - } - } - - public void testCanReturnReallyStrangeResults () throws Exception { - class QueryingPair extends AbstractLookup.Pair { - private Integer i = 434; - - // - // do the test - // - - public void doTest () throws Exception { - ic.add (i); - ic.addPair (this); - - Object found = lookup.lookup (QueryingPair.class); - assertEquals ("This object is found", this, found); - } - - - // - // Implementation of pair - // - - public String getId() { - return getType ().toString(); - } - - public String getDisplayName() { - return getId (); - } - - public Class getType() { - return getClass (); - } - - protected boolean creatorOf(Object obj) { - return obj == this; - } - - protected boolean instanceOf(Class c) { - assertEquals ("Integer found or exception is thrown", i, lookup.lookup (Integer.class)); - return c.isAssignableFrom(getType ()); - } - - public Object getInstance() { - return this; - } - - - } - - - QueryingPair qp = new QueryingPair (); - qp.doTest (); - } - - /** Test of firing events. */ - public void testLookupListener() { - Object inst = 10; - Lookup.Result res = lookup.lookupResult(inst.getClass()); - res.allInstances (); - - LL listener = new LL(res); - res.addLookupListener(listener); - - ic.add(inst); - if (listener.getCount() == 0) { - fail("None event fired during NbLookup.addPair()"); - } - - ic.remove(inst); - if (listener.getCount() == 0) { - fail("None event fired during NbLookup.removePair()"); - } - - ic.add(inst); - if (listener.getCount() == 0) { - fail("None event fired during second NbLookup.addPair()"); - } - - ic.remove(inst); - if (listener.getCount() == 0) { - fail("None event fired during second NbLookup.removePair()"); - } - } - - /** Testing identity of the lookup. - */ - public void testId () { - Lookup.Template templ; - int cnt; - - addInstances (INSTANCES); - - Lookup.Result res = lookup.lookupResult(Object.class); - for (AbstractLookup.Item item : res.allItems()) { - - templ = new Lookup.Template(null, item.getId(), null); - cnt = lookup.lookup (templ).allInstances ().size (); - if (cnt != 1) { - fail ("Identity lookup failed. Instances = " + cnt); - } - - templ = makeTemplate(item.getType(), item.getId()); - cnt = lookup.lookup (templ).allInstances ().size (); - if (cnt != 1) { - fail ("Identity lookup with type failed. Instances = " + cnt); - } - - templ = makeTemplate(this.getClass(), item.getId()); - cnt = lookup.lookup (templ).allInstances ().size (); - if (cnt != 0) { - fail ("Identity lookup with wrong type failed. Instances = " + cnt); - } - - templ = new Lookup.Template(null, null, item.getInstance()); - cnt = lookup.lookup (templ).allInstances ().size (); - if (cnt != 1) { - fail ("Instance lookup failed. Instances = " + cnt); - } - - templ = new Lookup.Template(null, item.getId(), item.getInstance()); - cnt = lookup.lookup (templ).allInstances ().size (); - if (cnt != 1) { - fail ("Instance & identity lookup failed. Instances = " + cnt); - } - - } - } - private static Lookup.Template makeTemplate(Class clazz, String id) { // captures type parameter - return new Lookup.Template(clazz, id, null); - } - - /** Tests adding and removing. - */ - public void testAddAndRemove () throws Exception { - Object map = new javax.swing.ActionMap (); - LL ll = new LL (); - - Lookup.Result res = lookup.lookupResult(map.getClass()); - res.allItems(); - res.addLookupListener (ll); - ll.source = res; - - ic.add (map); - - assertEquals ("First change when adding", ll.getCount (), 1); - - ic.remove (map); - - assertEquals ("Second when removing", ll.getCount (), 1); - - ic.add (map); - - assertEquals ("Third when readding", ll.getCount (), 1); - - ic.remove (map); - - assertEquals ("Forth when reremoving", ll.getCount (), 1); - - } - - /** Will a class garbage collect even it is registered in lookup. - */ - public void testGarbageCollect () throws Exception { - ClassLoader l = new CL (); - Class c = l.loadClass(Garbage.class.getName()); - Reference ref = new WeakReference(c); - - lookup.lookup (c); - - // now test garbage collection - c = null; - l = null; - impl.clearCaches (); - assertGC ("The classloader has not been garbage collected!", ref); - } - - /** Items are the same as results. - */ - public void testItemsAndIntances () { - addInstances (INSTANCES); - - Lookup.Result r = lookup.lookupResult(Object.class); - Collection> items = r.allItems(); - Collection insts = r.allInstances(); - - if (items.size () != insts.size ()) { - fail ("Different size of sets"); - } - - for (Lookup.Item item : items) { - if (!insts.contains (item.getInstance ())) { - fail ("Intance " + item.getInstance () + " is missing in " + insts); - } - } - } - - /** Checks search for interface. - */ - public void testSearchForInterface () { - Lookup.Template t = new Lookup.Template(Serializable.class, null, null); - - assertNull("Nothing to find", lookup.lookupItem (t)); - - Serializable s = new Serializable () {}; - ic.add (s); - - Lookup.Item item = lookup.lookupItem (t); - assertNotNull ("Something found", item); - } - - /** Test to add broken item if it incorrectly answers instanceOf questions. - */ - public void testIncorectInstanceOf40364 () { - final Long sharedLong = new Long (0); - - class P extends AbstractLookup.Pair { - public boolean isLong; - - P (boolean b) { - isLong = b; - } - - protected boolean creatorOf (Object obj) { - return obj == sharedLong; - } - - public String getDisplayName () { - return ""; - } - - public String getId () { - return ""; - } - - public Object getInstance () { - return sharedLong; - } - - public Class getType() { - return isLong ? Long.class : Number.class; - } - - protected boolean instanceOf(Class c) { - return c.isAssignableFrom (getType ()); - } - - public @Override int hashCode() { - return getClass ().hashCode (); - } - - public @Override boolean equals(Object obj) { - return obj != null && getClass ().equals (obj.getClass ()); - } - } - - // to create the right structure in the lookup - lookup.lookup (Object.class); - lookup.lookup (Long.class); - lookup.lookup (Number.class); - - P lng1 = new P (true); - ic.addPair (lng1); - - P lng2 = new P (false); - ic.setPairs (Collections.singleton (lng2)); - - Collection> res = lookup.lookupResult(Object.class).allItems(); - assertEquals ("Just one pair", 1, res.size ()); - } - - public void testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly () throws Exception { - class X implements TestInterfaceInheritanceA, TestInterfaceInheritanceB { - } - final X shared = new X (); - - class P extends AbstractLookup.Pair { - public int howLong; - - P (int b) { - howLong = b; - } - - protected boolean creatorOf (Object obj) { - return obj == shared; - } - - public String getDisplayName () { - return ""; - } - - public String getId () { - return ""; - } - - public Object getInstance () { - return shared; - } - - public Class getType() { - return howLong == 0 ? TestInterfaceInheritanceB.class : TestInterfaceInheritanceA.class; - } - - protected boolean instanceOf(Class c) { - return c.isAssignableFrom (getType ()); - } - - public @Override int hashCode() { - return getClass ().hashCode (); - } - - public @Override boolean equals(Object obj) { - if (obj instanceof P) { - P p = (P)obj; - if (this.howLong > 0) { - this.howLong--; - return false; - } - if (p.howLong > 0) { - p.howLong--; - return false; - } - return getClass ().equals (p.getClass ()); - } - return false; - } - } - - // to create the right structure in the lookup - Lookup.Result a = lookup.lookupResult(TestInterfaceInheritanceA.class); - Lookup.Result b = lookup.lookupResult(TestInterfaceInheritanceB.class); - - P lng1 = new P (0); - ic.addPair (lng1); - - assertEquals ("One in a", 1, a.allItems ().size ()); - assertEquals ("One in b", 1, b.allItems ().size ()); - - P lng2 = new P (1); - - - /* Following call used to generate this exception: - 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 - at org.openide.util.lookup.ALPairComparator.compare(ALPairComparator.java:52) - at java.util.Arrays.mergeSort(Arrays.java:1284) - at java.util.Arrays.sort(Arrays.java:1223) - at java.util.Collections.sort(Collections.java:159) - at org.openide.util.lookup.InheritanceTree.retainAllInterface(InheritanceTree.java:753) - at org.openide.util.lookup.InheritanceTree.retainAll(InheritanceTree.java:183) - at org.openide.util.lookup.DelegatingStorage.retainAll(DelegatingStorage.java:83) - at org.openide.util.lookup.AbstractLookup.setPairsAndCollectListeners(AbstractLookup.java:238) - at org.openide.util.lookup.AbstractLookup.setPairs(AbstractLookup.java:203) - at org.openide.util.lookup.AbstractLookup$Content.setPairs(AbstractLookup.java:885) - at org.openide.util.lookup.AbstractLookupBaseHid.testAbsolutelyCrazyWayToSimulateIssue48590ByChangingTheBehaviourOfEqualOnTheFly(AbstractLookupBaseHid.java:696) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) - at org.netbeans.junit.NbTestCase.run(NbTestCase.java:119) - */ - ic.setPairs (Collections.singleton (lng2)); - - - } - - public void testInstancesArePreservedFoundWhenFixing48590 () throws Exception { - class X implements Runnable, Serializable { - public void run () { - - } - - public void assertOnlyMe (String msg, Lookup.Result res) { - Collection col = res.allInstances(); - assertEquals (msg + " just one", 1, col.size ()); - assertSame (msg + " and it is me", this, col.iterator ().next ()); - } - } - - Lookup.Result runnable = lookup.lookupResult(Runnable.class); - Lookup.Result serial = lookup.lookupResult(Serializable.class); - - - X x = new X (); - ic.add (x); - - - x.assertOnlyMe ("x implements it (1)", runnable); - x.assertOnlyMe ("x implements it (2)", serial); - - ic.set (Collections.singleton (x), null); - - x.assertOnlyMe ("x implements it (3)", runnable); - x.assertOnlyMe ("x implements it (4)", serial); - } - - /** Testing lookup of inherited classes. */ - public void testInheritance() { - class A {} - class B extends A implements java.rmi.Remote {} - class BB extends B {} - class C extends A implements java.rmi.Remote {} - class D extends A {} - - A[] types = {new B(), new BB(), new C(), new D()}; - - for (int i = 0; i < types.length; i++) { - ic.add(types[i]); - if (lookup.lookup(types[i].getClass()) == null) { - // should find an instance - fail("Lookup (" + types[i].getClass().getName () + ") found nothing"); - } - } - - int size1, size2; - - //interface query - size1 = lookup.lookupAll(java.rmi.Remote.class).size(); - size2 = countInstances(types, java.rmi.Remote.class); - - if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2); - - // superclass query - size1 = lookup.lookupAll(A.class).size(); - size2 = countInstances(types, A.class); - - if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2); - } - - /** Test interface inheritance. - */ - public void testInterfaceInheritance() { - TestInterfaceInheritanceA[] types = { - new TestInterfaceInheritanceB() {}, - new TestInterfaceInheritanceBB() {}, - new TestInterfaceInheritanceC() {}, - new TestInterfaceInheritanceD() {} - }; - - for (int i = 0; i < types.length; i++) { - ic.add(types[i]); - if (lookup.lookup(types[i].getClass()) == null) { - // should find an instance - fail("Lookup (" + types[i].getClass().getName () + ") found nothing"); - } - } - - int size1, size2; - - //interface query - LL l = new LL (); - Lookup.Result res = lookup.lookupResult(java.rmi.Remote.class); - l.source = res; - size1 = res.allInstances().size(); - size2 = countInstances(types, java.rmi.Remote.class); - - if (size1 != size2) fail("Lookup with interface failed: " + size1 + " != " + size2); - - // superclass query - size1 = lookup.lookupAll(TestInterfaceInheritanceA.class).size(); - size2 = countInstances(types, TestInterfaceInheritanceA.class); - - if (size1 != size2) fail("Lookup with superclass failed: " + size1 + " != " + size2); - - res.addLookupListener (l); - ic.remove (types[0]); - - if (l.getCount () != 1) { - fail ("No notification that a Remote is removed"); - } - } - - /** Checks whether the AbstractLookup is guarded against modifications - * while doing some kind of modification. - */ - public void testModificationArePreventedWhenDoingModifications () throws Exception { - BrokenPair broken = new BrokenPair (true, false); - ic.addPair (broken); - - Lookup.Template templ = new Lookup.Template(BrokenPair.class); - Lookup.Item item = lookup.lookupItem (templ); - assertEquals ("Broken is found", broken, item); - } - - public void testModificationArePreventedWhenDoingModificationsResult () throws Exception { - BrokenPair broken = new BrokenPair (false, true); - ic.addPair (broken); - - Lookup.Template templ = new Lookup.Template(BrokenPair.class); - - Collection c = lookup.lookup (templ).allInstances(); - assertEquals ("One item", 1, c.size ()); - assertEquals ("Broken is found again", broken, c.iterator().next ()); - } - - public void testModificationArePreventedWhenDoingModificationsItemAndResult () throws Exception { - BrokenPair broken = new BrokenPair (false, true); - ic.addPair (broken); - - Lookup.Template templ = new Lookup.Template(BrokenPair.class); - Lookup.Item item = lookup.lookupItem (templ); - assertEquals ("Broken is found", broken, item); - - Collection c = lookup.lookup(templ).allInstances(); - assertEquals ("One item", 1, c.size ()); - assertEquals ("Broken is found again", broken, c.iterator().next ()); - } - - public void testModificationArePreventedWhenDoingModificationsResultAndItem () throws Exception { - BrokenPair broken = new BrokenPair (false, true); - ic.addPair (broken); - - Lookup.Template templ = new Lookup.Template(BrokenPair.class); - Collection c = lookup.lookup(templ).allInstances(); - assertEquals ("One item", 1, c.size ()); - assertEquals ("Broken is found again", broken, c.iterator().next ()); - - Object item = lookup.lookupItem (templ); - assertEquals ("Broken is found", broken, item); - } - - public void testAddALotOfPairsIntoTheLookupOneByOne () throws Exception { - Lookup.Result res = lookup.lookupResult(Integer.class); - for (int i = 0; i < 1000; i++) { - ic.add(i); - } - assertEquals ( - "there is the right count", - 1000, - res.allItems().size () - ); - } - - public void testAddALotOfPairsIntoTheLookup () throws Exception { - List arr = new ArrayList(); - for (int i = 0; i < 1000; i++) { - arr.add(i); - } - ic.set (arr, null); - - assertEquals ( - "there is the right count", - 1000, - lookup.lookupResult(Integer.class).allItems().size() - ); - } - - - public void testDoubleAddIssue35274 () throws Exception { - class P extends AbstractLookup.Pair { - protected boolean creatorOf(Object obj) { return false; } - public String getDisplayName() { return ""; } - public String getId() { return ""; } - public Object getInstance() { return null; } - public Class getType() { return Object.class; } - protected boolean instanceOf(Class c) { return c.isAssignableFrom(getType ()); } - public @Override int hashCode() {return getClass().hashCode();} - public @Override boolean equals(Object obj) {return getClass() == obj.getClass();} - } - - P p = new P (); - - ic.addPair (p); - ic.addPair (p); - - Lookup.Result result = lookup.lookupResult(Object.class); - Collection res = result.allItems (); - assertEquals ("One item there", 1, res.size ()); - assertTrue ("It is the p", p == res.iterator ().next ()); - - P p2 = new P (); - ic.addPair (p2); - - Reference ref = new WeakReference(result); - result = null; - assertGC ("The result can disappear", ref); - - impl.clearCaches (); - - result = lookup.lookupResult(Object.class); - res = result.allItems (); - assertEquals ("One item is still there", 1, res.size ()); - assertTrue ("But the p2 replaced p", p2 == res.iterator ().next ()); - - } - - /** Test for proper serialization. - */ - public void testSerializationSupport () throws Exception { - doSerializationSupport (1); - } - public void testDoubleSerializationSupport () throws Exception { - doSerializationSupport (2); - } - - private void doSerializationSupport (int count) throws Exception { - if (lookup instanceof Serializable) { - ic.addPair (new SerialPair ("1")); - ic.addPair (new SerialPair ("2")); - ic.addPair (new SerialPair ("3")); - - Lookup l = (Lookup)reserialize(lookup); - - assertEquals ("Able to answer simple query", "1", l.lookup (String.class)); - - assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ()); - - while (count-- > 0) { - l = (Lookup)reserialize(l); - } - - assertEquals ("Able to answer simple query", "1", l.lookup (String.class)); - - assertEquals ("Three objects there", 3, l.lookup (new Lookup.Template (String.class)).allInstances().size ()); - } - } - - /** When a lookup with two different versions of the same class - * get's serialized, the results may be very bad. - */ - public void testSerializationOfTwoClassesWithTheSameName () throws Exception { - if (lookup instanceof Serializable) { - doTwoSerializedClasses (false, false); - } - } - public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSave () throws Exception { - if (lookup instanceof Serializable) { - doTwoSerializedClasses (true, false); - } - } - public void testSerializationOfTwoClassesWithTheSameNameWithBroken () throws Exception { - if (lookup instanceof Serializable) { - doTwoSerializedClasses (false, true); - } - } - public void testSerializationOfTwoClassesWithTheSameNameButQueryBeforeSaveWithBroken () throws Exception { - if (lookup instanceof Serializable) { - doTwoSerializedClasses (true, true); - } - } - - private void doTwoSerializedClasses (boolean queryBeforeSerialization, boolean useBroken) throws Exception { - ClassLoader loader = new CL (); - Class c = loader.loadClass (Garbage.class.getName ()); - - // in case of InheritanceTree it creates a slot for class Garbage - lookup.lookup(c); - - // but creates new instance and adds it into the lookup - // without querying for it - loader = new CL (); - c = loader.loadClass (Garbage.class.getName ()); - - Object theInstance = c.newInstance (); - - ic.addPair (new SerialPair (theInstance)); - - Broken2Pair broken = null; - if (useBroken) { - broken = new Broken2Pair (); - ic.addPair (broken); - - assertNull ( - "We need to create the slot for the List as " + - "the Broken2Pair will ask for it after deserialization", - lookup.lookup (java.awt.List.class) - ); - } - - if (queryBeforeSerialization) { - assertEquals ("Instance is found", theInstance, lookup.lookup (c)); - } - - // replace the old lookup with new one - lookup = (Lookup)reserialize(lookup); - - Lookup.Result result = lookup.lookup (new Lookup.Template (Garbage.class)); - assertEquals ("One item is the result", 1, result.allInstances ().size ()); - Object r = result.allInstances ().iterator ().next (); - assertNotNull("A value is found", r); - assertEquals ("It is of the right class", Garbage.class, r.getClass()); - } - - /** Test of reorder and item change which used to fail on interfaces. - */ - public void testReoderingIssue13779 () throws Exception { - LinkedList arr = new LinkedList (); - - class R extends Exception implements Cloneable { - } - Object o1 = new R (); - Object o2 = new R (); - Object o3 = new R (); - - arr.add (o1); - arr.add (o2); - - ic.set (arr, null); - - Lookup.Result objectResult = lookup.lookup (new Lookup.Template (Exception.class)); - Lookup.Result interfaceResult = lookup.lookup (new Lookup.Template (Cloneable.class)); - objectResult.allItems (); - interfaceResult.allItems (); - - LL l1 = new LL (objectResult); - LL l2 = new LL (interfaceResult); - - objectResult.addLookupListener(l1); - interfaceResult.addLookupListener(l2); - - arr.addFirst (o3); - - ic.set (arr, null); - - assertEquals ("One change on objects", 1, l1.getCount ()); - assertEquals ("One change on interfaces", 1, l2.getCount ()); - - arr.addFirst (new Cloneable () { }); - ic.set (arr, null); - - assertEquals ("No change on objects", 0, l1.getCount ()); - assertEquals ("But one change on interfaces", 1, l2.getCount ()); - - } - - public void testDeadlockBetweenProxyResultAndLookupIssue47772 () throws Exception { - final String myModule = "My Module"; - ic.add (myModule); - - class MyProxy extends ProxyLookup { - public MyProxy () { - super (new Lookup[] { lookup }); - } - } - final MyProxy my = new MyProxy (); - - final Lookup.Result allModules = my.lookup (new Lookup.Template (String.class)); - - class PairThatNeedsInfoAboutModules extends AbstractLookup.Pair { - public String getDisplayName () { - return "Need a module"; - } - public String getId () { - return getDisplayName (); - } - public Class getType () { - return Integer.class; - } - protected boolean instanceOf (Class c) { - if (c == Integer.class) { - synchronized (this) { - notifyAll (); - try { - wait (1000); - } catch (InterruptedException ex) { - fail (ex.getMessage ()); - } - } - java.util.Collection coll = allModules.allInstances (); - assertEquals ("Size is 1", 1, coll.size ()); - assertEquals ("My module is there", myModule, coll.iterator ().next ()); - } - return c.isAssignableFrom (Integer.class); - } - - public Object getInstance () { - return new Integer (10); - } - - protected boolean creatorOf (Object obj) { - return new Integer (10).equals (obj); - } - } - - PairThatNeedsInfoAboutModules pair = new PairThatNeedsInfoAboutModules (); - ic.addPair (pair); - - synchronized (pair) { - class BlockInInstanceOf implements Runnable { - public void run () { - Integer i = my.lookup(Integer.class); - assertEquals (new Integer (10), i); - } - } - BlockInInstanceOf blk = new BlockInInstanceOf (); - Executors.newSingleThreadScheduledExecutor().schedule(blk, 0, TimeUnit.MICROSECONDS); - pair.wait (); - } - - java.util.Collection coll = allModules.allInstances (); - assertEquals ("Size is 1", 1, coll.size ()); - assertEquals ("My module is there", myModule, coll.iterator ().next ()); - } - - public void testAWayToGenerateProblem13779 () { - ic.add (new Integer (1)); - ic.add (new Integer (2)); - ic.add (new Integer (1)); - ic.add (new Integer (2)); - - Collection c = lookup.lookup (new Lookup.Template (Integer.class)).allInstances (); - assertEquals ("There are two objects", 2, c.size ()); - - } - - /** Replacing items with different objects. - */ - public void testReplacingObjectsDoesNotGenerateException () throws Exception { - LinkedList arr = new LinkedList (); - - class R extends Exception implements Cloneable { - } - arr.add (new R ()); - arr.add (new R ()); - - ic.set (arr, null); - - arr.clear(); - - arr.add (new R ()); - arr.add (new R ()); - - ic.set (arr, null); - } - - public void testAfterDeserializationNoQueryIsPeformedOnAlreadyQueriedObjects() throws Exception { - if (! (lookup instanceof Serializable)) { - // well this test works only for serializable lookups - return; - } - - SerialPair my = new SerialPair ("no"); - ic.addPair (my); - - Lookup.Result res = lookup.lookup (new Lookup.Template (String.class)); - assertEquals ("One instance", 1, res.allInstances().size ()); - assertEquals ("my.instanceOf called once", 1, my.countInstanceOf); - - Lookup serial = (Lookup)reserialize(lookup); - - Lookup.Result r2 = serial.lookup(new Lookup.Template(String.class)); - - assertEquals ("One item", 1, r2.allItems ().size ()); - Object one = r2.allItems().iterator().next (); - assertEquals ("The right class", SerialPair.class, one.getClass()); - SerialPair p = (SerialPair)one; - - assertEquals ("p.instanceOf has not been queried", 0, p.countInstanceOf); - } - - /** Checks the iterator */ - private void checkIterator(String msg, Iterator it1, List list) { - int cnt = 0; - Iterator it2 = list.iterator(); - while (it1.hasNext () && it2.hasNext ()) { - T n1 = it1.next(); - T n2 = it2.next(); - - if (n1 != n2) { - fail (msg + " iterator[" + cnt + "] = " + n1 + " but list[" + cnt + "] = " + n2); - } - - cnt++; - } - - if (it1.hasNext ()) { - fail ("Iterator has more elements than list"); - } - - if (it2.hasNext ()) { - fail ("List has more elements than iterator"); - } - } - - - public void testResultsAreUnmodifyableOrAtLeastTheyDoNotPropagateToCache() throws Exception { - String s = "Ahoj"; - - ic.add(s); - - Lookup.Result res = lookup.lookup(new Template(String.class)); - - for (int i = 1; i < 5; i++) { - Collection c1 = res.allInstances(); - Collection c2 = res.allClasses(); - Collection c3 = res.allItems(); - - assertTrue(i + ": c1 has it", c1.contains(s)); - assertTrue(i + ": c2 has it", c2.contains(s.getClass())); - assertEquals(i + ": c3 has one", 1, c3.size()); - Lookup.Item item = (Lookup.Item) c3.iterator().next(); - assertEquals(i + ": c3 has it", s, item.getInstance()); - - try { - c1.remove(s); - assertEquals("No elements now", 0, c1.size()); - } catch (UnsupportedOperationException ex) { - // ok, this need not be supported - } - try { - c2.remove(s.getClass()); - assertEquals("No elements now", 0, c2.size()); - } catch (UnsupportedOperationException ex) { - // ok, this need not be supported - } - try { - c3.remove(item); - assertEquals("No elements now", 0, c3.size()); - } catch (UnsupportedOperationException ex) { - // ok, this need not be supported - } - } - } - - public void testSomeProblemWithDVBFrameworkSeemsToBeInLookup() { - for (int i = 0; i < 5; i++) { - ic.add(lookup); - assertEquals("Can be found", lookup, lookup.lookup(lookup.getClass())); - ic.set(Collections.EMPTY_LIST, null); - } - } - - public void testListeningAndQueryingByTwoListenersInstances() { - doListeningAndQueryingByTwoListeners(0); - } - public void testListeningAndQueryingByTwoListenersClasses() { - doListeningAndQueryingByTwoListeners(1); - } - public void testListeningAndQueryingByTwoListenersItems() { - doListeningAndQueryingByTwoListeners(2); - } - - - private void doListeningAndQueryingByTwoListeners(final int type) { - class L implements LookupListener { - Lookup.Result integer = lookup.lookup(new Template(Integer.class)); - Lookup.Result number = lookup.lookup(new Template(Number.class)); - Lookup.Result serial = lookup.lookup(new Template(Serializable.class)); - - { - integer.addLookupListener(this); - number.addLookupListener(this); - serial.addLookupListener(this); - } - - int round; - - public void resultChanged(LookupEvent ev) { - Collection c1 = get(type, integer); - Collection c2 = get(type, number); - Collection c3 = get(type, serial); - - assertEquals("round " + round + " c1 vs. c2", c1, c2); - assertEquals("round " + round + " c1 vs. c3", c1, c3); - assertEquals("round " + round + " c2 vs. c3", c2, c3); - - round++; - } - - private Collection get(int type, Lookup.Result res) { - Collection c; - switch(type) { - case 0: c = res.allInstances(); break; - case 1: c = res.allClasses(); break; - case 2: c = res.allItems(); break; - default: c = null; fail("Type: " + type); break; - } - - assertNotNull(c); - return new ArrayList(c); - } - } - - L listener = new L(); - listener.resultChanged(null); - - for(int i = 0; i < 100; i++) { - ic.add(new Integer(i)); - } - - assertEquals("3x100+1 checks", 301, listener.round); - } - - public void testChangeOfNodeDoesNotFireChangeInActionMap() { - ActionMap am = new ActionMap(); - Lookup s = Lookups.singleton(am); - doChangeOfNodeDoesNotFireChangeInActionMap(am, s, false, 0); - } - public void testChangeOfNodeDoesNotFireChangeInActionMapSimple() { - ActionMap am = new ActionMap(); - Lookup s = Lookups.singleton(am); - doChangeOfNodeDoesNotFireChangeInActionMap(am, s, true, 0); - } - - public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookupSimple() { - doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(true); - } - - public void testChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup() { - doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(false); - } - private void doChangeOfNodeDoesNotFireChangeInActionMapWithBeforeLookup(boolean wrapBySimple) { - final ActionMap am = new ActionMap(); - - class Before extends AbstractLookup { - public InstanceContent ic; - public Before() { - this(new InstanceContent()); - } - - private Before(InstanceContent ic) { - super(ic); - this.ic = ic; - } - - protected @Override void beforeLookup(Template template) { - if (ic != null) { - ic.add(am); - ic = null; - } - } - } - - Before s = new Before(); - doChangeOfNodeDoesNotFireChangeInActionMap(am, s, wrapBySimple, 1); - - assertNull("beforeLookup called once", s.ic); - } - - private void doChangeOfNodeDoesNotFireChangeInActionMap(final ActionMap am, Lookup actionMapLookup, final boolean wrapBySimple, int firstChange) { - Lookup[] lookups = { lookup, actionMapLookup }; - - class Provider implements Lookup.Provider { - ProxyLookup delegate; - Lookup query; - - public Provider(Lookup[] arr) { - if (wrapBySimple) { - delegate = new ProxyLookup(arr); - query = Lookups.proxy(this); - } else { - query = delegate = new ProxyLookup(arr); - } - } - - public Lookup getLookup() { - return delegate; - } - - public void setLookups(Lookup... arr) { - if (wrapBySimple) { - delegate = new ProxyLookup(arr); - } else { - delegate.setLookups(arr); - } - } - } - - Provider p = new Provider(lookups); - - Lookup.Result res = p.query.lookup(new Lookup.Template(ActionMap.class)); - LL ll = new LL(); - res.addLookupListener(ll); - - Collection c = res.allInstances(); - assertFalse("Has next", c.isEmpty()); - - ActionMap am1 = (ActionMap)c.iterator().next(); - assertEquals("Am is there", am, am1); - - assertEquals("Correct # of changes in first get", firstChange, ll.getCount()); - - Object m1 = new InputMap(); - Object m2 = new InputMap(); - - ic.add(m1); - assertEquals("No change in ActionMap 1", 0, ll.getCount()); - ic.set(Collections.singletonList(m2), null); - assertEquals("No change in ActionMap 2", 0, ll.getCount()); - ic.add(m2); - assertEquals("No change in ActionMap 3", 0, ll.getCount()); - p.setLookups(lookup, actionMapLookup, Lookup.EMPTY); - assertEquals("No change in ActionMap 4", 0, ll.getCount()); - - ActionMap am2 = p.query.lookup(ActionMap.class); - assertEquals("Still the same action map", am, am2); - - - class Before extends AbstractLookup { - public InstanceContent ic; - public Before() { - this(new InstanceContent()); - } - - private Before(InstanceContent ic) { - super(ic); - this.ic = ic; - } - - protected @Override void beforeLookup(Template template) { - if (ic != null) { - ic.add(am); - ic = null; - } - } - } - - Before s = new Before(); - - // adding different Before, but returning the same instance - // this happens with metaInfServices lookup often, moreover - // it adds the instance in beforeLookup, which confuses a lot - p.setLookups(new Lookup[]{ lookup, new Before() }); - assertEquals("No change in ActionMap 5", 0, ll.getCount()); - - - } - - public void testTasklistsCase() throws Exception { - ic.remove(new Object()); - } - - - - public void testMultipleListeners() { - Object object = new ImplementationObject(); - ic.add(object); - - Listener[] listeners = new Listener[4]; - Lookup.Result result = lookup.lookup(new Lookup.Template(LookupObject.class)); - for(int i = 0; i < listeners.length; ++i) { - listeners[i] = new Listener(); - result.addLookupListener(listeners[i]); - } - // initialize listening - result.allItems(); - - ic.remove(object); - - // Apparently, only odd-numbered listeners get called when there are multiple LookupListeners on a result - //for(int i = 0; i < listeners.length; ++i) { - // System.out.println("Listener " + i + ": " + listeners[i].wasCalled()); - //} - for(int i = 0; i < listeners.length; ++i) { - assertTrue("Listener " + i + " called", listeners[i].wasCalled()); - } - } - - static Object reserialize(Object o) throws Exception { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(os); - oos.writeObject(o); - oos.close(); - - ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); - ObjectInputStream ois = new ObjectInputStream(is); - return ois.readObject(); - } - - private class Listener implements LookupListener { - private boolean listenerCalled = false; - - public void resultChanged(LookupEvent ev) { - listenerCalled = true; - } - - public boolean wasCalled() { - return listenerCalled; - } - - public void reset() { - listenerCalled = false; - } - } - - private interface LookupObject {} - private class ImplementationObject implements LookupObject {} - private class NullObject implements LookupObject {} - - - public void testReturnSomethingElseThenYouClaimYouWillReturn() { - class Liar extends AbstractLookup.Pair { - public Object obj; - - protected boolean instanceOf(Class c) { - return c.isAssignableFrom(String.class); - } - - protected boolean creatorOf(Object obj) { - return this.obj == obj; - } - - public Object getInstance() { - return this.obj; - } - - public Class getType() { - return String.class; - } - - public String getId() { - return String.class.getName(); - } - - public String getDisplayName() { - return getId(); - } - } - - - Liar l = new Liar(); - l.obj = new Integer(5); - - this.ic.addPair(l); - - Collection c = lookup.lookup(new Lookup.Template(String.class)).allInstances(); - assertTrue("It is empty: " + c, c.isEmpty()); - } - - public void testCanProxyLookupHaveWrongResults() { - class L implements LookupListener { - ProxyLookup pl; - Lookup.Result original; - Lookup.Result wrapped; - boolean ok; - - public void test() { - pl = new ProxyLookup(lookup); - original = lookup.lookupResult(String.class); - - original.addLookupListener(this); - - wrapped = pl.lookupResult(String.class); - - assertEquals("Original empty", 0, original.allInstances().size()); - assertEquals("Wrapped empty", 0, wrapped.allInstances().size()); - - ic.add("Hello!"); - } - - public void resultChanged(LookupEvent ev) { - ok = true; - - assertEquals("Original has hello", 1, original.allInstances().size()); - assertEquals("Wrapped has hello", 1, wrapped.allInstances().size()); - } - - } - L listener = new L(); - listener.test(); - assertTrue("Listener called", listener.ok); - } - - public void testObjectFromInstanceContentConverterDisappearsIfNotReferenced() { - Conv converter = new Conv("foo"); - ic.add (converter, converter); - Lookup lkp = instanceLookup; - StringBuilder sb = lookup.lookup (StringBuilder.class); - assertNotNull (sb); - int hash = System.identityHashCode(sb); - assertEquals ("foo", sb.toString()); - Reference r = new WeakReference(sb); - sb = null; - assertGC("Lookup held onto object", r); - sb = lookup.lookup (StringBuilder.class); - assertNotSame(hash, System.identityHashCode(sb)); - r = new WeakReference(sb); - sb = null; - assertGC("Lookup held onto object", r); - ic.remove (converter, converter); - Reference cref = new WeakReference(converter); - converter = null; - assertGC("Converter still referenced", cref); - - sb = lkp.lookup(StringBuilder.class); - assertNull ("Converter removed from lookup, but object it " + - "created still present:'" + sb +"'", sb); - converter = new Conv("bar"); - ic.add (converter, converter); - assertNotNull (lkp.lookup(StringBuilder.class)); - assertEquals ("bar", lkp.lookup(StringBuilder.class).toString()); - } - - private static class Conv implements InstanceContent.Convertor { - private final String str; - private Conv (String str) { - this.str = str; - } - - public StringBuilder convert(Conv obj) { - return new StringBuilder (str); - } - - public Class type(Conv obj) { - return StringBuilder.class; - } - - public String id(Conv obj) { - return "Foo"; - } - - public String displayName(Conv obj) { - return "Foo"; - } - } // end of Conv - - public void testCanGCResults() throws Exception { - class L implements LookupListener { - int cnt; - - public void resultChanged(LookupEvent ev) { - cnt++; - } - - } - L listener1 = new L(); - L listener2 = new L(); - - Lookup.Result res1 = this.instanceLookup.lookupResult(String.class); - Lookup.Result res2 = this.lookup.lookupResult(String.class); - - assertEquals("Empty1", 0, res1.allItems().size()); - assertEquals("Empty2", 0, res2.allItems().size()); - - res1.addLookupListener(listener1); - res2.addLookupListener(listener2); - - addInstances(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - this.ic.add("Ahoj"); - - assertEquals("Change1", 1, listener1.cnt); - assertEquals("Change2", 1, listener2.cnt); - - assertEquals("Full1", 1, res1.allItems().size()); - assertEquals("Full2", 1, res2.allItems().size()); - - - Reference ref2 = new WeakReference(res2); - res2 = null; - assertGC("Result can disappear", ref2); - } - - void beforeActualTest(String n) { - if (n.equals("testEqualsIsNotCalledTooMuch")) { - CntPair.cnt = 0; - CntPair.hashCnt = 0; - CntPair.instances = 0; - int how = 1000; - - for(int i = 0; i < how; i++) { - this.ic.addPair(new CntPair("x" + i)); - } - - assertEquals("No equals called", 0, CntPair.cnt); - assertEquals("1000 instances ", how, CntPair.instances); - } - } - - public void testEqualsIsNotCalledTooMuch() throws Exception { - // most of the work done in beforeActualTest - - // desirable: assertEquals("no comparitions", 0, CntPair.cnt); - // works for InheritanceTree, but not for ArrayStorage, but array - // storages are generally small - - if (CntPair.cnt > 12000) { - fail("Too much comparitions " + CntPair.cnt); - } - if (CntPair.hashCnt > 40000) { - fail("Too much hashes: " + CntPair.hashCnt); - } - - assertEquals("instaces is enough", 1000, CntPair.instances); - } - - /** Adds instances to the instance lookup. - */ - private void addInstances (Object... instances) { - for (int i = 0; i < instances.length; i++) { - ic.add(instances[i]); - } - } - - /** Count instances of clazz in an array. */ - private int countInstances (Object[] objs, Class clazz) { - int count = 0; - for (int i = 0; i < objs.length; i++) { - if (clazz.isInstance(objs[i])) count++; - } - return count; - } - - /** Counting listener */ - protected static class LL implements LookupListener { - private int count = 0; - public Object source; - public Thread changesIn; - - public LL () { - this (null); - } - - public LL (Object source) { - this.source = source; - } - - public void resultChanged(LookupEvent ev) { - if (changesIn != null) { - assertEquals("Changes in the same thread", changesIn, Thread.currentThread()); - } else { - changesIn = Thread.currentThread(); - } - ++count; - if (source != null) { - assertSame ("Source is the same", source, ev.getSource ()); -// assertSame ("Result is the same", source, ev.getResult ()); - } - } - - public int getCount() { - int i = count; - count = 0; - return i; - } - }; - - /** A set of interfaces for testInterfaceInheritance - */ - interface TestInterfaceInheritanceA {} - interface TestInterfaceInheritanceB extends TestInterfaceInheritanceA, java.rmi.Remote {} - interface TestInterfaceInheritanceBB extends TestInterfaceInheritanceB {} - interface TestInterfaceInheritanceC extends TestInterfaceInheritanceA, java.rmi.Remote {} - interface TestInterfaceInheritanceD extends TestInterfaceInheritanceA {} - - /** A special class for garbage test */ - public static final class Garbage extends Object implements Serializable { - static final long serialVersionUID = 435340912534L; - } - - - /* A classloader that can load one class in a special way */ - private static class CL extends ClassLoader { - public CL () { - super (null); - } - - public @Override Class findClass(String name) throws ClassNotFoundException { - if (name.equals (Garbage.class.getName ())) { - String n = name.replace ('.', '/'); - java.io.InputStream is = getClass ().getResourceAsStream ("/" + n + ".class"); - byte[] arr = new byte[8096]; - try { - int cnt = is.read (arr); - if (cnt == arr.length) { - fail ("Buffer to load the class is not big enough"); - } - - return defineClass (name, arr, 0, cnt); - } catch (java.io.IOException ex) { - ex.printStackTrace(); - fail ("IO Exception"); - return null; - } - } else { - return null; - } - } - - /** Convert obj to other object. There is no need to implement - * cache mechanism. It is provided by AbstractLookup.Item.getInstance(). - * Method should be called more than once because Lookup holds - * just weak reference. - */ - public Object convert(Object obj) { - return null; - } - - /** Return type of converted object. */ - public Class type(Object obj) { - try { - return loadClass (Garbage.class.getName ()); - } catch (ClassNotFoundException ex) { - fail ("Class not found"); - throw new InternalError (); - } - } - } - - private static final class CntPair extends AbstractLookup.Pair { - private static int instances; - private String txt; - - public CntPair(String txt) { - this.txt = txt; - instances++; - } - - public static int hashCnt; - @Override - public int hashCode() { - hashCnt++; - return txt.hashCode() + 3777; - } - - public static int cnt; - @Override - public boolean equals(Object obj) { - cnt++; - - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final CntPair other = (CntPair) obj; - if (this.txt != other.txt && (this.txt == null || !this.txt.equals(other.txt))) { - return false; - } - return true; - } - - protected boolean instanceOf(Class c) { - return c.isAssignableFrom(String.class); - } - - protected boolean creatorOf(Object obj) { - return obj == txt; - } - - public Object getInstance() { - return txt; - } - - public Class getType() { - return String.class; - } - - public String getId() { - return txt; - } - - public String getDisplayName() { - return txt; - } - - } - - public static final class SerialPair extends AbstractLookup.Pair - implements java.io.Serializable { - static final long serialVersionUID = 54305834L; - private Object value; - public transient int countInstanceOf; - - public SerialPair (Object value) { - this.value = value; - } - - protected boolean creatorOf(Object obj) { - return obj == value; - } - - public String getDisplayName() { - return getId (); - } - - public String getId() { - return value.toString(); - } - - public Object getInstance() { - return value; - } - - public Class getType() { - return value.getClass (); - } - - protected boolean instanceOf(Class c) { - countInstanceOf++; - return c.isInstance(value); - } - } // end of SerialPair - - private static class BrokenPair extends AbstractLookup.Pair { - private transient ThreadLocal IN = new ThreadLocal (); - private boolean checkModify; - private boolean checkQuery; - - public BrokenPair (boolean checkModify, boolean checkQuery) { - this.checkModify = checkModify; - this.checkQuery = checkQuery; - } - - protected boolean creatorOf(Object obj) { return this == obj; } - public String getDisplayName() { return "Broken"; } - public String getId() { return "broken"; } - public Object getInstance() { return this; } - public Class getType() { return getClass (); } - protected boolean instanceOf(Class c) { - - if (checkQuery) { - if (IN.get () == null) { - try { - IN.set (this); - // broken behaviour, tries to modify the lookup - // queries have to survive - - running.lookup.lookup (java.awt.List.class); - - // - // creation of new result has to survive as well - Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.Button.class)); - Collection all = myQuery.allItems (); - } finally { - IN.set (null); - } - } - } - - - if (checkModify) { - // - // modifications should fail - // - - try { - running.ic.addPair (new SerialPair ("")); - fail ("Modification from a query should be prohibited"); - } catch (IllegalStateException ex) { - } - - try { - running.ic.removePair (this); - fail ("This has to throw the exception"); - } catch (IllegalStateException ex) { - } - try { - running.ic.setPairs (Collections.EMPTY_SET); - fail ("This has to throw the exception as well"); - } catch (IllegalStateException ex) { - } - } - - return c.isAssignableFrom(getType ()); - } - } // end of BrokenPair - - private static class Broken2Pair extends AbstractLookup.Pair { - static final long serialVersionUID = 4532587018501L; - public transient ThreadLocal IN; - - public Broken2Pair () { - } - - private void writeObject (java.io.ObjectOutputStream oos) throws java.io.IOException { - } - - private void readObject (java.io.ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException { - IN = new ThreadLocal (); - } - - protected boolean creatorOf(Object obj) { return this == obj; } - public String getDisplayName() { return "Broken"; } - public String getId() { return "broken"; } - public Object getInstance() { return this; } - public Class getType() { return getClass (); } - protected boolean instanceOf(Class c) { - - // behaviour gets broken only after deserialization - if (IN != null && IN.get () == null) { - try { - IN.set (this); - - // creation of new result has to survive as well - Lookup.Result myQuery = running.lookup.lookup (new Lookup.Template (java.awt.List.class)); - Collection all = myQuery.allItems (); - } finally { - IN.set (null); - } - } - - return c.isAssignableFrom(getType ()); - } - } // end of Broken2Pair -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/AbstractLookupExecutorTest.java --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupExecutorTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.concurrent.Executor; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; - -public class AbstractLookupExecutorTest extends AbstractLookupBaseHid -implements AbstractLookupBaseHid.Impl, Executor, LookupListener { - Lookup.Result res; - - - public AbstractLookupExecutorTest(java.lang.String testName) { - super(testName, null); - } - - // - // Impl of AbstractLookupBaseHid.Impl - // - - /** Creates the initial abstract lookup. - */ - public Lookup createInstancesLookup (InstanceContent ic) { - ic.attachExecutor(this); - Lookup l = new AbstractLookup (ic, new InheritanceTree ()); - return l; - } - - /** Creates an lookup for given lookup. This class just returns - * the object passed in, but subclasses can be different. - * @param lookup in lookup - * @return a lookup to use - */ - public Lookup createLookup (Lookup lookup) { - res = lookup.lookupResult(Object.class); - res.addLookupListener(this); - return lookup; - } - - public void clearCaches () { - } - - ThreadLocal ME = new ThreadLocal(); - public void execute(Runnable command) { - assertEquals("Not yet set", null, ME.get()); - ME.set(this); - try { - command.run(); - } finally { - ME.set(null); - } - } - - public void resultChanged(LookupEvent ev) { - assertEquals("Changes delivered only from execute method", this, ME.get()); - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/AbstractLookupMemoryTest.java --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupMemoryTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.*; -import org.netbeans.junit.*; -import org.netbeans.modules.openide.util.ActiveQueue; -import org.openide.util.Lookup; - -/** Testing memory consumption of various AbstractLookup aspects. - */ -public class AbstractLookupMemoryTest extends NbTestCase { - public AbstractLookupMemoryTest(java.lang.String testName) { - super(testName); - } - - public static void main(java.lang.String[] args) { - junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupMemoryTest.class)); - } - - public void testEmptySize () { - AbstractLookup instanceLookup = new AbstractLookup (); - assertSize ("Empty lookup should be small", 16, instanceLookup); - - InstanceContent ic = new InstanceContent (); - instanceLookup = new AbstractLookup (ic); - assertSize ("Lookup with InstanceContent should be small as well", 16, instanceLookup); - } - - public void testPairSize () { - AbstractLookup.Pair pair = new EmptyPair (); - assertSize ("Pair occupies only 16 bytes", 16, pair); - } - - public void testPairWithOnePointerSize () { - AbstractLookup.Pair pair = new OneItemPair (); - assertSize ("Pair occupies only 16 bytes", 16, pair); - } - - public void testLookupWithPairs () { - Lookup.Template t = new Lookup.Template(Object.class); - class L implements org.openide.util.LookupListener { - public int cnt; - public void resultChanged (org.openide.util.LookupEvent ev) { - cnt++; - } - } - L listener = new L (); - L listener2 = new L (); - - EmptyPair[] pairs = { - new EmptyPair(), - new EmptyPair(), - new EmptyPair(), - new EmptyPair(), - }; - Object[] ignore = { - pairs[0], - pairs[1], - pairs[2], - pairs[3], - t, - ActiveQueue.queue(), - listener, - listener2, - new Integer (11) // trashhold is shared - }; - - AbstractLookup.Content c = new AbstractLookup.Content (); - AbstractLookup l = new AbstractLookup (c, (Integer)ignore[ignore.length - 1]); - - c.addPair ((EmptyPair)ignore[0]); - assertSize ("Should be really small (not counting the pair sizes)", Collections.singleton (l), 56, ignore); - - c.addPair ((EmptyPair)ignore[1]); - assertSize ("Is bigger I guess (not counting the pair sizes)", Collections.singleton (l), 56, ignore); - - c.setPairs(Arrays.asList(pairs).subList(0, 3)); - assertSize ("Even bigger (not counting the pair sizes)", Collections.singleton (l), 64, ignore); - - c.setPairs(Arrays.asList(pairs).subList(0, 4)); - assertSize ("Now not that much(not counting the pair sizes)", Collections.singleton (l), 64, ignore); - - Lookup.Result res = l.lookup (t); - - assertSize ("After creating a result", Collections.singleton (l), 120, ignore); - - res.addLookupListener (listener); - - assertSize ("And attaching one listener", Collections.singleton (l), 120, ignore); - - res.addLookupListener (listener2); - assertSize ("Second listener makes the situation much worse", Collections.singleton (l), 200, ignore); - res.removeLookupListener(listener2); - assertSize ("But removing it returns us back to original size", Collections.singleton (l), 120, ignore); - - - assertEquals ("Current for pairs are in", res.allItems ().size (), 4); // also activates the listener - assertSize ("and making the listener to work", Collections.singleton (l), 120, ignore); - - c.removePair ((EmptyPair)ignore[0]); - assertEquals ("A changes has been delivered", 1, listener.cnt); - } - - /** Simple pair with no data */ - private static class EmptyPair extends AbstractLookup.Pair { - protected boolean creatorOf(Object obj) { return false; } - public String getDisplayName() { return ""; } - public String getId() { return ""; } - public Object getInstance() { return null; } - public Class getType() { return Object.class; } - protected boolean instanceOf(Class c) { return c == getType (); } - } // end of EmptyPair - - /** Pair with one item (like InstanceContent.Pair) */ - private static class OneItemPair extends EmptyPair { - private Object pointer; - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/AbstractLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/AbstractLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,353 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.concurrent.ExecutionException; - -import java.lang.ref.WeakReference; -import java.util.*; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import junit.framework.Test; -import org.netbeans.junit.*; -import org.openide.util.Lookup; -import org.openide.util.lookup.AbstractLookup.Pair; - -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them -public class AbstractLookupTest extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl { - public AbstractLookupTest(java.lang.String testName) { - super(testName, null); - } - - // - // Impl of AbstractLookupBaseHid.Impl - // - - /** Creates the initial abstract lookup. - */ - public Lookup createInstancesLookup (InstanceContent ic) { - return new AbstractLookup (ic, new InheritanceTree ()); - } - - /** Creates an lookup for given lookup. This class just returns - * the object passed in, but subclasses can be different. - * @param lookup in lookup - * @return a lookup to use - */ - public Lookup createLookup (Lookup lookup) { - return lookup; - } - - public void clearCaches () { - } - - static class LkpResultCanBeGargageCollectedAndClearsTheResult extends AbstractLookup { - public int cleared; - public int dirty; - - synchronized @Override boolean cleanUpResult(Template t) { - boolean res = super.cleanUpResult (t); - if (res) { - cleared++; - } else { - dirty++; - } - - notifyAll (); - - return res; - } - } - public void testResultCanBeGargageCollectedAndClearsTheResult () throws Exception { - LkpResultCanBeGargageCollectedAndClearsTheResult lkp = new LkpResultCanBeGargageCollectedAndClearsTheResult (); - assertSize ("24 for AbstractLookup, 8 for two ints", 32, lkp); - synchronized (lkp) { - Lookup.Result res = lkp.lookup (new Lookup.Template (getClass ())); - res.allItems(); - - WeakReference ref = new WeakReference (res); - res = null; - assertGC ("Reference can get cleared", ref); - - // wait till we - while (lkp.cleared == 0 && lkp.dirty == 0) { - lkp.wait (); - } - - assertEquals ("No dirty cleanups", 0, lkp.dirty); - assertEquals ("One final cleanup", 1, lkp.cleared); - } - //assertSize ("Everything has been cleaned to original size", 32, lkp); - - } - - public void testPairCannotBeUsedInMoreThanOneLookupAtOnce () throws Exception { - /** Simple pair with no data */ - class EmptyPair extends AbstractLookup.Pair { - protected boolean creatorOf(Object obj) { return false; } - public String getDisplayName() { return "Empty"; } - public String getId() { return "empty"; } - public Object getInstance() { return null; } - public Class getType() { return Object.class; } - protected boolean instanceOf(Class c) { return c == getType (); } - } // end of EmptyPair - - AbstractLookup.Content c1 = new AbstractLookup.Content (); - AbstractLookup.Content c2 = new AbstractLookup.Content (); - AbstractLookup l1 = new AbstractLookup (c1); - AbstractLookup l2 = new AbstractLookup (c2); - - EmptyPair empty = new EmptyPair (); - c1.addPair (empty); - Lookup.Result res = l1.lookup (new Lookup.Template (Object.class)); - assertEquals ( - "Pair is really found", empty, - res.allItems ().iterator().next () - ); - try { - c2.addPair (empty); - fail ("It should not be possible to add pair to two lookups"); - } catch (IllegalStateException ex) { - // ok, exception is fine - } - assertEquals ( - "L2 is still empty", Collections.EMPTY_LIST, - new ArrayList (l2.lookup (new Lookup.Template (Object.class)).allItems ()) - ); - } - - public void testInitializationCanBeDoneFromAnotherThread () { - class MyLkp extends AbstractLookup implements Runnable { - private InstanceContent ic; - private boolean direct; - - public MyLkp (boolean direct) { - this (direct, new InstanceContent ()); - } - - private MyLkp (boolean direct, InstanceContent ic) { - super (ic); - this.direct = direct; - this.ic = ic; - } - - protected @Override void initialize() { - if (direct) { - run (); - } else { - try { - Executors.newSingleThreadScheduledExecutor().schedule(this, 0, TimeUnit.MICROSECONDS).get(); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } catch (ExecutionException ex) { - ex.printStackTrace(); - } - } - } - - public void run () { - ic.add (this); - ic.remove (this); - ic.set (Collections.nCopies(10, this), null); - ic.set (Collections.EMPTY_LIST, null); - ic.add (AbstractLookupTest.this); - } - } - - assertEquals ("The test should be there", this, new MyLkp (true).lookup (Object.class)); - assertEquals ("and in async mode as well", this, new MyLkp (false).lookup (Object.class)); - } - - public void testBeforeLookupIsCalled () { - class BeforeL extends AbstractLookup { - public ArrayList list = new ArrayList (); - public String toAdd; - public InstanceContent ic; - - public BeforeL () { - this (new InstanceContent ()); - } - - private BeforeL (InstanceContent c) { - super (c); - this.ic = c; - } - - protected @Override void beforeLookup(Template t) { - if (toAdd != null) { - list.add (0, new SerialPair (toAdd)); - setPairs (list); - } else { - ic.add (new Integer (1)); - } - } - } - - BeforeL lookup = new BeforeL (); - - lookup.toAdd = "First"; - assertEquals ("First if found", "First", lookup.lookup (String.class)); - - lookup.toAdd = "2"; - assertEquals ("2 is not first", "2", lookup.lookup (String.class)); - - Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class)); - for (int i = 3; i < 20; i++) { - lookup.toAdd = String.valueOf (i); - assertEquals (i + " items are now there", i, res.allInstances ().size ()); - } - for (int i = 20; i < 35; i++) { - lookup.toAdd = String.valueOf (i); - assertEquals (i + " items are now there", i, res.allItems ().size ()); - } - - assertEquals ("Just strings are there now", 1, res.allClasses ().size ()); - lookup.toAdd = null; // this will add integer - assertEquals ("Two classes now", 2, res.allClasses ().size ()); - } - - public void testInconsistentAfterDeserIssue71744() throws Exception { - InheritanceTree inhTree = new InheritanceTree(); - - AbstractLookup al = new AbstractLookup(new AbstractLookup.Content(), inhTree); - { - - Collection r = al.lookup(new Lookup.Template(Integer.class)).allInstances(); - assertEquals("None", 0, r.size()); - } - - ICP item = new ICP(new Integer(10)); - al.addPair(item); - al.removePair(item); - - AbstractLookup newLookup = (AbstractLookup)reserialize(al); - - newLookup.lookup(Number.class); - - - newLookup.addPair(new ICP(new Long(20))); - - { - - Collection r = newLookup.lookup(new Lookup.Template(Number.class)).allInstances(); - assertEquals("one", 1, r.size()); -/* - Iterator it = r.iterator(); - assertEquals(new Integer(10), it.next()); - assertEquals(new Long(20), it.next());*/ - } - } - - public void testMatchesIssue130673() { - class BrokenPairReturningNullID extends Pair { - @Override - protected boolean instanceOf(Class c) { - return false; - } - - @Override - protected boolean creatorOf(Object obj) { - return false; - } - - @Override - public Object getInstance() { - return null; - } - - @Override - public Class getType() { - return null; - } - - @Override - public String getId() { - return null; - } - - @Override - public String getDisplayName() { - return null; - } - } - BrokenPairReturningNullID broken = new BrokenPairReturningNullID(); - - - Lookup.Template t = new Lookup.Template(String.class, "ID", null); - boolean not = AbstractLookup.matches(t, broken, true); - assertFalse("Does not match the template, but throws no exception", not); - } - - private static final class ICP extends AbstractLookup.Pair { - private Number s; - - public ICP (Number s) { - this.s = s; - } - - - protected boolean instanceOf(Class c) { - return c.isInstance(s); - } - - protected boolean creatorOf(Object obj) { - return s == obj; - } - - public Object getInstance() { - return s; - } - - public Class getType() { - return s.getClass(); - } - - public String getId() { - return s.toString(); - } - - public String getDisplayName() { - return getId(); - } - - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/ExcludingLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/ExcludingLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.*; -import org.openide.util.Lookup; - -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional. - */ -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them -public class ExcludingLookupTest extends AbstractLookupBaseHid -implements AbstractLookupBaseHid.Impl { - public ExcludingLookupTest(java.lang.String testName) { - super(testName, null); - } - - public Lookup createLookup (final Lookup lookup) { - return Lookups.exclude (lookup, new Class[0]); - } - - public Lookup createInstancesLookup (InstanceContent ic) { - return new AbstractLookup (ic); - } - - public void clearCaches () { - } - - public void testWeCanRemoveInteger () throws Exception { - doBasicFilteringTest (Integer.class, Integer.class, 0); - } - - public void testWeCanRemoveIntegersEvenByAskingForRemoveOfAllNumbers () throws Exception { - doBasicFilteringTest (Number.class, Integer.class, 0); - } - public void testFunWithInterfaces () throws Exception { - doBasicFilteringTest (java.io.Serializable.class, Integer.class, 0); - } - - public void testWeCanGetInstanceOfSerializableEvenItIsExcludedIfWeAskForClassNotExtendingIt () throws Exception { - Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { java.io.Serializable.class }); - Lookup.Template t = new Lookup.Template (Object.class); - Lookup.Result res = lookup.lookup (t); - - LL ll = new LL (); - res.addLookupListener (ll); - assertEquals ("Nothing is there", 0, res.allItems ().size ()); - - Object inst = new Integer (3); - ic.add (inst); - - assertEquals ("Not Filtered out", inst, lookup.lookup (Object.class)); - assertEquals ("Not Filtered out2", inst, lookup.lookupItem (t).getInstance ()); - assertEquals ("One is there - 2", 1, res.allItems ().size ()); - assertEquals ("One is there - 2a", 1, res.allInstances ().size ()); - assertEquals ("One is there - 2b", 1, res.allClasses ().size ()); - assertEquals ("Right # of events", 1, ll.getCount ()); - - ic.remove (inst); - assertEquals ("Filtered out3", null, lookup.lookupItem (t)); - assertEquals ("Nothing is there - 3", 0, res.allItems ().size ()); - assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ()); - assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ()); - assertEquals ("Of course it is not there", null, lookup.lookup (Object.class)); - assertEquals ("Right # of events", 1, ll.getCount ()); - } - - public void testIntegersQueriedThruObject () throws Exception { - doBasicFilteringTest (Number.class, Object.class, 1); - } - - private void doBasicFilteringTest (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception { - Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter }); - Lookup.Template t = new Lookup.Template (theQuery); - Lookup.Result res = lookup.lookup (t); - - LL ll = new LL (); - res.addLookupListener (ll); - assertEquals ("Nothing is there", 0, res.allItems ().size ()); - - Object inst = new Integer (3); - ic.add (inst); - - assertEquals ("Filtered out", null, lookup.lookup (theQuery)); - assertEquals ("Filtered out2", null, lookup.lookupItem (t)); - assertEquals ("Nothing is there - 2", 0, res.allItems ().size ()); - assertEquals ("Nothing is there - 2a", 0, res.allInstances ().size ()); - assertEquals ("Nothing is there - 2b", 0, res.allClasses ().size ()); - assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ()); - - ic.remove (inst); - assertEquals ("Filtered out3", null, lookup.lookupItem (t)); - assertEquals ("Nothing is there - 3", 0, res.allItems ().size ()); - assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ()); - assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ()); - assertEquals ("Of course it is not there", null, lookup.lookup (theQuery)); - assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ()); - - } - - public void testSizeOfTheLookup () throws Exception { - Class exclude = String.class; - - Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { exclude }); - - assertSize ("Should be pretty lightweight", Collections.singleton (lookup), 16, - new Object[] { this.instanceLookup, exclude }); - } - public void testSizeOfTheLookupForMultipleFiltersIsHigher () throws Exception { - Class exclude = String.class; - Class exclude2 = Integer.class; - Class[] arr = new Class[] { exclude, exclude2 }; - - Lookup lookup = Lookups.exclude (this.instanceLookup, arr); - - assertSize ("Is fatter", Collections.singleton (lookup), 40, - new Object[] { this.instanceLookup, exclude, exclude2 }); - assertSize ("But only due to the array", Collections.singleton (lookup), 16, - new Object[] { this.instanceLookup, exclude, exclude2, arr }); - } - - public void testFilteringOfSomething () throws Exception { - doFilteringOfSomething (Runnable.class, java.io.Serializable.class, 1); - } - - private void doFilteringOfSomething (Class theFilter, Class theQuery, int numberOfExcpectedEventsAfterOneChange) throws Exception { - Lookup lookup = Lookups.exclude (this.instanceLookup, new Class[] { theFilter }); - Lookup.Template t = new Lookup.Template (theQuery); - Lookup.Result res = lookup.lookup (t); - - LL ll = new LL (); - res.addLookupListener (ll); - assertEquals ("Nothing is there", 0, res.allItems ().size ()); - - Object inst = new Integer (3); - ic.add (inst); - - assertEquals ("Accepted", inst, lookup.lookup (theQuery)); - assertNotNull ("Accepted too", lookup.lookupItem (t)); - assertEquals ("One is there - 2", 1, res.allItems ().size ()); - assertEquals ("One is there - 2a", 1, res.allInstances ().size ()); - assertEquals ("One is there - 2b", 1, res.allClasses ().size ()); - assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ()); - - Object inst2 = new Thread (); // implements Runnable - ic.add (inst2); - assertEquals ("Accepted - 2", inst, lookup.lookup (theQuery)); - assertNotNull ("Accepted too -2", lookup.lookupItem (t)); - assertEquals ("One is there - 3", 1, res.allItems ().size ()); - assertEquals ("One is there - 3a", 1, res.allInstances ().size ()); - assertEquals ("One is there - 3b", 1, res.allClasses ().size ()); - assertEquals ("Right # of events", 0, ll.getCount ()); - - - ic.remove (inst); - assertEquals ("Filtered out3", null, lookup.lookupItem (t)); - assertEquals ("Nothing is there - 3", 0, res.allItems ().size ()); - assertEquals ("Nothing is there - 3a", 0, res.allInstances ().size ()); - assertEquals ("Nothing is there - 3b", 0, res.allClasses ().size ()); - assertEquals ("Of course it is not there", null, lookup.lookup (theQuery)); - assertEquals ("Right # of events", numberOfExcpectedEventsAfterOneChange, ll.getCount ()); - } - - public void testTheBehaviourAsRequestedByDavidAndDescribedByJesse () throws Exception { - class C implements Runnable, java.io.Serializable { - public void run () {} - } - Object c = new C(); - Lookup l1 = Lookups.singleton(c); - Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class}); - assertNull(l2.lookup(Runnable.class)); - assertEquals(c, l2.lookup(java.io.Serializable.class)); - } - - public void testTheBehaviourAsRequestedByDavidAndDescribedByJesseWithUsageOfResult () throws Exception { - class C implements Runnable, java.io.Serializable { - public void run () {} - } - Object c = new C(); - Lookup l1 = Lookups.singleton(c); - Lookup l2 = Lookups.exclude(l1, new Class[] {Runnable.class}); - - Lookup.Result run = l2.lookup (new Lookup.Template (Runnable.class)); - Lookup.Result ser = l2.lookup (new Lookup.Template (java.io.Serializable.class)); - - assertEquals ("Runnables filtered out", 0, run.allItems ().size ()); - assertEquals ("One serialiazble", 1, ser.allItems ().size ()); - assertEquals ("And it is c", c, ser.allInstances ().iterator ().next ()); - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/InheritanceTreeTest.java --- a/lookup/src/test/java/org/openide/util/lookup/InheritanceTreeTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util.lookup; - -import junit.framework.TestCase; -import junit.framework.*; -import org.openide.util.Lookup; -import org.openide.util.lookup.AbstractLookup.ReferenceIterator; -import org.openide.util.lookup.AbstractLookup.ReferenceToResult; -import java.io.*; -import java.lang.ref.WeakReference; -import java.util.*; - -/** - * - * @author Jaroslav Tulach - */ -public class InheritanceTreeTest extends TestCase { - - public InheritanceTreeTest(String testName) { - super(testName); - } - - protected void setUp() throws Exception { - } - - protected void tearDown() throws Exception { - } - - public void testDeserOfNode() { - InheritanceTree inh = new InheritanceTree(); - InheritanceTree.Node n = new InheritanceTree.Node(String.class); - n.markDeserialized(); - n.markDeserialized(); - - n.assignItem(inh, new InstanceContent.SimpleItem("Ahoj")); - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/InitializationBug44134Test.java --- a/lookup/src/test/java/org/openide/util/lookup/InitializationBug44134Test.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.*; -import org.netbeans.junit.*; -import org.openide.util.Lookup; - -public class InitializationBug44134Test extends NbTestCase { - public InitializationBug44134Test (java.lang.String testName) { - super(testName); - } - - public static void main(java.lang.String[] args) { - junit.textui.TestRunner.run(new NbTestSuite(InitializationBug44134Test.class)); - } - - public void testThereShouldBe18Integers () throws Exception { - FooManifestLookup foo = new FooManifestLookup (); - - Collection items = foo.lookup (new Lookup.Template (Integer.class)).allItems (); - - assertEquals ("18 of them", 18, items.size ()); - - Iterator it = items.iterator (); - while (it.hasNext()) { - Lookup.Item t = (Lookup.Item)it.next (); - assertEquals ("Is Integer", Integer.class, t.getInstance ().getClass ()); - } - } - - - public class FooManifestLookup extends AbstractLookup { - public FooManifestLookup() { - super(); - } - - @Override - protected void initialize() { - for (int i=0; i<18; i++) { - try { - String id= "__" + i; - - addPair(new FooLookupItem(new Integer(i),id)); - } - catch (Exception e) { - } - } - } - - public class FooLookupItem extends AbstractLookup.Pair { - public FooLookupItem(Integer data, String id) { - super(); - this.data=data; - this.id=id; - } - - protected boolean creatorOf(Object obj) { - return obj == data; - } - - public String getDisplayName() { - return data.toString(); - } - - public Class getType () { - return Integer.class; - } - - protected boolean instanceOf (Class c) { - return c.isInstance(data); - } - - public Object getInstance() { - return data; - } - - public String getId() { - return id; - } - - private Integer data; - private String id; - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/KomrskaLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/KomrskaLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2008 Sun Microsystems, Inc. - */ -package org.openide.util.lookup; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; -import static org.junit.Assert.*; - -/** - * Test donated by Mr. Komrska. Seems to pass with 6.5. - * @author komrska - */ -public final class KomrskaLookupTest { - private TestLookupManager lookupManager=null; - private StringBuffer result=null; - - // - - private void addToLookup(final TestLookupItemA object) { - result.append('A'); - lookupManager.add(object); - } - private void removeFromLookup(final TestLookupItemA object) { - result.append('A'); - lookupManager.remove(object); - } - - private void addToLookup(final TestLookupItemB object) { - result.append('B'); - lookupManager.add(object); - } - private void removeFromLookup(final TestLookupItemB object) { - result.append('B'); - lookupManager.remove(object); - } - - public String getResult() { - return result.toString(); - } - - // - - @Before - public void setUp() { - lookupManager=new TestLookupManager(); - result=new StringBuffer(); - } - - @After - public void tearDown() { - lookupManager=null; - result=null; - } - - @Test - public void testLookupBug() { - TestLookupItemA itemA1=new TestLookupItemA(); - TestLookupItemB itemB1=new TestLookupItemB(); - // - addToLookup(itemA1); - addToLookup(itemB1); - removeFromLookup(itemA1); - removeFromLookup(itemB1); - addToLookup(itemB1); - removeFromLookup(itemB1); - // - addToLookup(itemA1); - addToLookup(itemB1); - removeFromLookup(itemA1); - removeFromLookup(itemB1); - addToLookup(itemB1); - removeFromLookup(itemB1); - // - addToLookup(itemA1); - addToLookup(itemB1); - removeFromLookup(itemA1); - removeFromLookup(itemB1); - addToLookup(itemB1); - removeFromLookup(itemB1); - // - assertEquals(getResult(),lookupManager.getResult()); - } - - public static final class TestLookupItemA {} - public static final class TestLookupItemB {} - public static final class TestLookupManager { - private InstanceContent instanceContent=new InstanceContent(); - private AbstractLookup abstractLookup=new AbstractLookup(instanceContent); - - private Lookup.Result resultA=null; - private Lookup.Result resultB=null; - - private LookupListener listenerA=new LookupListener() { - public void resultChanged(LookupEvent event) { - result.append('A'); - } - }; - private LookupListener listenerB=new LookupListener() { - public void resultChanged(LookupEvent event) { - result.append('B'); - } - }; - - private StringBuffer result=new StringBuffer(); - - // - - public TestLookupManager() { - Lookup.Template templateA= - new Lookup.Template(TestLookupItemA.class); - resultA=abstractLookup.lookup(templateA); - resultA.addLookupListener(listenerA); - resultA.allInstances().size(); - // - Lookup.Template templateB= - new Lookup.Template(TestLookupItemB.class); - resultB=abstractLookup.lookup(templateB); - resultB.addLookupListener(listenerB); - resultB.allInstances().size(); - // WORKAROUND - // instanceContent.add(Boolean.TRUE); - } - - // - - public void add(Object item) { - instanceContent.add(item); - } - public void remove(Object item) { - instanceContent.remove(item); - } - public String getResult() { - return result.toString(); - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/LookupBugTest.java --- a/lookup/src/test/java/org/openide/util/lookup/LookupBugTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -package org.openide.util.lookup; - -import java.util.logging.Logger; -import org.junit.Before; -import org.junit.Test; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; -import static org.junit.Assert.*; - -/** - * Test of a Lookup bug seen in NetBeans platforms 6.0-6.5M1. - * @author rlee - */ -public class LookupBugTest implements LookupListener -{ - private static final int MAX_LOOPS = 1000; - - private AbstractLookup lookup; - private InstanceContent content; - private Lookup.Result wordResult; - private Lookup.Result numberResult; - private String word; - private Integer number; - private Logger LOG; - - private boolean fired; - private int i; - - @Before - public void setUp() - { - LOG = Logger.getLogger("test.LookupBugTest"); - content = new InstanceContent(); - lookup = new AbstractLookup(content); - wordResult = lookup.lookupResult(java.lang.String.class); - wordResult.addLookupListener(this); - numberResult = lookup.lookupResult(java.lang.Integer.class); - numberResult.addLookupListener(this); - - fired = false; - } - - @Test - public void lookupTest() - { - for(i = 0; i < MAX_LOOPS; i++ ) - { - word = String.valueOf(i); - number = new Integer(i); - content.add(word); - assertTrue( "word on loop " + i, checkLookupEventFired() ); - content.add(number); - assertTrue( "number on loop " + i, checkLookupEventFired() ); - content.remove(word); - assertTrue( "remove word on loop " + i, checkLookupEventFired() ); - content.remove(number); - assertTrue( "remove number on loop " + i, checkLookupEventFired() ); - - assertTrue("The lookup still needs to stay simple", AbstractLookup.isSimple(lookup)); - } - } - - public void resultChanged(LookupEvent ev) - { - fired = true; - } - - public boolean checkLookupEventFired() - { - LOG.fine(" round: " + i + " word = " + word + " number = " + number); - if( fired ) - { - fired = false; - return true; - } - else return false; - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/LookupsProxyTest.java --- a/lookup/src/test/java/org/openide/util/lookup/LookupsProxyTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.io.Serializable; - -import java.util.*; -import org.netbeans.junit.*; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; - -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional. - */ -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them -public class LookupsProxyTest extends AbstractLookupBaseHid -implements AbstractLookupBaseHid.Impl { - public LookupsProxyTest(java.lang.String testName) { - super(testName, null); - } - - public static void main(java.lang.String[] args) { - junit.textui.TestRunner.run(new NbTestSuite (LookupsProxyTest.class)); - } - - /** Creates an lookup for given lookup. This class just returns - * the object passed in, but subclasses can be different. - * @param lookup in lookup - * @return a lookup to use - */ - public Lookup createLookup (final Lookup lookup) { - return org.openide.util.lookup.Lookups.proxy ( - new Lookup.Provider () { - public Lookup getLookup () { - return lookup; - } - } - ); - } - - public Lookup createInstancesLookup (InstanceContent ic) { - return new AbstractLookup (ic); - } - - public void clearCaches () { - } - - - - /** Check whether setLookups method does not fire when there is no - * change in the lookups. - */ - public void testProxyListener () { - Changer ch = new Changer (Lookup.EMPTY); - - Lookup lookup = Lookups.proxy(ch); - Lookup.Result res = lookup.lookup (new Lookup.Template (Object.class)); - - LL ll = new LL (); - res.addLookupListener (ll); - Collection allRes = res.allInstances (); - - ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup - lookup.lookup (Object.class); // does the refresh - - assertEquals("Replacing an empty by empty does not generate an event", 0, ll.getCount()); - - InstanceContent content = new InstanceContent (); - AbstractLookup del = new AbstractLookup (content); - content.add (this); - ch.setLookup (del); - lookup.lookup (Object.class); - - if (ll.getCount () != 1) { - fail ("Changing lookups with different content generates an event"); - } - - ch.setLookup (del); - lookup.lookup (Object.class); - - if (ll.getCount () != 0) { - fail ("Not changing the lookups does not generate any event"); - } - } - - - public void testListeningAndQueryingByTwoListenersInstancesSetLookups() { - doListeningAndQueryingByTwoListenersSetLookups(0, 1, false); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups() { - doListeningAndQueryingByTwoListenersSetLookups(1, 1, false); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups() { - doListeningAndQueryingByTwoListenersSetLookups(2, 1, false); - } - - public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() { - doListeningAndQueryingByTwoListenersSetLookups(0, 2, false); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups2() { - doListeningAndQueryingByTwoListenersSetLookups(1, 2, false); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups2() { - doListeningAndQueryingByTwoListenersSetLookups(2, 2, false); - } - - public void testListeningAndQueryingByTwoListenersInstancesSetLookupsWithProxy() { - doListeningAndQueryingByTwoListenersSetLookups(0, 1, true); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookupsWithProxy() { - doListeningAndQueryingByTwoListenersSetLookups(1, 1, true); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookupsWithProxy() { - doListeningAndQueryingByTwoListenersSetLookups(2, 1, true); - } - - public void testListeningAndQueryingByTwoListenersInstancesSetLookups2WithProxy() { - doListeningAndQueryingByTwoListenersSetLookups(0, 2, true); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups2WithProxy() { - doListeningAndQueryingByTwoListenersSetLookups(1, 2, true); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups2WithProxy() { - doListeningAndQueryingByTwoListenersSetLookups(2, 2, true); - } - - /* XXX: these are pretty slow, seems there is a performance problem 2^22 - public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() { - doListeningAndQueryingByTwoListenersSetLookups(0, 22); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups22() { - doListeningAndQueryingByTwoListenersSetLookups(1, 22); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups22() { - doListeningAndQueryingByTwoListenersSetLookups(2, 22); - } - */ - - private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth, boolean cacheOnTop) { - Changer orig = new Changer(Lookup.EMPTY); - Lookup on = Lookups.proxy(orig); - Lookup first = on; - - while (--depth > 0) { - Changer next = new Changer(on); - on = Lookups.proxy(next); - } - - - final Lookup lookup = cacheOnTop ? new ProxyLookup(new Lookup[] { on }) : on; - - class L implements LookupListener { - Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class)); - Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class)); - Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class)); - - { - integer.addLookupListener(this); - number.addLookupListener(this); - serial.addLookupListener(this); - } - - int round; - - public void resultChanged(LookupEvent ev) { - Collection c1 = get(type, integer); - Collection c2 = get(type, number); - Collection c3 = get(type, serial); - - assertEquals("round " + round + " c1 vs. c2", c1, c2); - assertEquals("round " + round + " c1 vs. c3", c1, c3); - assertEquals("round " + round + " c2 vs. c3", c2, c3); - - round++; - } - - private Collection get(int type, Lookup.Result res) { - Collection c; - switch(type) { - case 0: c = res.allInstances(); break; - case 1: c = res.allClasses(); break; - case 2: c = res.allItems(); break; - default: c = null; fail("Type: " + type); break; - } - - assertNotNull(c); - return new ArrayList(c); - } - } - - L listener = new L(); - listener.resultChanged(null); - ArrayList arr = new ArrayList(); - for(int i = 0; i < 100; i++) { - arr.add(new Integer(i)); - - orig.lookup = Lookups.fixed(arr.toArray()); - // do the refresh - first.lookup((Class)null); - } - - assertEquals("3x100+1 checks", 301, listener.round); - } - - - public void testRefreshWithoutAllInstances103300 () { - Changer ch = new Changer (Lookup.EMPTY); - - Lookup lookup = Lookups.proxy(ch); - - ch.setLookup (new AbstractLookup (new InstanceContent ())); // another empty lookup - assertNull("Nothing there", lookup.lookup (Object.class)); // does the refresh - - InstanceContent content = new InstanceContent (); - AbstractLookup del = new AbstractLookup (content); - content.add (this); - ch.setLookup (del); - assertEquals("Can see me", this, lookup.lookup (Object.class)); - - ch.setLookup (del); - assertEquals("Still can see me", this, lookup.lookup (Object.class)); - - assertEquals("I am visible", this, lookup.lookup(LookupsProxyTest.class)); - } - - - private static final class Changer implements Lookup.Provider { - private Lookup lookup; - - public Changer (Lookup lookup) { - setLookup (lookup); - } - - public void setLookup (Lookup lookup) { - this.lookup = lookup; - } - - public Lookup getLookup() { - return lookup; - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/MetaInfServicesLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/MetaInfServicesLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,552 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.bar.Comparator2; -import org.netbeans.junit.MockServices; -import org.netbeans.junit.NbTestCase; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; -import org.openide.util.test.MockLookup; - -/** Test finding services from manifest. - * @author Jesse Glick - */ -public class MetaInfServicesLookupTest extends NbTestCase { - private Logger LOG; - private Map lookups = new WeakHashMap(); - - public MetaInfServicesLookupTest(String name) { - super(name); - LOG = Logger.getLogger("Test." + name); - } - - protected String prefix() { - return "META-INF/services/"; - } - - protected Lookup createLookup(ClassLoader c) { - return Lookups.metaInfServices(c); - } - - @Override - protected Level logLevel() { - return Level.INFO; - } - - private Lookup getTestedLookup(ClassLoader c) { - MockServices.setServices(); - Lookup l = lookups.get(c); - if (l == null) { - l = createLookup(c); - lookups.put(c, l); - } - return l; - } - - private URL findJar(String n) throws IOException { - LOG.info("Looking for " + n); - File jarDir = new File(getWorkDir(), "jars"); - jarDir.mkdirs(); - File jar = new File(jarDir, n); - if (jar.exists()) { - return jar.toURI().toURL(); - } - - LOG.info("generating " + jar); - - URL data = MetaInfServicesLookupTest.class.getResource(n.replaceAll("\\.jar", "\\.txt")); - assertNotNull("Data found", data); - StringBuffer sb = new StringBuffer(); - InputStreamReader r = new InputStreamReader(data.openStream()); - for(;;) { - int ch = r.read(); - if (ch == -1) { - break; - } - sb.append((char)ch); - } - - JarOutputStream os = new JarOutputStream(new FileOutputStream(jar)); - - Pattern p = Pattern.compile(":([^:]+):([^:]*)", Pattern.MULTILINE | Pattern.DOTALL); - Matcher m = p.matcher(sb); - Pattern foobar = Pattern.compile("^(org\\.(foo|bar)\\..*)$", Pattern.MULTILINE); - Set names = new TreeSet(); - while (m.find()) { - assert m.groupCount() == 2; - String entryName = prefix() + m.group(1); - LOG.info("putting there entry: " + entryName); - os.putNextEntry(new JarEntry(entryName)); - os.write(m.group(2).getBytes()); - os.closeEntry(); - - Matcher fb = foobar.matcher(m.group(2)); - while (fb.find()) { - String clazz = fb.group(1).replace('.', '/') + ".class"; - LOG.info("will copy " + clazz); - names.add(clazz); - } - } - - for (String copy : names) { - os.putNextEntry(new JarEntry(copy)); - LOG.info("copying " + copy); - InputStream from = MetaInfServicesLookupTest.class.getResourceAsStream("/" + copy); - assertNotNull(copy, from); - for (;;) { - int ch = from.read(); - if (ch == -1) { - break; - } - os.write(ch); - } - from.close(); - os.closeEntry(); - } - os.close(); - LOG.info("done " + jar); - return jar.toURI().toURL(); - } - - ClassLoader c1, c2, c2a, c3, c4; - - @Override - protected void setUp() throws Exception { - clearWorkDir(); - ClassLoader app = getClass().getClassLoader().getParent(); - ClassLoader c0 = app; - - c1 = new URLClassLoader(new URL[] { - findJar("services-jar-1.jar"), - }, c0); - c2 = new URLClassLoader(new URL[] { - findJar("services-jar-2.jar"), - }, c1); - c2a = new URLClassLoader(new URL[] { - findJar("services-jar-2.jar"), - }, c1); - c3 = new URLClassLoader(new URL[] { findJar("services-jar-2.jar") }, - c0 - ); - c4 = new URLClassLoader(new URL[] { - findJar("services-jar-1.jar"), - findJar("services-jar-2.jar"), - }, c0); - } - - @Override - protected void tearDown() throws Exception { - Set> weak = new HashSet>(); - for (Lookup l : lookups.values()) { - weak.add(new WeakReference(l)); - } - - lookups = null; - - for(Reference ref : weak) { - assertGC("Lookup can disappear", ref); - } - } - - public void testBasicUsage() throws Exception { - Lookup l = getTestedLookup(c2); - Class xface = c1.loadClass("org.foo.Interface"); - List results = new ArrayList(l.lookupAll(xface)); - assertEquals("Two items in result: " + results, 2, results.size()); - // Note that they have to be in order: - assertEquals("org.foo.impl.Implementation1", results.get(0).getClass().getName()); - assertEquals("org.bar.Implementation2", results.get(1).getClass().getName()); - // Make sure it does not gratuitously replace items: - List results2 = new ArrayList(l.lookupAll(xface)); - assertEquals(results, results2); - } - - public void testLoaderSkew() throws Exception { - Class xface1 = c1.loadClass("org.foo.Interface"); - Lookup l3 = getTestedLookup(c3); - // If we cannot load Interface, there should be no impls of course... quietly! - assertEquals(Collections.emptyList(), - new ArrayList(l3.lookupAll(xface1))); - Lookup l4 = getTestedLookup(c4); - // If we can load Interface but it is the wrong one, ignore it. - assertEquals(Collections.emptyList(), - new ArrayList(l4.lookupAll(xface1))); - // Make sure l4 is really OK - it can load from its own JARs. - Class xface4 = c4.loadClass("org.foo.Interface"); - assertEquals(2, l4.lookupAll(xface4).size()); - } - - public void testStability() throws Exception { - Lookup l = getTestedLookup(c2); - Class xface = c1.loadClass("org.foo.Interface"); - Object first = l.lookup(xface); - assertEquals(first, l.lookupAll(xface).iterator().next()); - l = getTestedLookup(c2a); - Object second = l.lookup(xface); - assertEquals(first, second); - } - - public void testMaskingOfResources() throws Exception { - Lookup l1 = getTestedLookup(c1); - Lookup l2 = getTestedLookup(c2); - Lookup l4 = getTestedLookup(c4); - - assertNotNull("services1.jar defines a class that implements runnable", l1.lookup(Runnable.class)); - assertNull("services2.jar does not defines a class that implements runnable", l2.lookup(Runnable.class)); - assertNull("services1.jar defines Runnable, but services2.jar masks it out", l4.lookup(Runnable.class)); - } - - public void testOrdering() throws Exception { - Lookup l = getTestedLookup(c1); - Class xface = c1.loadClass("java.util.Comparator"); - List results = new ArrayList(l.lookupAll(xface)); - assertEquals(1, results.size()); - - l = getTestedLookup(c2); - xface = c2.loadClass("java.util.Comparator"); - results = new ArrayList(l.lookupAll(xface)); - assertEquals(2, results.size()); - // Test order: - assertEquals("org.bar.Comparator2", results.get(0).getClass().getName()); - assertEquals("org.foo.impl.Comparator1", results.get(1).getClass().getName()); - - // test that items without position are always at the end - l = getTestedLookup(c2); - xface = c2.loadClass("java.util.Iterator"); - results = new ArrayList(l.lookupAll(xface)); - assertEquals(2, results.size()); - // Test order: - assertEquals("org.bar.Iterator2", results.get(0).getClass().getName()); - assertEquals("org.foo.impl.Iterator1", results.get(1).getClass().getName()); - } - - public void testNoCallToGetResourceForObjectIssue65124() throws Exception { - class Loader extends ClassLoader { - private int counter; - - @Override - protected URL findResource(String name) { - if (name.equals(prefix() + "java.lang.Object")) { - counter++; - } - - URL retValue; - - retValue = super.findResource(name); - return retValue; - } - - @Override - protected Enumeration findResources(String name) throws IOException { - if (name.equals(prefix() + "java.lang.Object")) { - counter++; - } - return super.findResources(name); - } - } - Loader loader = new Loader(); - Lookup l = getTestedLookup(loader); - - Object no = l.lookup(String.class); - assertNull("Not found of course", no); - assertEquals("No lookup of Object", 0, loader.counter); - } - - public void testCanGarbageCollectClasses() throws Exception { - class Loader extends ClassLoader { - public Loader() { - super(Loader.class.getClassLoader().getParent()); - } - - @Override - protected URL findResource(String name) { - if (name.equals(prefix() + "java.lang.Runnable")) { - return Loader.class.getResource("MetaInfServicesLookupTestRunnable.txt"); - } - - URL retValue; - - retValue = super.findResource(name); - return retValue; - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - if (name.equals("org.openide.util.lookup.MetaInfServicesLookupTestRunnable")) { - try { - InputStream is = getClass().getResourceAsStream("MetaInfServicesLookupTestRunnable.class"); - byte[] arr = new byte[is.available()]; - int read = is.read(arr); - assertEquals("Fully read", arr.length, read); - return defineClass(name, arr, 0, arr.length); - } catch (IOException ex) { - throw new ClassNotFoundException("Cannot load", ex); - } - } - throw new ClassNotFoundException(); - } - - - - @Override - protected Enumeration findResources(String name) throws IOException { - if (name.equals(prefix() + "java.lang.Runnable")) { - return Collections.enumeration(Collections.singleton(findResource(name))); - } - return super.findResources(name); - } - } - Loader loader = new Loader(); - Lookup l = getTestedLookup(loader); - - - Object no = l.lookup(Runnable.class); - assertNotNull("Found of course", no); - assertEquals("The right name", "MetaInfServicesLookupTestRunnable", no.getClass().getSimpleName()); - if (no.getClass().getClassLoader() != loader) { - fail("Wrong classloader: " + no.getClass().getClassLoader()); - } - - WeakReference ref = new WeakReference(no.getClass()); - loader = null; - no = null; - l = null; - lookups.clear(); - MockLookup.setInstances(); - Thread.currentThread().setContextClassLoader(null); - assertGC("Class can be garbage collected", ref); - } - - public void testSuperTypes() throws Exception { - doTestSuperTypes(createLookup(c2)); - doTestSuperTypes(new ProxyLookup(createLookup(c2))); - } - private void doTestSuperTypes(Lookup l) throws Exception { - final Class xface = c1.loadClass("org.foo.Interface"); - final Lookup.Result res = l.lookupResult(Object.class); - assertEquals("Nothing yet", 0, res.allInstances().size()); - final AtomicBoolean event = new AtomicBoolean(); - final Thread here = Thread.currentThread(); - res.addLookupListener(new LookupListener() { - public void resultChanged(LookupEvent ev) { - if (Thread.currentThread() == here) { - event.set(true); - } - } - }); - assertNotNull("Interface found", l.lookup(xface)); - assertFalse(event.get()); - class W implements Runnable { - boolean ok; - public synchronized void run() { - ok = true; - notifyAll(); - } - - public synchronized void await() throws Exception { - while (!ok) { - wait(); - } - } - } - W w = new W(); - MetaInfServicesLookup.RP.execute(w); - w.await(); - assertEquals("Now two", 2, res.allInstances().size()); - } - - public void testWrongOrderAsInIssue100320() throws Exception { - ClassLoader app = getClass().getClassLoader().getParent(); - ClassLoader c0 = app; - ClassLoader ctmp = new URLClassLoader(new URL[] { - findJar("problem100320.jar"), - }, c0); - Lookup lookup = Lookups.metaInfServices(ctmp, prefix()); - - Collection colAWT = lookup.lookupAll(IOException.class); - assertEquals("There is enough objects to switch to InheritanceTree", 12, colAWT.size()); - - - List col1 = new ArrayList(lookup.lookupAll(Comparator.class)); - assertEquals("Two", 2, col1.size()); - Collection col2 = lookup.lookupAll(ctmp.loadClass(Comparator2.class.getName())); - assertEquals("One", 1, col2.size()); - List col3 = new ArrayList(lookup.lookupAll(Comparator.class)); - assertEquals("Two2", 2, col3.size()); - - Iterator it1 = col1.iterator(); - Iterator it3 = col3.iterator(); - if ( - it1.next() != it3.next() || - it1.next() != it3.next() - ) { - fail("Collections are different:\nFirst: " + col1 + "\nLast: " + col3); - } - } - - public void testContentionWhenLoadingMetainfServices() throws Exception { - class My extends ClassLoader implements Runnable { - Lookup query; - Integer value; - - public void run() { - value = query.lookup(Integer.class); - } - - - @Override - protected URL findResource(String name) { - waitForTask(name); - return super.findResource(name); - } - - @Override - protected Enumeration findResources(String name) throws IOException { - waitForTask(name); - return super.findResources(name); - } - - private synchronized void waitForTask(String name) { - if (name.startsWith(prefix()) && Thread.currentThread().getName().contains("block")) { - try { - wait(); - } catch (InterruptedException ex) { - Logger.getLogger("global").log(Level.WARNING, "", ex); - } - } - } - } - - My loader = new My(); - loader.query = createLookup(loader); - Thread t = new Thread(loader, "block when querying"); - t.start(); - t.join(1000); - - // this blocks waiting for the waitForTask to finish - // right now - Float f = loader.query.lookup(Float.class); - assertNull("Nothing found", f); - - synchronized (loader) { - loader.notifyAll(); - } - t.join(); - - assertNull("Nothing found", loader.value); - } - - public void testInitializerRobustness() throws Exception { // #174055 - check(Broken1.class.getName()); - check(Broken2.class.getName()); - } - private void check(final String n) { - assertNull(Lookups.metaInfServices(new ClassLoader() { - protected @Override Enumeration findResources(String name) throws IOException { - if (name.equals("META-INF/services/java.lang.Object")) { - return singleton(new URL(null, "dummy:stuff", new URLStreamHandler() { - protected URLConnection openConnection(URL u) throws IOException { - return new URLConnection(u) { - public void connect() throws IOException {} - public @Override InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(n.getBytes("UTF-8")); - } - }; - } - })); - } else { - return Collections.enumeration(Collections.emptyList()); - } - } - - }).lookup(Object.class)); - } - public static class Broken1 { - public Broken1() { - throw new NullPointerException("broken1"); - } - } - public static class Broken2 { - static { - if (true) { // otherwise javac complains - throw new NullPointerException("broken2"); - } - } - } - - static Enumeration singleton(T t) { - return Collections.enumeration(Collections.singleton(t)); - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.java --- a/lookup/src/test/java/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - - -/** - */ -public final class MetaInfServicesLookupTestRunnable implements Runnable { - public void run() { - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/NamedServicesLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/NamedServicesLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import org.openide.util.Lookup; -import org.openide.util.test.MockLookup; - - -/** Test finding services from manifest. - * @author Jaroslav Tulach - */ -public class NamedServicesLookupTest extends MetaInfServicesLookupTest { - static { - MockLookup.init(); - } - public NamedServicesLookupTest(String name) { - super(name); - } - - @Override - protected String prefix() { - return "META-INF/namedservices/sub/path/"; - } - - @Override - protected Lookup createLookup(ClassLoader c) { - MockLookup.setInstances(c); - Thread.currentThread().setContextClassLoader(c); - Lookup l = Lookups.forPath("sub/path"); - return l; - } - - // - // this is not much inheriting test, as we mask most of the tested methods - // anyway, but the infrastructure to generate the JAR files is useful - // - - public @Override void testLoaderSkew() {} - public @Override void testStability() throws Exception {} - public @Override void testMaskingOfResources() throws Exception {} - public @Override void testOrdering() throws Exception {} - public @Override void testNoCallToGetResourceForObjectIssue65124() throws Exception {} - public @Override void testSuperTypes() throws Exception {} - public @Override void testWrongOrderAsInIssue100320() throws Exception {} - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/PathInLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/PathInLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.logging.Level; -import org.netbeans.junit.MockServices; -import org.netbeans.junit.NbTestCase; -import org.netbeans.modules.openide.util.NamedServicesProvider; -import org.openide.util.Lookup; - -/** - * @author Jaroslav Tulach - */ -public class PathInLookupTest extends NbTestCase { - static { - System.setProperty("org.openide.util.Lookup.paths", "MyServices:YourServices"); - MockServices.setServices(P.class); - Lookup.getDefault(); - } - - public PathInLookupTest(String name) { - super(name); - } - - @Override - protected Level logLevel() { - return Level.FINE; - } - - public void testInterfaceFoundInMyServices() throws Exception { - assertNull("not found", Lookup.getDefault().lookup(Shared.class)); - Shared v = new Shared(); - P.ic1.add(v); - assertNotNull("found", Lookup.getDefault().lookup(Shared.class)); - P.ic1.remove(v); - assertNull("not found again", Lookup.getDefault().lookup(Shared.class)); - } - public void testInterfaceFoundInMyServices2() throws Exception { - assertNull("not found", Lookup.getDefault().lookup(Shared.class)); - Shared v = new Shared(); - P.ic2.add(v); - assertNotNull("found", Lookup.getDefault().lookup(Shared.class)); - P.ic2.remove(v); - assertNull("not found again", Lookup.getDefault().lookup(Shared.class)); - } - - static final class Shared extends Object {} - - public static final class P extends NamedServicesProvider { - static InstanceContent ic1 = new InstanceContent(); - static InstanceContent ic2 = new InstanceContent(); - static AbstractLookup[] arr = { - new AbstractLookup(ic1), new AbstractLookup(ic2) - }; - - - @Override - public Lookup create(String path) { - int indx = -1; - if (path.equals("MyServices/")) { - indx = 0; - } - if (path.equals("YourServices/")) { - indx = 1; - } - if (indx == -1) { - fail("Unexpected lookup query: " + path); - } - return arr[indx]; - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/PrefixServicesLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/PrefixServicesLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import org.openide.util.Lookup; - - -/** Test finding services from manifest. - * @author Jaroslav Tulach - */ -public class PrefixServicesLookupTest extends MetaInfServicesLookupTest { - public PrefixServicesLookupTest(String name) { - super(name); - } - - protected String prefix() { - return "META-INF/netbeans/prefix/services/test/"; - } - - protected Lookup createLookup(ClassLoader c) { - return Lookups.metaInfServices(c, prefix()); - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/ProxyLookup173975Test.java --- a/lookup/src/test/java/org/openide/util/lookup/ProxyLookup173975Test.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.openide.util.lookup; - -import java.util.Collection; -import java.util.Collections; -import org.junit.Assert; -import org.junit.Test; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; -import org.openide.util.lookup.AbstractLookup.Storage; - -public class ProxyLookup173975Test { - - public ProxyLookup173975Test() { - } - - boolean called = false; - - @Test - public void testAbstractLookupWithoutAllInstances() { - registerLookupListenerAndAddSomething(false, false, false); - } - - @Test - public void testAbstractLookupWithAllInstances() { - registerLookupListenerAndAddSomething(false, true, false); - } - - @Test - public void testAbstractLookupInheritanceTreeWithoutAllInstances() { - registerLookupListenerAndAddSomething(false, false, true); - } - - @Test - public void testAbstractLookupInheritanceTreeWithAllInstances() { - registerLookupListenerAndAddSomething(false, true, true); - } - - @Test - public void testProxyLookupWithoutAllInstances() { - registerLookupListenerAndAddSomething(true, false, false); - } - - @Test - public void testProxyLookupWithAllInstances() { - registerLookupListenerAndAddSomething(true, true, false); - } - - @Test - public void testProxyLookupInheritanceTreeWithoutAllInstances() { - registerLookupListenerAndAddSomething(true, false, true); - } - - @Test - public void testProxyLookupInheritanceTreeWithAllInstances() { - registerLookupListenerAndAddSomething(true, true, true); - } - - private void registerLookupListenerAndAddSomething(boolean useProxy, boolean callAllInstances, boolean inheritanceTree) { - called = false; - InstanceContent aInstanceContent = new InstanceContent(); - Storage s = inheritanceTree ? new InheritanceTree() : new ArrayStorage(); - Lookup aLookup = new AbstractLookup(aInstanceContent, s); - if (useProxy) { - aLookup = new ProxyLookup(aLookup); - } - Lookup.Result result = aLookup.lookupResult(ObjectInLookup.class); - if (callAllInstances) { - result.allInstances(); // TO GET SUCCESS - } - result.addLookupListener(new LookupListener() { - - public void resultChanged(LookupEvent ev) { - Lookup.Result aResult = (Lookup.Result) ev.getSource(); - Collection c = aResult.allInstances(); - if (!c.isEmpty()) { - called = true; - } - } - }); - - aInstanceContent.set(Collections.singleton( - new ObjectInLookup("Set Object in Lookup)")), null); - Assert.assertTrue("Listener was notified", called); - } - - public class ObjectInLookup { - - private final String name; - - public ObjectInLookup(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } - - @Override - public String toString() { - return "objectinlookup:" + getName(); - } - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/ProxyLookupEventIssue136866Test.java --- a/lookup/src/test/java/org/openide/util/lookup/ProxyLookupEventIssue136866Test.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -package org.openide.util.lookup; - -import junit.framework.TestCase; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; - -/** - * Test case which demonstrates that ProxyLookup does not fire - * an event when it should. - */ -public class ProxyLookupEventIssue136866Test extends TestCase { - - public ProxyLookupEventIssue136866Test(String testName) { - super(testName); - } - - public void testAbstractLookupFiresEventWhenContentChanged() { - InstanceContent ic = new InstanceContent(); - AbstractLookup al = new AbstractLookup(ic); - - final int[] counts = {0}; // Number of items observed upon a LookupEvent - final Lookup.Result result = al.lookupResult(String.class); - - result.addLookupListener(new LookupListener() { - public void resultChanged(LookupEvent ev) { - // this gets called as expected - assertSame(result, ev.getSource()); - counts[0] = result.allInstances().size(); - } - }); - - ic.add("hello1"); - assertEquals(1, counts[0]); - } - - public void testProxyLookupFailsToFireEventWhenProxiedLookupChanged() { - InstanceContent ic = new InstanceContent(); -// AbstractLookup al = new AbstractLookup(ic); - Lookup proxy = new AbstractLookup(ic); - - final int[] counts = {0}; // Number of items observed upon a LookupEvent - final Lookup.Result result = proxy.lookupResult(String.class); - - result.addLookupListener(new LookupListener() { - public void resultChanged(LookupEvent ev) { - // this should be called but never is - assertSame(result, ev.getSource()); - counts[0] = result.allInstances().size(); - } - }); - - ic.add("hello1"); - assertEquals(1, counts[0]); - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/ProxyLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/ProxyLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,655 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.io.Serializable; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.*; -import java.util.concurrent.Executor; -import junit.framework.*; -import org.netbeans.junit.*; -import org.netbeans.modules.openide.util.ActiveQueue; -import org.openide.util.Lookup; -import org.openide.util.Lookup.Result; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; - -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional. - */ -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them -public class ProxyLookupTest extends AbstractLookupBaseHid -implements AbstractLookupBaseHid.Impl { - public ProxyLookupTest(java.lang.String testName) { - super(testName, null); - } - - public static Test suite() { - return new NbTestSuite (ProxyLookupTest.class); -// return new ProxyLookupTest("testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679"); - } - - /** Creates an lookup for given lookup. This class just returns - * the object passed in, but subclasses can be different. - * @param lookup in lookup - * @return a lookup to use - */ - public Lookup createLookup (Lookup lookup) { - return new ProxyLookup (new Lookup[] { lookup }); - } - - public Lookup createInstancesLookup (InstanceContent ic) { - return new AbstractLookup (ic); - } - - - public void clearCaches () { - } - - - /** Check whether setLookups method does not fire when there is no - * change in the lookups. - */ - public void testProxyListener () { - ProxyLookup lookup = new ProxyLookup (new Lookup[0]); - - final Lookup.Template template = new Lookup.Template(Object.class); - final Object[] IGNORE = { - ProxyLookup.ImmutableInternalData.EMPTY, - ProxyLookup.ImmutableInternalData.EMPTY_ARR, - ActiveQueue.queue(), - Collections.emptyMap(), - Collections.emptyList(), - Collections.emptySet() - }; - - assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE); - - Lookup.Result res = lookup.lookup (template); - - assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE); - - LL ll = new LL (); - res.addLookupListener (ll); - Collection allRes = res.allInstances (); - - lookup.setLookups (new Lookup[0]); - - if (ll.getCount () != 0) { - fail ("Calling setLookups (emptyarray) fired a change"); - } - - InstanceContent t = new InstanceContent(); - Lookup del = new AbstractLookup (t); - t.add("Ahoj"); - lookup.setLookups (new Lookup[] { del }); - - if (ll.getCount () != 1) { - fail ("Changing lookups did not generate an event"); - } - - lookup.setLookups (new Lookup[] { del }); - - if (ll.getCount () != 0) { - fail ("Calling setLookups (thesamearray) fired a change"); - } - } - - public void testNoListenersProxyListener () { - ProxyLookup lookup = new ProxyLookup (new Lookup[0]); - class E implements Executor { - Runnable r; - public void execute(Runnable command) { - assertNull("NO previous", r); - r = command; - } - public void perform() { - assertNotNull("We shall have a runnable", r); - r.run(); - r = null; - } - } - E executor = new E(); - - - final Lookup.Template template = new Lookup.Template(Object.class); - final Object[] IGNORE = { - ProxyLookup.ImmutableInternalData.EMPTY, - ProxyLookup.ImmutableInternalData.EMPTY_ARR, - ActiveQueue.queue(), - Collections.emptyMap(), - Collections.emptyList(), - Collections.emptySet() - }; - - assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE); - - Lookup.Result res = lookup.lookup (template); - - assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE); - - LL ll = new LL (); - res.addLookupListener (ll); - Collection allRes = res.allInstances (); - - lookup.setLookups (executor, new Lookup[0]); - if (ll.getCount () != 0) { - fail ("Calling setLookups (emptyarray) fired a change"); - } - - InstanceContent t = new InstanceContent(); - Lookup del = new AbstractLookup (t); - t.add("Ahoj"); - lookup.setLookups (executor, new Lookup[] { del }); - assertEquals("No change yet", 0, ll.getCount()); - executor.perform(); - if (ll.getCount () != 1) { - fail ("Changing lookups did not generate an event"); - } - - lookup.setLookups (executor, new Lookup[] { del }); - if (ll.getCount () != 0) { - fail ("Calling setLookups (thesamearray) fired a change"); - } - } - - public void testSetLookups () throws Exception { - AbstractLookup a1 = new AbstractLookup (new InstanceContent ()); - AbstractLookup a2 = new AbstractLookup (new InstanceContent ()); - - InstanceContent i3 = new InstanceContent (); - i3.add (i3); - AbstractLookup a3 = new AbstractLookup (i3); - - final ProxyLookup p = new ProxyLookup (new Lookup[] { a1, a2 }); - final Lookup.Result res1 = p.lookup (new Lookup.Template (Object.class)); - Collection c1 = res1.allInstances(); - - Lookup.Result res2 = p.lookup (new Lookup.Template (String.class)); - Collection c2 = res2.allInstances (); - - - assertTrue ("We need two results", res1 != res2); - - final Object blocked = new Object (); - - class L extends Object implements LookupListener { - public void resultChanged (LookupEvent ev) { - try { - res1.removeLookupListener(this); - - // waiting for second thread to start #111# - blocked.wait (); - - } catch (Exception ex) { - ex.printStackTrace(); - fail ("An exception occured "); - } - } - } - - final L listener1 = new L (); - res1.addLookupListener (listener1); - - - Runnable newLookupSetter = new Runnable() { - public void run () { - synchronized (blocked) { - try { - p.setLookups (new Lookup[0]); - } catch (Exception ex) { - ex.printStackTrace(); - fail ("setLookups failed."); - } finally { - // starts the main thread #111# - blocked.notify (); - } - } - } - }; - - synchronized (blocked) { - new Thread (newLookupSetter).start (); - - p.setLookups (new Lookup[] { a1, a2, a3 }); - } - } - - public void testProxyLookupTemplateCaching(){ - Lookup lookups[] = new Lookup[1]; - doProxyLookupTemplateCaching(lookups, false); - } - - public void testProxyLookupTemplateCachingOnSizeTwoArray() { - Lookup lookups[] = new Lookup[2]; - lookups[1] = Lookup.EMPTY; - doProxyLookupTemplateCaching(lookups, false); - } - public void testProxyLookupShallNotAllowModificationOfGetLookups(){ - Lookup lookups[] = new Lookup[1]; - doProxyLookupTemplateCaching(lookups, true); - } - - public void testProxyLookupShallNotAllowModificationOfGetLookupsOnSizeTwoArray() { - Lookup lookups[] = new Lookup[2]; - lookups[1] = Lookup.EMPTY; - doProxyLookupTemplateCaching(lookups, true); - } - - /** Index 0 of lookups will be modified, the rest is up to the - * setup code. - */ - private void doProxyLookupTemplateCaching(Lookup[] lookups, boolean reget) { - // Create MyProxyLookup with one lookup containing the String object - InstanceContent inst = new InstanceContent(); - inst.add(new String("Hello World")); //NOI18N - lookups[0] = new AbstractLookup(inst); - ProxyLookup proxy = new ProxyLookup(lookups); - if (reget) { - lookups = proxy.getLookups(); - } - - // Performing template lookup for String object - Lookup.Result result = proxy.lookup(new Lookup.Template(String.class, null, null)); - int stringTemplateResultSize = result.allInstances().size(); - assertEquals ("Ensure, there is only one instance of String.class in proxyLookup:", //NOI18N - 1, stringTemplateResultSize); - - // Changing lookup in proxy lookup, now it will contain - // StringBuffer Object instead of String - InstanceContent ic2 = new InstanceContent(); - ic2.add(new Integer(1234567890)); - lookups[0] = new AbstractLookup(ic2); - proxy.setLookups(lookups); - - assertEquals ("the old result is updated", 0, result.allInstances().size()); - - // Instance of String.class should not appear in proxyLookup - Lookup.Result r2 = proxy.lookup(new Lookup.Template(String.class, null, null)); - assertEquals ("Instance of String.class should not appear in proxyLookup:", //NOI18N - 0, r2.allInstances().size()); - - Lookup.Result r3 = proxy.lookup(new Lookup.Template(Integer.class, null, null)); - assertEquals ("There is only one instance of Integer.class in proxyLookup:", //NOI18N - 1, r3.allInstances().size()); - } - - public void testListeningAndQueryingByTwoListenersInstancesSetLookups() { - doListeningAndQueryingByTwoListenersSetLookups(0, 1); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups() { - doListeningAndQueryingByTwoListenersSetLookups(1, 1); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups() { - doListeningAndQueryingByTwoListenersSetLookups(2, 1); - } - - public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() { - doListeningAndQueryingByTwoListenersSetLookups(0, 2); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups2() { - doListeningAndQueryingByTwoListenersSetLookups(1, 2); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups2() { - doListeningAndQueryingByTwoListenersSetLookups(2, 2); - } - public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() { - doListeningAndQueryingByTwoListenersSetLookups(0, 22); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups22() { - doListeningAndQueryingByTwoListenersSetLookups(1, 22); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups22() { - doListeningAndQueryingByTwoListenersSetLookups(2, 22); - } - - private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth) { - ProxyLookup orig = new ProxyLookup(); - ProxyLookup on = orig; - - while (--depth > 0) { - on = new ProxyLookup(new Lookup[] { on }); - } - - - final ProxyLookup lookup = on; - - class L implements LookupListener { - Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class)); - Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class)); - Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class)); - - { - integer.addLookupListener(this); - number.addLookupListener(this); - serial.addLookupListener(this); - } - - int round; - - public void resultChanged(LookupEvent ev) { - Collection c1 = get(type, integer); - Collection c2 = get(type, number); - Collection c3 = get(type, serial); - - assertEquals("round " + round + " c1 vs. c2", c1, c2); - assertEquals("round " + round + " c1 vs. c3", c1, c3); - assertEquals("round " + round + " c2 vs. c3", c2, c3); - - round++; - } - - private Collection get(int type, Lookup.Result res) { - Collection c; - switch(type) { - case 0: c = res.allInstances(); break; - case 1: c = res.allClasses(); break; - case 2: c = res.allItems(); break; - default: c = null; fail("Type: " + type); break; - } - - assertNotNull(c); - return new ArrayList(c); - } - } - - L listener = new L(); - listener.resultChanged(null); - ArrayList arr = new ArrayList(); - for(int i = 0; i < 100; i++) { - arr.add(new Integer(i)); - - orig.setLookups(new Lookup[] { Lookups.fixed(arr.toArray()) }); - } - - assertEquals("3x100+1 checks", 301, listener.round); - } - - static Object holder; - - public void testProxyWithLiveResultCanBeCollected() { - Lookup layer0 = Lookups.singleton("Hello"); - Lookup layer1 = new ProxyLookup(new Lookup[] { layer0 }); - Lookup layer2 = new ProxyLookup(new Lookup[] { layer1 }); - Lookup.Result result1 = layer1.lookup(new Lookup.Template(String.class)); - - assertEquals("One instance", 1, result1.allInstances().size()); - - // this will create ProxyLookup$R which listens on origResult - Lookup.Result result2 = layer2.lookup(new Lookup.Template(String.class)); - - // this line is necessary. W/o actually querying the result, - // it will nether compute it nor attach the listener. - assertEquals("One instance", 1, result2.allInstances().size()); - - result2.addLookupListener(new LookupListener() { - public void resultChanged(LookupEvent ev) {} - }); - - Reference ref = new WeakReference(layer2); - layer2 = null; - result2 = null; - try { - holder = result1; - assertGC ("The proxy lookup not been garbage collected!", ref); - } finally { - holder = null; - } - } - - public void testArrayIndexAsInIssue119292() throws Exception { - final ProxyLookup pl = new ProxyLookup(); - final int[] cnt = { 0 }; - - class L extends Lookup { - L[] set; - Lookup l; - - public L(String s) { - l = Lookups.singleton(s); - } - - @Override - public T lookup(Class clazz) { - return l.lookup(clazz); - } - - @Override - public Result lookup(Template template) { - return l.lookup(template); - } - - @Override - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - public boolean equals(Object obj) { - if (set != null) { - cnt[0]++; - pl.setLookups(set); - } - return super.equals(obj); - } - - @Override - public int hashCode() { - int hash = 3; - return hash; - } - } - - Result res = pl.lookupResult(String.class); - assertEquals(Collections.EMPTY_LIST, res.allItems()); - - L[] old = { new L("A"), new L("B") }; - L[] now = { new L("C") }; - - pl.setLookups(old); - cnt[0] = 0; - - old[0].set = new L[0]; - pl.setLookups(now); - - assertEquals("No call to equals", 0, cnt[0]); - - assertEquals("Still assigned to C", Collections.singletonList("C"), res.allInstances()); - } - - public void testArrayIndexWithAddRemoveListenerAsInIssue119292() throws Exception { - final ProxyLookup pl = new ProxyLookup(); - final int[] cnt = { 0 }; - - class L extends Lookup { - L[] set; - Lookup l; - - public L(String s) { - l = Lookups.singleton(s); - } - - @Override - public T lookup(Class clazz) { - return l.lookup(clazz); - } - - @Override - public Result lookup(Template template) { - Result r = l.lookup(template); - return new R(r); - } - - final class R extends Result { - private Result delegate; - - public R(Result delegate) { - this.delegate = delegate; - } - - @Override - public void addLookupListener(LookupListener l) { - cnt[0]++; - if (set != null) { - pl.setLookups(set); - } - delegate.addLookupListener(l); - } - - @Override - public void removeLookupListener(LookupListener l) { - cnt[0]++; - if (set != null) { - pl.setLookups(set); - } - delegate.removeLookupListener(l); - } - - @Override - public Collection allInstances() { - return delegate.allInstances(); - } - } - } - - Result res = pl.lookupResult(String.class); - assertEquals(Collections.EMPTY_LIST, res.allItems()); - - L[] old = { new L("A"), new L("B") }; - L[] now = { new L("C") }; - - pl.setLookups(old); - cnt[0] = 0; - - old[0].set = new L[0]; - pl.setLookups(now); - - if (cnt[0] == 0) { - fail("There should be calls to listeners"); - } - - assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances()); - } - - - public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception { - final ProxyLookup pl = new ProxyLookup(); - final int[] cnt = { 0 }; - - class L extends Lookup { - L[] set; - Lookup l; - Collection res; - - public L(String s) { - l = Lookups.singleton(s); - } - - @Override - public T lookup(Class clazz) { - return l.lookup(clazz); - } - - @Override - public Result lookup(Template template) { - cnt[0]++; - if (set != null) { - pl.setLookups(set); - res = pl.lookupAll(Serializable.class); - } - Result r = l.lookup(template); - return r; - } - } - - L[] now = { new L("A"), new L("B") }; - L[] old = { new L("C") }; - pl.setLookups(old); - old[0].set = now; - - Result res = pl.lookupResult(String.class); - assertEquals("New items visible", 2, res.allItems().size()); - - - pl.setLookups(new L("X"), new L("Y"), new L("Z")); - } - - public void testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679() throws Exception { - final ProxyLookup pl = new ProxyLookup(); - final int[] cnt = { 0 }; - - class L extends Lookup { - L[] set; - Lookup l; - Collection res; - - public L(String s) { - l = Lookups.singleton(s); - } - - @Override - public T lookup(Class clazz) { - return l.lookup(clazz); - } - - @Override - public Result lookup(Template template) { - cnt[0]++; - if (set != null) { - pl.setLookups(set); - res = pl.lookupAll(Serializable.class); - } - Result r = l.lookup(template); - return r; - } - } - - L dupl = new L("A"); - L[] now = { dupl }; - L[] old = { new L("C") }; - pl.setLookups(old); - old[0].set = now; - - Result res = pl.lookupResult(String.class); - assertEquals("New items visible", 1, res.allItems().size()); - - - pl.setLookups(old); - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/SimpleLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/SimpleLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,351 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import org.netbeans.junit.NbTestCase; -import org.openide.util.Lookup; - -/** - * Tests for class SimpleLookup. - * @author David Strupl - */ -public class SimpleLookupTest extends NbTestCase { - - public SimpleLookupTest(String testName) { - super(testName); - } - - public void testEmptyLookup() { - assertSize("Lookup.EMPTY should be small", 8, Lookup.EMPTY); - } - - /** - * Simple tests testing singleton lookup. - */ - public void testSingleton() { - // - Object orig = new Object(); - Lookup p1 = Lookups.singleton(orig); - Object obj = p1.lookup(Object.class); - assertTrue(obj == orig); - assertNull(p1.lookup(String.class)); - assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same? - // - Lookup p2 = Lookups.singleton("test"); - assertNotNull(p2.lookup(Object.class)); - assertNotNull(p2.lookup(String.class)); - assertNotNull(p2.lookup(java.io.Serializable.class)); - } - - public void testEmptyFixed() { - Lookup l = Lookups.fixed(); - assertSize("Lookups.fixed() for empty list of items should be small", 8, l); - assertSame(Lookup.EMPTY, l); - } - - public void testSingleItemFixed() { - Object o = new Object(); - Lookup l = Lookups.fixed(o); - assertSize("Lookups.fixed(o) for a single item should be small", 24, l); - } - - /** - * Simple tests testing fixed lookup. - */ - public void testFixed() { - // - Object[] orig = new Object[] { new Object(), new Object() }; - Lookup p1 = Lookups.fixed(orig); - Object obj = p1.lookup(Object.class); - assertTrue(obj == orig[0] || obj == orig[1]); - assertNull(p1.lookup(String.class)); - // - String[] s = new String[] { "test1", "test2" }; - Lookup p2 = Lookups.fixed((Object[]) s); - Object obj2 = p2.lookup(Object.class); - assertNotNull(obj2); - if (obj2 != s[0] && obj2 != s[1]) { - fail("Returned objects are not the originals"); - } - assertNotNull(p2.lookup(String.class)); - assertNotNull(p2.lookup(java.io.Serializable.class)); - Lookup.Template t = new Lookup.Template(String.class); - Lookup.Result r = p2.lookup(t); - Collection all = r.allInstances(); - assertTrue(all.size() == 2); - for (String o : all) { - assertTrue("allInstances contains wrong objects", o.equals(s[0]) || o.equals(s[1])); - } - - try { - Lookups.fixed(new Object[] {null}); - fail("No nulls are allowed"); - } catch (NullPointerException ex) { - // ok, NPE is what we want - } - } - - public void testFixedSubtypes() { - class A {} - class B extends A {} - Lookup l = Lookups.fixed(new A(), new B()); - assertEquals(1, l.lookupAll(B.class).size()); - assertEquals(2, l.lookupAll(A.class).size()); - } - - /** - * Simple tests testing converting lookup. - */ - public void testConverting() { - // - String[] orig = new String[] { TestConvertor.TEST1, TestConvertor.TEST2 }; - TestConvertor convertor = new TestConvertor(); - Lookup p1 = Lookups.fixed(orig, convertor); - assertNull("Converting from String to Integer - it should not find String in result", p1.lookup(String.class)); - assertNotNull(p1.lookup(Integer.class)); - assertNotNull(p1.lookup(Integer.class)); - assertTrue("Convertor should be called only once.", convertor.getNumberOfConvertCalls() == 1); - Lookup.Template t = new Lookup.Template(Integer.class); - Lookup.Result r = p1.lookup(t); - Collection all = r.allInstances(); - assertTrue(all.size() == 2); - for (int i : all) { - assertTrue("allInstances contains wrong objects", i == TestConvertor.t1 || i == TestConvertor.t2); - } - } - - private static class TestConvertor implements InstanceContent.Convertor { - static final String TEST1 = "test1"; - static final int t1 = 1; - static final String TEST2 = "test2"; - static final int t2 = 2; - - private int numberOfConvertCalls = 0; - - public Integer convert(String obj) { - numberOfConvertCalls++; - if (obj.equals(TEST1)) { - return t1; - } - if (obj.equals(TEST2)) { - return t2; - } - throw new IllegalArgumentException(); - } - - public String displayName(String obj) { - return obj; - } - - public String id(String obj) { - if (obj.equals(TEST1)) { - return TEST1; - } - if (obj.equals(TEST2)) { - return TEST2; - } - return null; - } - - public Class type(String obj) { - return Integer.class; - } - - int getNumberOfConvertCalls() { - return numberOfConvertCalls; - } - } - - public void testLookupItem() { - SomeInst inst = new SomeInst(); - Lookup.Item item = Lookups.lookupItem(inst, "XYZ"); - - assertTrue("Wrong instance", item.getInstance() == inst); - assertTrue("Wrong instance class", item.getType() == inst.getClass()); - assertEquals("Wrong id", "XYZ", item.getId()); - - item = Lookups.lookupItem(inst, null); - assertNotNull("Id must never be null", item.getId()); - } - - public void testLookupItemEquals() { - SomeInst instA = new SomeInst(); - SomeInst instB = new SomeInst(); - Lookup.Item itemA = Lookups.lookupItem(instA, null); - Lookup.Item itemB = Lookups.lookupItem(instB, null); - - assertTrue("Lookup items shouldn't be equal", !itemA.equals(itemB) && !itemB.equals(itemA)); - - itemA = Lookups.lookupItem(instA, null); - itemB = Lookups.lookupItem(instA, null); // same instance - - assertTrue("Lookup items should be equal", itemA.equals(itemB) && itemB.equals(itemA)); - assertTrue("Lookup items hashcode should be same", itemA.hashCode() == itemB.hashCode()); - - itemA = Lookups.lookupItem(new String("VOKURKA"), null); - itemB = Lookups.lookupItem(new String("VOKURKA"), null); - - assertTrue("Lookup items shouldn't be equal (2)", !itemA.equals(itemB) && !itemB.equals(itemA)); - } - - public void testAllClassesIssue42399 () throws Exception { - Object[] arr = { "Ahoj", new Object () }; - - Lookup l = Lookups.fixed (arr); - - Set> s = l.lookup(new Lookup.Template(Object.class)).allClasses(); - - assertEquals ("Two there", 2, s.size ()); - assertTrue ("Contains Object.class", s.contains (Object.class)); - assertTrue ("Contains string", s.contains (String.class)); - - } - - public void testLookupItemEarlyInitializationProblem() { - InstanceContent ic = new InstanceContent(); - AbstractLookup al = new AbstractLookup(ic); - LI item = new LI(); - List pairs1 = new ArrayList(); - List pairs2 = new ArrayList(); - - assertEquals("Item's instance shouldn't be requested", 0, item.cnt); - - pairs1.add(new ItemPair(Lookups.lookupItem(new SomeInst(), null))); - pairs1.add(new ItemPair(item)); - pairs1.add(new ItemPair(Lookups.lookupItem(new Object(), null))); - - pairs2.add(new ItemPair(item)); - pairs2.add(new ItemPair(Lookups.lookupItem(new Object(), null))); - - ic.setPairs(pairs1); - ic.setPairs(pairs2); - - assertEquals("Item's instance shouldn't be requested when added to lookup", 0, item.cnt); - - LI item2 = al.lookup(LI.class); - assertEquals("Item's instance should be requested", 1, item.cnt); - } - - public void testConvenienceMethods() throws Exception { - // Just check signatures and basic behavior of #73848. - Lookup l = Lookups.fixed(new Object[] {1, "hello", 2, "goodbye"}); - Collection ints = l.lookupAll(Integer.class); - assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList(ints)); - Lookup.Result r = l.lookupResult(Integer.class); - ints = r.allInstances(); - assertEquals(Arrays.asList(new Integer[] {1, 2}), new ArrayList(ints)); - } - - private static class SomeInst { } - - private static class LI extends Lookup.Item { - - public long cnt = 0; - - public String getDisplayName() { - return getId(); - } - - public String getId() { - return getClass() + "@" + hashCode(); - } - - public Object getInstance() { - cnt++; - return this; - } - - public Class getType() { - return getClass(); - } - } // End of LI class - - private static class ItemPair extends AbstractLookup.Pair { - - private AbstractLookup.Item item; - - public ItemPair(Lookup.Item i) { - this.item = i; - } - - protected boolean creatorOf(Object obj) { - return item.getInstance() == obj; - } - - public String getDisplayName() { - return item.getDisplayName (); - } - - public String getId() { - return item.getId (); - } - - public T getInstance() { - return item.getInstance (); - } - - public Class getType() { - return item.getType (); - } - - protected boolean instanceOf(Class c) { - return c.isAssignableFrom(getType()); - } - - public @Override boolean equals(Object o) { - if (o instanceof ItemPair) { - ItemPair p = (ItemPair)o; - return item.equals (p.item); - } - return false; - } - - public @Override int hashCode() { - return item.hashCode (); - } - } // end of ItemPair -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/SimpleProxyLookupIssue42244Test.java --- a/lookup/src/test/java/org/openide/util/lookup/SimpleProxyLookupIssue42244Test.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.lang.ref.WeakReference; -import java.util.*; -import junit.framework.*; -import org.netbeans.junit.*; -import org.openide.util.Lookup; - -/** To simulate issue 42244. - */ -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them -public class SimpleProxyLookupIssue42244Test extends AbstractLookupBaseHid implements AbstractLookupBaseHid.Impl { - public SimpleProxyLookupIssue42244Test (java.lang.String testName) { - super(testName, null); - } - - public static Test suite() { - // return new SimpleProxyLookupIssue42244Test("testGarbageCollect"); - return new NbTestSuite(SimpleProxyLookupIssue42244Test.class); - } - - /** Creates an lookup for given lookup. This class just returns - * the object passed in, but subclasses can be different. - * @param lookup in lookup - * @return a lookup to use - */ - public Lookup createLookup (final Lookup lookup) { - class C implements Lookup.Provider { - public Lookup getLookup () { - return lookup; - } - } - return Lookups.proxy (new C ()); - } - - public Lookup createInstancesLookup (InstanceContent ic) { - return new KeepResultsProxyLookup (new AbstractLookup (ic)); - } - - public void clearCaches () { - KeepResultsProxyLookup k = (KeepResultsProxyLookup)this.instanceLookup; - - ArrayList toGC = new ArrayList (); - Iterator it = k.allQueries.iterator (); - while (it.hasNext ()) { - Lookup.Result r = (Lookup.Result)it.next (); - toGC.add (new WeakReference (r)); - } - - k.allQueries = null; - - it = toGC.iterator (); - while (it.hasNext ()) { - WeakReference r = (WeakReference)it.next (); - assertGC ("Trying to release all results from memory", r); - } - } - - class KeepResultsProxyLookup extends ProxyLookup { - private ArrayList allQueries = new ArrayList (); - private ThreadLocal in = new ThreadLocal (); - - public KeepResultsProxyLookup (Lookup delegate) { - super (new Lookup[] { delegate }); - } - - @Override - protected void beforeLookup (org.openide.util.Lookup.Template template) { - super.beforeLookup (template); - if (allQueries != null && in.get () == null) { - in.set (this); - Lookup.Result res = lookup (template); - allQueries.add (res); - in.set (null); - } - } - - } -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/SimpleProxyLookupSpeedIssue42244Test.java --- a/lookup/src/test/java/org/openide/util/lookup/SimpleProxyLookupSpeedIssue42244Test.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.HashSet; -import java.util.Set; -import org.netbeans.junit.NbTestCase; - -import org.netbeans.junit.RandomlyFails; -import org.openide.util.Lookup; - -/** - * @author Petr Nejedly, adapted to test by Jaroslav Tulach - */ -@RandomlyFails // NB-Core-Build #1847 -public class SimpleProxyLookupSpeedIssue42244Test extends NbTestCase { - - public SimpleProxyLookupSpeedIssue42244Test (String name) { - super (name); - } - - public void testCompareTheSpeed () { - String content1 = "String1"; - String content2 = "String2"; - - Lookup fixed1 = Lookups.singleton(content1); - Lookup fixed2 = Lookups.singleton(content2); - - MyProvider provider = new MyProvider(); - provider.setLookup(fixed1); - - Lookup top = Lookups.proxy(provider); - - Lookup.Result r0 = top.lookupResult(String.class); - r0.allInstances(); - - long time = System.currentTimeMillis(); - top.lookupAll(String.class); - long withOneResult = System.currentTimeMillis() - time; - - - Set results = new HashSet(); - for (int i=0; i<10000; i++) { - Lookup.Result res = top.lookupResult(String.class); - results.add (res); - res.allInstances(); - } - - provider.setLookup(fixed2); - - time = System.currentTimeMillis(); - top.lookupAll(String.class); - long withManyResults = System.currentTimeMillis() - time; - - // if the measurement takes less then 10ms, pretend 10ms - if (withManyResults < 10) { - withManyResults = 10; - } - if (withOneResult < 10) { - withOneResult = 10; - } - - if (withManyResults >= 10 * withOneResult) { - fail ("With many results the test runs too long.\n With many: " + withManyResults + "\n With one : " + withOneResult); - } - } - - private static class MyProvider implements Lookup.Provider { - private Lookup lookup; - public Lookup getLookup() { - return lookup; - } - - void setLookup(Lookup lookup) { - this.lookup = lookup; - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/SimpleProxyLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/SimpleProxyLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.lang.ref.WeakReference; -import org.netbeans.junit.NbTestCase; -import org.openide.util.Lookup; -import org.openide.util.Lookup.Provider; - -/** - * - * @author Jan Lahoda - */ -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them -public class SimpleProxyLookupTest extends NbTestCase { - - public SimpleProxyLookupTest(String testName) { - super(testName); - } - - public void test69810() throws Exception { - Lookup.Template t = new Lookup.Template(String.class); - SimpleProxyLookup spl = new SimpleProxyLookup(new Provider() { - public Lookup getLookup() { - return Lookups.fixed(new Object[] {"test1", "test2"}); - } - }); - - assertGC("", new WeakReference(spl.lookup(t))); - - spl.lookup(new Lookup.Template(Object.class)).allInstances(); - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/lookup/SingletonLookupTest.java --- a/lookup/src/test/java/org/openide/util/lookup/SingletonLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2008 Sun Microsystems, Inc. - */ - -package org.openide.util.lookup; - -import java.util.Collection; -import org.netbeans.junit.NbTestCase; -import org.openide.util.Lookup; - -/** - * Contains tests of class {@code SingletonLookup}. - * - * @author Marian Petras - */ -public class SingletonLookupTest extends NbTestCase { - - public SingletonLookupTest(String testName) { - super(testName); - } - - public void testBasics() { - Object orig = new Object(); - Lookup p1 = new SingletonLookup(orig); - Object obj = p1.lookup(Object.class); - assertTrue(obj == orig); - assertNull(p1.lookup(String.class)); - assertTrue(orig == p1.lookup(Object.class)); // 2nd time, still the same? - // - Lookup p2 = new SingletonLookup("test"); - assertNotNull(p2.lookup(Object.class)); - assertNotNull(p2.lookup(String.class)); - assertNotNull(p2.lookup(java.io.Serializable.class)); - } - - public void testId() { - Object orig = new Object(); - Collection allInstances; - - Lookup l = new SingletonLookup(orig, "id"); - - allInstances = l.lookup(new Lookup.Template(Object.class, null, null)).allInstances(); - assertNotNull(allInstances); - assertFalse(allInstances.isEmpty()); - assertEquals(1, allInstances.size()); - assertTrue(allInstances.iterator().next() == orig); - - allInstances = l.lookup(new Lookup.Template(Object.class, "id", null)).allInstances(); - assertNotNull(allInstances); - assertFalse(allInstances.isEmpty()); - assertEquals(1, allInstances.size()); - assertTrue(allInstances.iterator().next() == orig); - - allInstances = l.lookup(new Lookup.Template(Object.class, "not", null)).allInstances(); - assertNotNull(allInstances); - assertTrue(allInstances.isEmpty()); - - allInstances = l.lookup(new Lookup.Template(String.class, null, null)).allInstances(); - assertNotNull(allInstances); - assertTrue(allInstances.isEmpty()); - - allInstances = l.lookup(new Lookup.Template(String.class, "id", null)).allInstances(); - assertNotNull(allInstances); - assertTrue(allInstances.isEmpty()); - - allInstances = l.lookup(new Lookup.Template(String.class, "not", null)).allInstances(); - assertNotNull(allInstances); - assertTrue(allInstances.isEmpty()); - } - - public void testSize() { - final Object obj = new Object(); - assertSize("The singleton lookup instance should be small", - 24, - new SingletonLookup(obj)); - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/test/AnnotationProcessorTestUtils.java --- a/lookup/src/test/java/org/openide/util/test/AnnotationProcessorTestUtils.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2008 Sun Microsystems, Inc. - */ - -package org.openide.util.test; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; -import javax.tools.JavaCompiler; -import javax.tools.ToolProvider; -import junit.framework.Assert; - -/** - * Utilities useful to those testing JSR 269 annotation processors. - *

If you just want to test that the output of the processor is correct, - * you do not need to do anything special: - * just use the annotation on some sample classes nested inside your unit test. - * They will be processed, and you check that your SPI loads them correctly. - * These utilities are useful mainly in case you want to check that the processor - * rejects erroneous sources, and that any messages it prints are reasonable; - * that it behaves correctly on incremental compilations; etc. - */ -public class AnnotationProcessorTestUtils { - - private AnnotationProcessorTestUtils() {} - - /** - * Create a source file. - * @param dir source root - * @param clazz a fully-qualified class name - * @param content lines of text (skip package decl) - */ - public static void makeSource(File dir, String clazz, String... content) throws IOException { - File f = new File(dir, clazz.replace('.', File.separatorChar) + ".java"); - f.getParentFile().mkdirs(); - Writer w = new FileWriter(f); - try { - PrintWriter pw = new PrintWriter(w); - String pkg = clazz.replaceFirst("\\.[^.]+$", ""); - if (!pkg.equals(clazz)) { - pw.println("package " + pkg + ";"); - } - for (String line : content) { - pw.println(line); - } - pw.flush(); - } finally { - w.close(); - } - } - - /** - * Run the Java compiler. - * (A JSR 199 implementation must be available.) - * @param src a source root (runs javac on all *.java it finds matching {@code srcIncludes}) - * @param srcIncludes a pattern of source files names without path to compile (useful for testing incremental compiles), or null for all - * @param dest a dest dir to compile classes to - * @param cp classpath entries; if null, use Java classpath of test - * @param stderr output stream to print messages to, or null for test console (i.e. do not capture) - * @return true if compilation succeeded, false if it failed - */ - public static boolean runJavac(File src, String srcIncludes, File dest, File[] cp, OutputStream stderr) { - List args = new ArrayList(); - args.add("-classpath"); - if (cp != null) { - StringBuffer b = new StringBuffer(); - for (File entry : cp) { - b.append(File.pathSeparatorChar); - b.append(entry.getAbsolutePath()); - } - args.add(b.toString()); - } else { - args.add(System.getProperty("java.class.path")); - } - args.add("-d"); - args.add(dest.getAbsolutePath()); - args.add("-sourcepath"); - args.add(src.getAbsolutePath()); - dest.mkdirs(); - scan(args, src, srcIncludes); - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - Assert.assertNotNull("no JSR 199 compiler impl found; try e.g.: " + - "test.unit.run.cp.extra=${nb_all}/apisupport.harness/external/openjdk-javac-6-b12.jar", compiler); - //System.err.println("running javac with args: " + args); - return compiler.run(null, null, stderr, args.toArray(new String[args.size()])) == 0; - } - private static void scan(List names, File f, String includes) { - if (f.isDirectory()) { - for (File kid : f.listFiles()) { - scan(names, kid, includes); - } - } else if (f.getName().endsWith(".java") && (includes == null || Pattern.compile(includes).matcher(f.getName()).find())) { - names.add(f.getAbsolutePath()); - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/test/MockLookup.java --- a/lookup/src/test/java/org/openide/util/test/MockLookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.test; - -import java.lang.reflect.Field; -import java.util.Collection; -import static junit.framework.Assert.*; -import org.openide.util.Lookup; -import org.openide.util.lookup.Lookups; -import org.openide.util.lookup.ProxyLookup; - -/** - * Mock implementation of system default lookup suitable for use in unit tests. - * The initial value just contains classpath services. - */ -public class MockLookup extends ProxyLookup { - - private static MockLookup DEFAULT; - private static boolean making = false; - private static volatile boolean ready; - - static { - making = true; - try { - System.setProperty("org.openide.util.Lookup", MockLookup.class.getName()); - if (Lookup.getDefault().getClass() != MockLookup.class) { - // Someone else initialized lookup first. Try to force our way. - Field defaultLookup = Lookup.class.getDeclaredField("defaultLookup"); - defaultLookup.setAccessible(true); - defaultLookup.set(null, null); - } - assertEquals(MockLookup.class, Lookup.getDefault().getClass()); - } catch (Exception x) { - throw new ExceptionInInitializerError(x); - } finally { - making = false; - } - } - - /** Do not call this directly! */ - public MockLookup() { - assertTrue(making); - assertNull(DEFAULT); - DEFAULT = this; - } - - /** - * Just ensures that this lookup is default lookup, but does not actually change its content. - * Useful mainly if you have some test utility method which calls foreign code which might use default lookup, - * and you want to ensure that any users of mock lookup will see the correct default lookup right away, - * even if they have not yet called {@link #setLookup} or {@link #setInstances}. - */ - public static void init() { - if (!ready) { - setInstances(); - } - } - - /** - * Sets the global default lookup with zero or more delegate lookups. - * Caution: if you don't include Lookups.metaInfServices, you may have trouble, - * e.g. {@link #makeScratchDir} will not work. - * Most of the time you should use {@link #setInstances} instead. - */ - public static void setLookup(Lookup... lookups) { - ready = true; - DEFAULT.setLookups(lookups); - } - - /** - * Sets the global default lookup with some fixed instances. - * Will also include (at a lower priority) a {@link ClassLoader}, - * and services found from META-INF/services/* in the classpath. - */ - public static void setInstances(Object... instances) { - ClassLoader l = MockLookup.class.getClassLoader(); - setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l)); - } - /** - * Sets the global default lookup with some fixed instances and - * content read from Services folder from system file system. - * Will also include (at a lower priority) a {@link ClassLoader}, - * and services found from META-INF/services/* in the classpath. - */ - public static void setLayersAndInstances(Object... instances) { - ClassLoader l = MockLookup.class.getClassLoader(); - if (l != Lookup.getDefault().lookup(ClassLoader.class)) { - setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l)); - } - Lookup projects = Lookups.forPath("Services"); - Collection initialize = projects.lookupAll(Object.class); - //System.err.println("all: " + initialize); - setLookup(Lookups.fixed(instances), Lookups.metaInfServices(l), Lookups.singleton(l), projects); - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/java/org/openide/util/test/MockLookupTest.java --- a/lookup/src/test/java/org/openide/util/test/MockLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.test; - -import junit.framework.TestCase; -import org.openide.util.Lookup; - -public class MockLookupTest extends TestCase { - - // XXX test: - // setLookup with one or more lookup args does not use M-I/s - // still works if another Lookup.getDefault was set before - - public MockLookupTest(String n) { - super(n); - } - - public void testSetLookup() throws Exception { - MockLookup.setInstances("hello"); - assertEquals("initial lookup works", "hello", Lookup.getDefault().lookup(String.class)); - MockLookup.setInstances("goodbye"); - assertEquals("modified lookup works", "goodbye", Lookup.getDefault().lookup(String.class)); - MockLookup.setInstances(); - assertEquals("cleared lookup works", null, Lookup.getDefault().lookup(String.class)); - } - -} diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/resources/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.txt --- a/lookup/src/test/resources/org/openide/util/lookup/MetaInfServicesLookupTestRunnable.txt Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -org.openide.util.lookup.MetaInfServicesLookupTestRunnable diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/resources/org/openide/util/lookup/problem100320.txt --- a/lookup/src/test/resources/org/openide/util/lookup/problem100320.txt Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -:java.io.IOException: -java.nio.charset.CharacterCodingException -java.io.EOFException -java.io.FileNotFoundException -java.io.InterruptedIOException -java.net.MalformedURLException -java.io.IOException -java.io.UnsupportedEncodingException -java.io.NotActiveException -java.io.StreamCorruptedException -java.io.UTFDataFormatException -java.util.zip.ZipException -java.util.jar.JarException -:java.util.Comparator: -org.bar.Comparator3 -org.bar.Comparator2 -#position=5 diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/resources/org/openide/util/lookup/services-jar-1.txt --- a/lookup/src/test/resources/org/openide/util/lookup/services-jar-1.txt Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -:somedummyfile: -org.foo.Interface -:java.lang.Runnable: -org.foo.impl.Runnable1 -:java.util.Comparator: -#some comment -org.foo.impl.Comparator1 -#position=10 -#som comment2 -:java.util.Iterator: -org.foo.impl.Iterator1 -:org.foo.Interface: -# Some header info, maybe. - -# Our first impl here -org.foo.impl.Implementation1 - diff -r b3ae88304dd0 -r a2947558c966 lookup/src/test/resources/org/openide/util/lookup/services-jar-2.txt --- a/lookup/src/test/resources/org/openide/util/lookup/services-jar-2.txt Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -:java.lang.Runnable: -#-org.foo.impl.Runnable1 -:java.util.Comparator: -org.bar.Comparator2 -#position=5 -:java.util.Iterator: -org.bar.Iterator2 -#position=100 -:org.foo.Interface: -org.bar.Implementation2 diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/apichanges.xml --- a/openide.util.lookup/apichanges.xml Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,495 +0,0 @@ - - - - - - Lookup API - - - - -

Introducing semihidden SPI - - - - - -

- Adding SPI interface package for those who implement - the NetBeans platform. This package is not shown in Javadoc - as it does not form a generally available public API. -

-
- - - - - Separate module for Lookup API - - - - -

- Runtime compatibility remains, compile time compatibility is - mostly preserved too. It is however recommended to upgrade - dependencies of your modules. Try running - ant fix-dependencies in your Ant module. -

-
- -

- Lookup - and its associated interfaces are now available as a - separate module. -

-
- - - - - -
- - - Added - org.openide.util.Lookup.paths property - - - - - - -

- Better way to integrate Lookup.getDefault() and system filesystem. -

-
- - -
- - - Added ServiceProvider annotation - - - - -

- Modules registering services using META-INF/services - files in the source tree are encouraged to switch to the annotation. -

-
- -

- Added annotations ServiceProvider and ServiceProviders - to simplify registration of global singleton services. -

-
- - - -
- - - AbstractLookup and ProxyLookup fire changes asynchronously - - - - - -

- All modification methods in AbstractLookup and ProxyLookup - were extended to accept an - Executor. - If not null, it is used to dispatch events to listeners sometime - "later". Also the AbstractLookup.Content - and InstanceContent constructors - have been extended to accept such Executors. -

-
- - - - -
- - - - Added simplified support for named lookups Lookups.forPath - - - - - -

- New method Lookups.forPath(String) - has been added to replace now deprecated FolderLookup - and allow modules who wants to read settings from layers - to do so with a simpler code, without dependency on DataSystems API. -

-
- - -
- - - - Convenience methods added to Lookup - - - - -

- Could conceivably conflict with existing subclass method with same signature - with different semantics or return type. -

-
- -

- Two methods, lookupResult and lookupAll, were - added to Lookup to encapsulate the most common usage patterns - with less typing, and more importantly avoiding the need to explicitly - make a Lookup.Template object. -

-
- - -
- - - Less change notifications from ProxyLookup - - - - - - ProxyLookup.setLookups - used to fire LookupEvent every - time it was called. Now it always checks whether there was a change to the - previous state. This will reduce the number of events delivered when a small - change is made. Also results from both - ProxyLookup - and AbstractLookup - were modified to return immutable Collections. - So do not try to modify them. It was always documented that the - results, are immutable and also it was never said that a change is - delivered when there is no change in the result, so this is considered - compatible change, even it is know that at least one piece of code - in NetBeans relied on this behaviour. - - - - - - - - - - -Lookups.exclude added to simplify writing of lookups that filter content of other lookups - - - - - -

New method that takes lookup and set of classes and return new lookup - which contains everything from the original one except instances of - the specified classes has been added. -

-
- - -
- - - Added ability to order items in META-INF/services/ lookup - - - - - - Items in META-INF/services/ lookup can be followed by advisory - "position" attribute. The resulting lookup will list first items with lower - position value. Items without position attribute will be listed - last. See documentation for more details on format. - - - - - - - New lookupItem() method in Lookups - - - - - - New method that returns Lookup.Item implementation for given instance and key identifying - that instance in the lookup. This method is useful when writing Looks which need to - return some cookies (Collection of Lookup.Items). - - - - - - New method Lookups.metaInfServices - - - - - - A lookup that implements the JDK1.3 JAR services mechanism and delegates - to META-INF/services/name.of.class files. This lookup was (is) used by core - and the core had to use reflection to create an instance. Moreover can - be usefull for module authors and in standalone library. - - - - - - - New method Lookups.proxy - - - - - - Creates a lookup that delegates to another one but that one can change - from time to time. The returned lookup checks every time somebody calls - lookup or lookupItem method whether the provider still returns - the same lookup. If not, it updates state of all Lookup.Results - that it created (and that still exists). - - - - - - - Modules can specify the content of Lookup.getDefault - in META-INF/services - - - - - - The content of Lookup.getDefault() can be specified - by a standard JDK registration mechanism, using JARs' - - META-INF/services - - directory. This is suitable for services that do not change, - do not require user modification and that need to be ready - soon during initialization of the system. - - - - - Added org.openide.util.lookup.Lookups - - - - - New utility class added. The class cannot be instantiated - and contains following static methods: -
-public static Lookup singleton(Object objectToLookup);
-public static Lookup fixed(Object[] objectsToLookup);
-public static Lookup fixed(Object[] keys, InstanceContent.Convertor convertor);
-
- The methods return an instance of simple lookup implementation - that holds the objects passed a parameter. -
- - -
- - - Enhanced usage of ProxyLookup & AbstractLookup.Content - - - - - - AbstractLookup.Content made public to allow its usage - for objects that do not subclass AbstractLookup. ProxyLookup.beforeLookup - added so subclasses can update themselves (call setLookups (...)) before the actual lookup is - performed. - - - - - - - Instance content simplifies creation of lookups - - - - - - Added AbstractLookup.Content which can be passed to an - abstract lookup in its constructor and used to control the contents - easily. Also InstanceLookup provides the common easy - implementation. - - - - - - - Folder lookup may be serialized - - - - - Modules which rely on a data object under Services/ gaining - or losing InstanceCookie between sessions may not work - correctly with the cache. This is probably very rare. - - - To implement lookup caching, some lookup implementations are now - serializable: AbstractLookup as well as - FolderLookup's lookup. ProxyLookup has a - protected subclass constructor permitting subclasses to be serializable. - - - - - - - - Changes in access protection of proxy lookup - - - - Changes to newly added feature. - - - ProxyLookup.setLookups made protected instead of public so - nobody can misuse the method except the creator of the object and - ProxyLookup.getLookups added. ProxyLookup made - non final. - - - - - - Lookup service providers package created - - - - - - Package org.openide.util.lookup created, should hold SPI - interfaces for lookup. Initially filled with AbstractLookup - which introduces AbstractLookup.Pair and with - ProxyLookup. - - - - - - - - Added lookup items and support APIs - - - - - - Lookup enhanced. Interface Lookup.Item and - additional methods to access it also added. - - - - - - Lookup system introduced - - - - - Better version of Lookup introduced. There is a - org.openide.util.Lookup with bunch of inner classes and - org.openide.util.LookupListener and - org.openide.util.LookupEvent. - - - - - - - - -Change History for the Lookup API - - - - -

Introduction

-

What do the Dates Mean?

-

The supplied dates indicate when the API change was made, on the CVS -trunk. From this you can generally tell whether the change should be -present in a given build or not; for trunk builds, simply whether it -was made before or after the change; for builds on a stabilization -branch, whether the branch was made before or after the given date. In -some cases corresponding API changes have been made both in the trunk -and in an in-progress stabilization branch, if they were needed for a -bug fix; this ought to be marked in this list.

-
    -
  • The release41 branch was made on Apr 03 '05 for use in the NetBeans 4.1 release. -Specification versions: 6.0 begins after this point.
  • -
  • The release40 branch was made on Nov 01 '04 for use in the NetBeans 4.0 release. -Specification versions: 5.0 begins after this point.
  • -
-
- -
-

@FOOTER@

- -
- diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/manifest.mf --- a/openide.util.lookup/manifest.mf Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: org.openide.util.lookup -OpenIDE-Module-Localizing-Bundle: org/openide/util/lookup/Bundle.properties -OpenIDE-Module-Specification-Version: 8.1 - diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/nbproject/project.properties --- a/openide.util.lookup/nbproject/project.properties Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. -# -# Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. -# -# The contents of this file are subject to the terms of either the GNU -# General Public License Version 2 only ("GPL") or the Common -# Development and Distribution License("CDDL") (collectively, the -# "License"). You may not use this file except in compliance with the -# License. You can obtain a copy of the License at -# http://www.netbeans.org/cddl-gplv2.html -# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the -# specific language governing permissions and limitations under the -# License. When distributing the software, include this License Header -# Notice in each file and include the License file at -# nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun in the GPL Version 2 section of the License file that -# accompanied this code. If applicable, add the following below the -# License Header, with the fields enclosed by brackets [] replaced by -# your own identifying information: -# "Portions Copyrighted [year] [name of copyright owner]" -# -# Contributor(s): -# -# The Original Software is NetBeans. The Initial Developer of the Original -# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun -# Microsystems, Inc. All Rights Reserved. -# -# If you wish your version of this file to be governed by only the CDDL -# or only the GPL Version 2, indicate your decision by adding -# "[Contributor] elects to include this software in this distribution -# under the [CDDL or GPL Version 2] license." If you do not indicate a -# single choice of license, a recipient has the option to distribute -# your version of this file under either the CDDL, the GPL Version 2 or -# to extend the choice of license to its licensees as provided above. -# However, if you add GPL Version 2 code and therefore, elected the GPL -# Version 2 license, then the option applies only if the new code is -# made subject to such option by the copyright holder. - -module.jar.dir=lib -javac.source=1.6 -javac.compilerargs=-Xlint -Xlint:-serial - -javadoc.arch=${basedir}/arch.xml -javadoc.apichanges=${basedir}/apichanges.xml -# Hide org.openide.util.lookup.implspi: -module.javadoc.packages=org.openide.util,org.openide.util.lookup diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/nbproject/project.xml --- a/openide.util.lookup/nbproject/project.xml Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - org.openide.util.lookup - - - - unit - - org.netbeans.libs.junit4 - - - - org.netbeans.modules.nbjunit - - - - - - - org.openide.util - org.openide.util.lookup - org.openide.util.lookup.implspi - - - - diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java --- a/openide.util.lookup/src/org/netbeans/modules/openide/util/ServiceProviderProcessor.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2008 Sun Microsystems, Inc. - */ - -package org.netbeans.modules.openide.util; - -import java.lang.annotation.Annotation; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import javax.annotation.processing.Completion; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.MirroredTypeException; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import org.openide.util.lookup.ServiceProvider; -import org.openide.util.lookup.ServiceProviders; -import org.openide.util.lookup.implspi.AbstractServiceProviderProcessor; - -@SupportedSourceVersion(SourceVersion.RELEASE_6) -public class ServiceProviderProcessor extends AbstractServiceProviderProcessor { - - public @Override Set getSupportedAnnotationTypes() { - return new HashSet(Arrays.asList( - ServiceProvider.class.getCanonicalName(), - ServiceProviders.class.getCanonicalName() - )); - } - - /** public for ServiceLoader */ - public ServiceProviderProcessor() {} - - protected boolean handleProcess(Set annotations, RoundEnvironment roundEnv) { - for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) { - TypeElement clazz = (TypeElement) el; - ServiceProvider sp = clazz.getAnnotation(ServiceProvider.class); - register(clazz, ServiceProvider.class, sp); - } - for (Element el : roundEnv.getElementsAnnotatedWith(ServiceProviders.class)) { - TypeElement clazz = (TypeElement) el; - ServiceProviders spp = clazz.getAnnotation(ServiceProviders.class); - for (ServiceProvider sp : spp.value()) { - register(clazz, ServiceProviders.class, sp); - } - } - return true; - } - - private void register(TypeElement clazz, Class annotation, ServiceProvider svc) { - try { - svc.service(); - assert false; - return; - } catch (MirroredTypeException e) { - register(clazz, annotation, e.getTypeMirror(), svc.path(), svc.position(), svc.supersedes()); - } - } - - @Override - public Iterable getCompletions(Element annotated, AnnotationMirror annotation, ExecutableElement attr, String userText) { - if (processingEnv == null || annotated == null || !annotated.getKind().isClass()) { - return Collections.emptyList(); - } - - if ( annotation == null - || !"org.openide.util.lookup.ServiceProvider".contentEquals(((TypeElement) annotation.getAnnotationType().asElement()).getQualifiedName())) { - return Collections.emptyList(); - } - - if (!"service".contentEquals(attr.getSimpleName())) { - return Collections.emptyList(); - } - - TypeElement jlObject = processingEnv.getElementUtils().getTypeElement("java.lang.Object"); - - if (jlObject == null) { - return Collections.emptyList(); - } - - Collection result = new LinkedList(); - List toProcess = new LinkedList(); - - toProcess.add((TypeElement) annotated); - - while (!toProcess.isEmpty()) { - TypeElement c = toProcess.remove(0); - - result.add(new TypeCompletion(c.getQualifiedName().toString() + ".class")); - - List parents = new LinkedList(); - - parents.add(c.getSuperclass()); - parents.addAll(c.getInterfaces()); - - for (TypeMirror tm : parents) { - if (tm == null || tm.getKind() != TypeKind.DECLARED) { - continue; - } - - TypeElement type = (TypeElement) processingEnv.getTypeUtils().asElement(tm); - - if (!jlObject.equals(type)) { - toProcess.add(type); - } - } - } - - return result; - } - - private static final class TypeCompletion implements Completion { - - private final String type; - - public TypeCompletion(String type) { - this.type = type; - } - - public String getValue() { - return type; - } - - public String getMessage() { - return null; - } - - } - -} diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/src/org/openide/util/lookup/AbstractLookup.java --- a/openide.util.lookup/src/org/openide/util/lookup/AbstractLookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1463 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util.lookup; - -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.Executor; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; -import org.openide.util.lookup.implspi.ActiveQueue; - - -/** Implementation of the lookup from OpenAPIs that is based on the - * introduction of Item. This class should provide the default way - * of how to store (Class, Object) pairs in the lookups. It offers - * protected methods for subclasses to register the pairs. - *

Serializable since 3.27. - * @author Jaroslav Tulach - * @since 1.9 - */ -public class AbstractLookup extends Lookup implements Serializable { - static final long serialVersionUID = 5L; - - /** lock for initialization of the maps of lookups */ - private static final Object treeLock = new Object(); - - /** the tree that registers all items (or Integer as a treshold size) */ - private Object tree; - - /** count of items in to lookup */ - private int count; - - /** Constructor to create this lookup and associate it with given - * Content. The content than allows the creator to invoke protected - * methods which are not accessible for any other user of the lookup. - * - * @param content the content to assciate with - * - * @since 1.25 - */ - public AbstractLookup(Content content) { - content.attach(this); - } - - /** Constructor for testing purposes that allows specification of storage - * as mechanism as well. - */ - AbstractLookup(Content content, Storage storage) { - this(content); - this.tree = storage; - initialize(); - } - - /** Constructor for testing purposes that allows specification of storage - * as mechanism as well. - * @param trashhold number of Pair to "remain small" - */ - AbstractLookup(Content content, Integer trashhold) { - this(content); - this.tree = trashhold; - } - - /** Default constructor for subclasses that do not need to provide a content - */ - protected AbstractLookup() { - } - - @Override - public String toString() { - if (tree instanceof Storage) { - return "AbstractLookup" + lookup(new Lookup.Template(Object.class)).allItems(); // NOI18N - } else { - return super.toString(); - } - } - - /** Entres the storage management system. - */ - @SuppressWarnings("unchecked") - private AbstractLookup.Storage enterStorage() { - for (;;) { - synchronized (treeLock) { - if (tree instanceof AbstractLookup.Storage) { - if (tree instanceof DelegatingStorage) { - // somebody is using the lookup right now - DelegatingStorage del = (DelegatingStorage) tree; - - // check whether there is not access from the same - // thread (can throw exception) - del.checkForTreeModification(); - - try { - treeLock.wait(); - } catch (InterruptedException ex) { - // ignore and go on - } - - continue; - } else { - // ok, tree is initialized and nobody is using it yet - tree = new DelegatingStorage((Storage) tree); - - return (Storage) tree; - } - } - - // first time initialization of the tree - if (tree instanceof Integer) { - tree = new ArrayStorage((Integer) tree); - } else { - tree = new ArrayStorage(); - } - } - - // the tree has not yet been initilized, initialize and go on again - initialize(); - } - } - - /** Exists tree ownership. - */ - private AbstractLookup.Storage exitStorage() { - synchronized (treeLock) { - AbstractLookup.Storage stor = ((DelegatingStorage) tree).exitDelegate(); - tree = stor; - treeLock.notifyAll(); - - return stor; - } - } - - /** Method for subclasses to initialize them selves. - */ - protected void initialize() { - } - - /** Notifies subclasses that a query is about to be processed. - * @param template the template - */ - protected void beforeLookup(Template template) { - } - - /** The method to add instance to the lookup with. - * @param pair class/instance pair - */ - protected final void addPair(Pair pair) { - addPairImpl(pair, null); - } - - /** The method to add instance to the lookup with. - * @param pair class/instance pair - * @param notifyIn the executor that will handle the notification of events - * @since 7.16 - */ - protected final void addPair(Pair pair, Executor notifyIn) { - addPairImpl(pair, notifyIn); - } - - private final void addPairImpl(Pair pair, Executor notifyIn) { - HashSet toNotify = new HashSet(); - - AbstractLookup.Storage t = enterStorage(); - Transaction transaction = null; - - try { - transaction = t.beginTransaction(-2); - - if (t.add(pair, transaction)) { - try { - pair.setIndex(t, count++); - } catch (IllegalStateException ex) { - // remove the pair - t.remove(pair, transaction); - - // rethrow the exception - throw ex; - } - - // if the pair is newly added and was not there before - t.endTransaction(transaction, toNotify); - } else { - // just finish the process by calling endTransaction - t.endTransaction(transaction, new HashSet()); - } - } finally { - exitStorage(); - } - - notifyIn(notifyIn, toNotify); - } - - /** Remove instance. - * @param pair class/instance pair - */ - protected final void removePair(Pair pair) { - removePairImpl(pair, null); - } - /** Remove instance. - * @param pair class/instance pair - * @param notifyIn the executor that will handle the notification of events - * @since 7.16 - */ - protected final void removePair(Pair pair, Executor notifyIn) { - removePairImpl(pair, notifyIn); - } - - private void removePairImpl(Pair pair, Executor notifyIn) { - HashSet toNotify = new HashSet(); - - AbstractLookup.Storage t = enterStorage(); - Transaction transaction = null; - - try { - transaction = t.beginTransaction(-1); - t.remove(pair, transaction); - t.endTransaction(transaction, toNotify); - } finally { - exitStorage(); - } - - notifyIn(notifyIn, toNotify); - } - - /** Changes all pairs in the lookup to new values. - * @param collection the collection of (Pair) objects - */ - protected final void setPairs(Collection collection) { - setPairs(collection, null); - } - - /** Changes all pairs in the lookup to new values, notifies listeners - * using provided executor. - * - * @param collection the collection of (Pair) objects - * @param notifyIn the executor that will handle the notification of events - * @since 7.16 - */ - protected final void setPairs(Collection collection, Executor notifyIn) { - HashSet listeners = setPairsAndCollectListeners(collection); - notifyIn(notifyIn, listeners); - } - - private final void notifyIn(Executor notifyIn, final HashSet listeners) { - NotifyListeners notify = new NotifyListeners(listeners); - if (notify.shallRun()) { - if (notifyIn == null) { - notify.run(); - } else { - notifyIn.execute(notify); - } - } - } - - /** Getter for set of pairs. Package private contract with MetaInfServicesLookup. - * @return a LinkedHashSet that can be modified - */ - final LinkedHashSet> getPairsAsLHS() { - AbstractLookup.Storage t = enterStorage(); - - try { - Enumeration> en = t.lookup(Object.class); - TreeSet> arr = new TreeSet>(ALPairComparator.DEFAULT); - while (en.hasMoreElements()) { - Pair item = en.nextElement(); - arr.add(item); - } - return new LinkedHashSet>(arr); - } finally { - exitStorage(); - } - } - - /** Collects listeners without notification. Needed in MetaInfServicesLookup - * right now, but maybe will become an API later. - */ - final HashSet setPairsAndCollectListeners(Collection collection) { - HashSet toNotify = new HashSet(27); - - AbstractLookup.Storage t = enterStorage(); - Transaction transaction = null; - - try { - // map between the Items and their indexes (Integer) - HashMap,Info> shouldBeThere = new HashMap,Info>(collection.size() * 2); - - count = 0; - - Iterator it = collection.iterator(); - transaction = t.beginTransaction(collection.size()); - - while (it.hasNext()) { - Pair item = (Pair) it.next(); - - if (t.add(item, transaction)) { - // the item has not been there yet - //t.endTransaction(transaction, toNotify); - } - - // remeber the item, because it should not be removed - shouldBeThere.put(item, new Info(count++, transaction)); - - // arr.clear (); - } - - // Object transaction = t.beginTransaction (); - // deletes all objects that should not be there and - t.retainAll(shouldBeThere, transaction); - - // collect listeners - t.endTransaction(transaction, toNotify); - - /* - // check consistency - Enumeration en = t.lookup (java.lang.Object.class); - boolean[] max = new boolean[count]; - int mistake = -1; - while (en.hasMoreElements ()) { - Pair item = (Pair)en.nextElement (); - - if (max[item.index]) { - mistake = item.index; - } - max[item.index] = true; - } - - if (mistake != -1) { - System.err.println ("Mistake at: " + mistake); - tree.print (System.err, true); - } - */ - } finally { - exitStorage(); - } - - return toNotify; - } - - private final void writeObject(ObjectOutputStream oos) - throws IOException { - AbstractLookup.Storage s = enterStorage(); - - try { - // #36830: Serializing only InheritanceTree no ArrayStorage - s.beginTransaction(Integer.MAX_VALUE); - - // #32040: don't write half-made changes - oos.defaultWriteObject(); - } finally { - exitStorage(); - } - } - - public final T lookup(Class clazz) { - Lookup.Item item = lookupItem(new Lookup.Template(clazz)); - return (item == null) ? null : item.getInstance(); - } - - @Override - public final Lookup.Item lookupItem(Lookup.Template template) { - AbstractLookup.this.beforeLookup(template); - - ArrayList> list = null; - AbstractLookup.Storage t = enterStorage(); - - try { - Enumeration> en; - - try { - en = t.lookup(template.getType()); - - return findSmallest(en, template, false); - } catch (AbstractLookup.ISE ex) { - // not possible to enumerate the exception, ok, copy it - // to create new - list = new ArrayList>(); - en = t.lookup(null); // this should get all the items without any checks - - // the checks will be done out side of the storage - while (en.hasMoreElements()) { - list.add(en.nextElement()); - } - } - } finally { - exitStorage(); - } - - return findSmallest(Collections.enumeration(list), template, true); - } - - private static Pair findSmallest(Enumeration> en, Lookup.Template template, boolean deepCheck) { - int smallest = InheritanceTree.unsorted(en) ? Integer.MAX_VALUE : Integer.MIN_VALUE; - Pair res = null; - - while (en.hasMoreElements()) { - Pair item = en.nextElement(); - - if (matches(template, item, deepCheck)) { - if (smallest == Integer.MIN_VALUE) { - // ok, sorted enumeration the first that matches is fine - return item; - } else { - // check for the smallest item - if (smallest > item.getIndex()) { - smallest = item.getIndex(); - res = item; - } - } - } - } - - return res; - } - - public final Lookup.Result lookup(Lookup.Template template) { - for (;;) { - AbstractLookup.ISE toRun = null; - - AbstractLookup.Storage t = enterStorage(); - - try { - R r = new R(); - ReferenceToResult newRef = new ReferenceToResult(r, this, template); - newRef.next = t.registerReferenceToResult(newRef); - - return r; - } catch (AbstractLookup.ISE ex) { - toRun = ex; - } finally { - exitStorage(); - } - - toRun.recover(this); - - // and try again - } - } - - /** Notifies listeners. - * @param allAffectedResults set of R - */ - static final class NotifyListeners implements Runnable { - private final ArrayList evAndListeners; - - public NotifyListeners(Set allAffectedResults) { - if (allAffectedResults.isEmpty()) { - evAndListeners = null; - return; - } - - evAndListeners = new ArrayList(); - { - for (R result : allAffectedResults) { - result.collectFires(evAndListeners); - } - } - } - - public boolean shallRun() { - return evAndListeners != null && !evAndListeners.isEmpty(); - } - - public void run() { - Iterator it = evAndListeners.iterator(); - while (it.hasNext()) { - LookupEvent ev = (LookupEvent)it.next(); - LookupListener l = (LookupListener)it.next(); - l.resultChanged(ev); - } - } - } - - /** - * Call resultChanged on all listeners. - * @param listeners array of listeners in the format used by - * javax.swing.EventListenerList. It means that there are Class - * objects on even positions and the listeners on odd positions - * @param ev the event to fire - */ - static void notifyListeners(Object[] listeners, LookupEvent ev, Collection evAndListeners) { - for (int i = listeners.length - 1; i >= 0; i--) { - if (! (listeners[i] instanceof LookupListener)) { - continue; - } - LookupListener ll = (LookupListener)listeners[i]; - - try { - if (evAndListeners != null) { - if (ll instanceof WaitableResult) { - WaitableResult wr = (WaitableResult)ll; - wr.collectFires(evAndListeners); - } else { - evAndListeners.add(ev); - evAndListeners.add(ll); - } - } else { - ll.resultChanged(ev); - } - } catch (StackOverflowError err) { - throw new CycleError(evAndListeners); // NOI18N - } catch (RuntimeException e) { - // Such as e.g. occurred in #32040. Do not halt other things. - e.printStackTrace(); - } - } - } - - private static class CycleError extends StackOverflowError { - private final Collection print; - public CycleError(Collection evAndListeners) { - this.print = evAndListeners; - } - - @Override - public String getMessage() { - StringBuilder sb = new StringBuilder(); - sb.append("StackOverflowError, here are the listeners:\n"); // NOI18N - for (Object o : print) { - sb.append('\n').append(o); - if (sb.length() > 10000) { - break; - } - } - return sb.toString(); - } - } // end of CycleError - - /** A method that defines matching between Item and Template. - * @param t template providing the criteria - * @param item the item to match - * @param deepCheck true if type of the pair should be tested, false if it is already has been tested - * @return true if item matches the template requirements, false if not - */ - static boolean matches(Template t, Pair item, boolean deepCheck) { - String id = t.getId(); - - if (id != null && !id.equals(item.getId())) { - return false; - } - - Object instance = t.getInstance(); - - if ((instance != null) && !item.creatorOf(instance)) { - return false; - } - - if (deepCheck) { - return item.instanceOf(t.getType()); - } else { - return true; - } - } - - /** - * Compares the array elements for equality. - * @return true if all elements in the arrays are equal - * (by calling equals(Object x) method) - */ - private static boolean compareArrays(Object[] a, Object[] b) { - // handle null values - if (a == null) { - return (b == null); - } else { - if (b == null) { - return false; - } - } - - if (a.length != b.length) { - return false; - } - - for (int i = 0; i < a.length; i++) { - // handle null values for individual elements - if (a[i] == null) { - if (b[i] != null) { - return false; - } - - // both are null --> ok, take next - continue; - } else { - if (b[i] == null) { - return false; - } - } - - // perform the comparison - if (!a[i].equals(b[i])) { - return false; - } - } - - return true; - } - - /** Method to be called when a result is cleared to signal that the list - * of all result should be checked for clearing. - * @param template the template the result was for - * @return true if the hash map with all items has been cleared - */ - boolean cleanUpResult(Lookup.Template template) { - AbstractLookup.Storage t = enterStorage(); - - try { - return t.cleanUpResult(template) == null; - } finally { - exitStorage(); - } - } - - /** Storage check for tests. */ - static boolean isSimple(AbstractLookup l) { - return DelegatingStorage.isSimple((Storage)l.tree); - } - - /** Generic support for listeners, so it can be used in other results - * as well. - * @param add true to add it, false to modify - * @param l listener to modify - * @param ref the value of the reference to listener or listener list - * @return new value to the reference to listener or list - */ - @SuppressWarnings("unchecked") - static Object modifyListenerList(boolean add, LookupListener l, Object ref) { - if (add) { - if (ref == null) { - return l; - } - - if (ref instanceof LookupListener) { - ArrayList arr = new ArrayList(); - arr.add(ref); - ref = arr; - } - - ((ArrayList) ref).add(l); - - return ref; - } else { - // remove - if (ref == null) { - return null; - } - - if (ref == l) { - return null; - } - - ArrayList arr = (ArrayList) ref; - arr.remove(l); - - if (arr.size() == 1) { - return arr.iterator().next(); - } else { - return arr; - } - } - } - - private static ReferenceQueue activeQueue() { - return ActiveQueue.queue(); - } - - /** Storage to keep the internal structure of Pairs and to answer - * different queries. - */ - interface Storage { - /** Initializes a modification operation by creating an object - * that will be passsed to all add, remove, retainAll methods - * and should collect enough information about the change to - * notify listeners about the transaction later - * - * @param ensure the amount of items that will appear in the storage - * after the modifications (-1 == remove one, -2 == add one, >= 0 - * the amount of objects at the end - * @return a token to identify the transaction - */ - public Transaction beginTransaction(int ensure); - - /** Collects all affected results R that were modified in the - * given transaction. - * - * @param modified place to add results R to - * @param transaction the transaction indentification - */ - public void endTransaction(Transaction transaction, Set modifiedResults); - - /** Adds an item into the storage. - * @param item to add - * @param transaction transaction token - * @return true if the Item has been added for the first time or false if some other - * item equal to this one already existed in the lookup - */ - public boolean add(AbstractLookup.Pair item, Transaction transaction); - - /** Removes an item. - */ - public void remove(AbstractLookup.Pair item, Transaction transaction); - - /** Removes all items that are not present in the provided collection. - * @param retain collection of Pairs to keep them in - * @param transaction the transaction context - */ - public void retainAll(Map retain, Transaction transaction); - - /** Queries for instances of given class. - * @param clazz the class to check - * @return enumeration of Item - * @see #unsorted - */ - public Enumeration> lookup(Class clazz); - - /** Registers another reference to a result with the storage. This method - * has also a special meaning. - * - * @param newRef the new reference to remember - * @return the previous reference that was kept (null if newRef is the first one) - * the applications is expected to link from newRef to this returned - * value to form a linked list - */ - public ReferenceToResult registerReferenceToResult(ReferenceToResult newRef); - - /** Given the provided template, Do cleanup the results. - * @param templ template of a result(s) that should be checked - * @return null if all references for this template were cleared or one of them - */ - public ReferenceToResult cleanUpResult(Lookup.Template templ); - } - - /** Extension to the default lookup item that offers additional information - * for the data structures use in AbstractLookup - */ - public static abstract class Pair extends Lookup.Item implements Serializable { - private static final long serialVersionUID = 1L; - - /** possition of this item in the lookup, manipulated in addPair, removePair, setPairs methods */ - private int index = -1; - - /** For use by subclasses. */ - protected Pair() { - } - - final int getIndex() { - return index; - } - - final void setIndex(AbstractLookup.Storage tree, int x) { - if (tree == null) { - this.index = x; - - return; - } - - if (this.index == -1) { - this.index = x; - } else { - throw new IllegalStateException("You cannot use " + this + " in more than one AbstractLookup. Prev: " + this.index + " new: " + x); // NOI18N - } - } - - /** Tests whether this item can produce object - * of class c. - */ - protected abstract boolean instanceOf(Class c); - - /** Method that can test whether an instance of a class has been created - * by this item. - * - * @param obj the instance - * @return if the item has already create an instance and it is the same - * as obj. - */ - protected abstract boolean creatorOf(Object obj); - } - - /** Result based on one instance returned. - */ - static final class R extends WaitableResult { - /** reference our result is attached to (do not modify) */ - public ReferenceToResult reference; - - /** listeners on the results or pointer to one listener */ - private Object listeners; - - public R() { - } - - /** Checks whether we have simple behaviour of complex. - */ - private boolean isSimple() { - Storage s = (Storage) reference.lookup.tree; - - return DelegatingStorage.isSimple(s); - } - - // - // Handling cache management for both cases, no caches - // for simple (but mark that we needed them, so refresh can - // be done in cloneList) and complex when all 3 types - // of result are cached - // - private Object getFromCache(int indx) { - if (isSimple()) { - return null; - } - - Object maybeArray = reference.caches; - - if (maybeArray instanceof Object[]) { - return ((Object[]) maybeArray)[indx]; - } - - return null; - } - - @SuppressWarnings("unchecked") - private Set> getClassesCache() { - return (Set>) getFromCache(0); - } - - private void setClassesCache(Set s) { - if (isSimple()) { - // mark it as being used - reference.caches = reference; - - return; - } - - if (!(reference.caches instanceof Object[])) { - reference.caches = new Object[3]; - } - - ((Object[]) reference.caches)[0] = s; - } - - @SuppressWarnings("unchecked") - private Collection getInstancesCache() { - return (Collection) getFromCache(1); - } - - private void setInstancesCache(Collection c) { - if (isSimple()) { - // mark it as being used - reference.caches = reference; - - return; - } - - if (!(reference.caches instanceof Object[])) { - reference.caches = new Object[3]; - } - - ((Object[]) reference.caches)[1] = c; - } - - @SuppressWarnings("unchecked") - private Pair[] getItemsCache() { - return (Pair[]) getFromCache(2); - } - - private void setItemsCache(Collection c) { - if (isSimple()) { - // mark it as being used - reference.caches = reference; - - return; - } - - if (!(reference.caches instanceof Object[])) { - reference.caches = new Object[3]; - } - - ((Object[]) reference.caches)[2] = c.toArray(new Pair[0]); - } - - private void clearCaches() { - if (reference.caches instanceof Object[]) { - reference.caches = new Object[3]; - } - } - - /** Ok, register listeners to all classes and super classes. - */ - public synchronized void addLookupListener(LookupListener l) { - listeners = modifyListenerList(true, l, listeners); - } - - /** Ok, register listeners to all classes and super classes. - */ - public synchronized void removeLookupListener(LookupListener l) { - listeners = modifyListenerList(false, l, listeners); - } - - /** Delete all cached values, the template changed. - */ - protected void collectFires(Collection evAndListeners) { - Object[] previousItems = getItemsCache(); - clearCaches(); - - if (previousItems != null) { - Object[] newArray = allItemsWithoutBeforeLookup().toArray(); - - if (compareArrays(previousItems, newArray)) { - // do not fire any change if nothing has been changed - return; - } - } - - LookupListener[] arr; - - synchronized (this) { - if (listeners == null) { - return; - } - - if (listeners instanceof LookupListener) { - arr = new LookupListener[] { (LookupListener) listeners }; - } else { - ArrayList l = (ArrayList) listeners; - arr = l.toArray(new LookupListener[l.size()]); - } - } - - final LookupListener[] ll = arr; - final LookupEvent ev = new LookupEvent(this); - notifyListeners(ll, ev, evAndListeners); - } - - public Collection allInstances() { - reference.lookup.beforeLookup(reference.template); - - Collection s = getInstancesCache(); - - if (s != null) { - return s; - } - - Collection> items = allItemsWithoutBeforeLookup(); - ArrayList list = new ArrayList(items.size()); - - Iterator> it = items.iterator(); - - while (it.hasNext()) { - Pair item = it.next(); - T obj = item.getInstance(); - - if (reference.template.getType().isInstance(obj)) { - list.add(obj); - } - } - - s = Collections.unmodifiableList(list); - setInstancesCache(s); - - return s; - } - - /** Set of all classes. - * - */ - @Override - public Set> allClasses() { - reference.lookup.beforeLookup(reference.template); - - Set> s = getClassesCache(); - - if (s != null) { - return s; - } - - s = new HashSet>(); - - for (Pair item : allItemsWithoutBeforeLookup()) { - Class clazz = item.getType(); - - if (clazz != null) { - s.add(clazz); - } - } - - s = Collections.unmodifiableSet(s); - setClassesCache(s); - - return s; - } - - /** Items are stored directly in the allItems. - */ - @Override - public Collection> allItems() { - reference.lookup.beforeLookup(reference.template); - - return allItemsWithoutBeforeLookup(); - } - - /** Implements the search for allItems, but without asking for before lookup */ - private Collection> allItemsWithoutBeforeLookup() { - Pair[] c = getItemsCache(); - - if (c != null) { - return Collections.unmodifiableList(Arrays.asList(c)); - } - - ArrayList> saferCheck = null; - AbstractLookup.Storage t = reference.lookup.enterStorage(); - - try { - try { - return Collections.unmodifiableCollection(initItems(t)); - } catch (AbstractLookup.ISE ex) { - // do less effective evaluation of items outside of the - // locked storage - saferCheck = new ArrayList>(); - - Enumeration> en = t.lookup(null); // get all Pairs - - while (en.hasMoreElements()) { - Pair i = en.nextElement(); - saferCheck.add(i); - } - } - } finally { - reference.lookup.exitStorage(); - } - return extractPairs(saferCheck); - } - - @SuppressWarnings("unchecked") - private Collection> extractPairs(final ArrayList> saferCheck) { - TreeSet> items = new TreeSet>(ALPairComparator.DEFAULT); - for (Pair i : saferCheck) { - if (matches(reference.template, i, false)) { - items.add((Pair)i); - } - } - return Collections.unmodifiableCollection(items); - } - - /** Initializes items. - */ - private Collection> initItems(Storage t) { - // manipulation with the tree must be synchronized - Enumeration> en = t.lookup(reference.template.getType()); - - // InheritanceTree is comparator for AbstractLookup.Pairs - TreeSet> items = new TreeSet>(ALPairComparator.DEFAULT); - - while (en.hasMoreElements()) { - Pair i = en.nextElement(); - - if (matches(reference.template, i, false)) { - items.add(i); - } - } - - // create a correctly sorted copy using the tree as the comparator - setItemsCache(items); - - return items; - } - - /** Used by proxy results to synchronize before lookup. - */ - protected void beforeLookup(Lookup.Template t) { - if (t.getType() == reference.template.getType()) { - reference.lookup.beforeLookup(t); - } - } - - /* Do not need to implement it, the default way is ok. - public boolean equals(java.lang.Object obj) { - return obj == this; - } - */ - @Override - public String toString() { - return super.toString() + " for " + reference.template; - } - } - // end of R - - /** A class that can be used by the creator of the AbstractLookup to - * control its content. It can be passed to AbstractLookup constructor - * and used to add and remove pairs. - * - * @since 1.25 - */ - public static class Content extends Object implements Serializable { - private static final long serialVersionUID = 1L; - - // one of them is always null (except attach stage) - - /** abstract lookup we are connected to */ - private AbstractLookup al; - private transient Object notifyIn; - - /** Default constructor. - */ - public Content() { - this(null); - } - - /** Creates a content associated with an executor to handle dispatch - * of changes. - * @param notifyIn the executor to notify changes in - * @since 7.16 - */ - public Content(Executor notifyIn) { - this.notifyIn = notifyIn; - } - - /** for testing purposes */ - final void attachExecutor(Executor notifyIn) { - this.notifyIn = notifyIn; - } - - /** A lookup attaches to this object. - */ - final synchronized void attach(AbstractLookup al) { - if (this.al == null) { - this.al = al; - - ArrayList ep = getEarlyPairs(); - if (ep != null) { - notifyIn = null; - setPairs(ep); - } - } else { - throw new IllegalStateException( - "Trying to use content for " + al + " but it is already used for " + this.al - ); // NOI18N - } - } - - /** The method to add instance to the lookup with. - * @param pair class/instance pair - */ - public final void addPair(Pair pair) { - AbstractLookup a = al; - Executor e = getExecutor(); - - if (a != null || e != null) { - a.addPair(pair, e); - } else { - if (notifyIn == null) { - notifyIn = new ArrayList(3); - } - - getEarlyPairs().add(pair); - } - } - - /** Remove instance. - * @param pair class/instance pair - */ - public final void removePair(Pair pair) { - AbstractLookup a = al; - Executor e = getExecutor(); - - if (a != null || e != null) { - a.removePair(pair, e); - } else { - if (notifyIn == null) { - notifyIn = new ArrayList(3); - } - - getEarlyPairs().remove(pair); - } - } - - /** Changes all pairs in the lookup to new values. - * @param c the collection of (Pair) objects - */ - public final void setPairs(Collection c) { - AbstractLookup a = al; - Executor e = getExecutor(); - - if (a != null || e != null) { - a.setPairs(c, e); - } else { - notifyIn = new ArrayList(c); - } - } - - @SuppressWarnings("unchecked") - private ArrayList getEarlyPairs() { - Object o = notifyIn; - return o instanceof ArrayList ? (ArrayList)o : null; - } - - private Executor getExecutor() { - Object o = notifyIn; - return o instanceof Executor ? (Executor)o : null; - } - } - // end of Content - - /** Just a holder for index & modified values. - */ - final static class Info extends Object { - public int index; - public Object transaction; - - public Info(int i, Object t) { - index = i; - transaction = t; - } - } - - /** Reference to a result R - */ - static final class ReferenceToResult extends WeakReference> implements Runnable { - /** next refernece in chain, modified only from AbstractLookup or this */ - private ReferenceToResult next; - - /** the template for the result */ - public final Template template; - - /** the lookup we are attached to */ - public final AbstractLookup lookup; - - /** caches for results */ - public Object caches; - - /** Creates a weak refernece to a new result R in context of lookup - * for given template - */ - private ReferenceToResult(R result, AbstractLookup lookup, Template template) { - super(result, activeQueue()); - this.template = template; - this.lookup = lookup; - getResult().reference = this; - } - - /** Returns the result or null - */ - R getResult() { - return get(); - } - - /** Cleans the reference. Implements Runnable interface, do not call - * directly. - */ - public void run() { - lookup.cleanUpResult(this.template); - } - - /** Clones the reference list to given Storage. - * @param storage storage to clone to - */ - public void cloneList(AbstractLookup.Storage storage) { - ReferenceIterator it = new ReferenceIterator(this); - - while (it.next()) { - ReferenceToResult current = it.current(); - ReferenceToResult newRef = current.cloneRef(); - newRef.next = storage.registerReferenceToResult(newRef); - newRef.caches = current.caches; - - if (current.caches == current) { - current.getResult().initItems(storage); - } - } - } - - private ReferenceToResult cloneRef() { - return new ReferenceToResult(getResult(), lookup, template); - } - } - // end of ReferenceToResult - - /** Supporting class to iterate over linked list of ReferenceToResult - * Use: - *
-     *  ReferenceIterator it = new ReferenceIterator (this.ref);
-     *  while (it.next ()) {
-     *    it.current (): // do some work
-     *  }
-     *  this.ref = it.first (); // remember the first one
-     */
-    static final class ReferenceIterator extends Object {
-        private ReferenceToResult first;
-        private ReferenceToResult current;
-
-        /** hard reference to current result, so it is not GCed meanwhile */
-        private R currentResult;
-
-        /** Initializes the iterator with first reference.
-         */
-        public ReferenceIterator(ReferenceToResult first) {
-            this.first = first;
-        }
-
-        /** Moves the current to next possition */
-        public boolean next() {
-            ReferenceToResult prev;
-            ReferenceToResult ref;
-
-            if (current == null) {
-                ref = first;
-                prev = null;
-            } else {
-                prev = current;
-                ref = current.next;
-            }
-
-            while (ref != null) {
-                R result = ref.get();
-
-                if (result == null) {
-                    if (prev == null) {
-                        // move the head
-                        first = ref.next;
-                    } else {
-                        // skip over this reference
-                        prev.next = ref.next;
-                    }
-
-                    prev = ref;
-                    ref = ref.next;
-                } else {
-                    // we have found next item
-                    currentResult = result;
-                    current = ref;
-
-                    return true;
-                }
-            }
-
-            currentResult = null;
-            current = null;
-
-            return false;
-        }
-
-        /** Access to current reference.
-         */
-        public ReferenceToResult current() {
-            return current;
-        }
-
-        /** Access to reference that is supposed to be the first one.
-         */
-        public ReferenceToResult first() {
-            return first;
-        }
-    }
-
-    /** Signals that a lookup is being modified from a lookup query.
-     *
-     * @author  Jaroslav Tulach
-     */
-    static final class ISE extends IllegalStateException {
-        static final long serialVersionUID = 100L;
-        
-        /** list of jobs to execute. */
-        private java.util.List jobs;
-
-        /** @param msg message
-         */
-        public ISE(String msg) {
-            super(msg);
-        }
-
-        /** Registers a job to be executed partially out and partially in
-         * the lock over storage.
-         */
-        public void registerJob(Job job) {
-            if (jobs == null) {
-                jobs = new java.util.ArrayList();
-            }
-
-            jobs.add(job);
-        }
-
-        /** Executes the jobs outside, and then inside a locked session.
-         */
-        public void recover(AbstractLookup lookup) {
-            if (jobs == null) {
-                // no recovery plan, throw itself
-                throw this;
-            }
-
-            for (Job j : jobs) {
-                j.before();
-            }
-
-            AbstractLookup.Storage s = lookup.enterStorage();
-
-            try {
-                for (Job j : jobs) {
-                    j.inside();
-                }
-            } finally {
-                lookup.exitStorage();
-            }
-        }
-
-        /** A job to be executed partially outside and partially inside
-         * the storage lock.
-         */
-        static interface Job {
-            public void before();
-
-            public void inside();
-        }
-    }
-     // end of ISE
-}
diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/src/org/openide/util/lookup/Lookups.java
--- a/openide.util.lookup/src/org/openide/util/lookup/Lookups.java	Wed Jan 27 17:46:23 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,325 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common
- * Development and Distribution License("CDDL") (collectively, the
- * "License"). You may not use this file except in compliance with the
- * License. You can obtain a copy of the License at
- * http://www.netbeans.org/cddl-gplv2.html
- * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
- * specific language governing permissions and limitations under the
- * License.  When distributing the software, include this License Header
- * Notice in each file and include the License file at
- * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the GPL Version 2 section of the License file that
- * accompanied this code. If applicable, add the following below the
- * License Header, with the fields enclosed by brackets [] replaced by
- * your own identifying information:
- * "Portions Copyrighted [year] [name of copyright owner]"
- *
- * Contributor(s):
- *
- * The Original Software is NetBeans. The Initial Developer of the Original
- * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
- * Microsystems, Inc. All Rights Reserved.
- *
- * If you wish your version of this file to be governed by only the CDDL
- * or only the GPL Version 2, indicate your decision by adding
- * "[Contributor] elects to include this software in this distribution
- * under the [CDDL or GPL Version 2] license." If you do not indicate a
- * single choice of license, a recipient has the option to distribute
- * your version of this file under either the CDDL, the GPL Version 2 or
- * to extend the choice of license to its licensees as provided above.
- * However, if you add GPL Version 2 code and therefore, elected the GPL
- * Version 2 license, then the option applies only if the new code is
- * made subject to such option by the copyright holder.
- */
-
-package org.openide.util.lookup;
-
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import org.openide.util.Lookup;
-import org.openide.util.lookup.implspi.NamedServicesProvider;
-
-/**
- * Static factory methods for creating common lookup implementations.
- *
- * @author David Strupl
- * @since 2.21
- */
-public class Lookups {
-
-    /** static methods only */
-    private Lookups() {}
-
-    /**
-     * Creates a singleton lookup. It means lookup that contains only
-     * one object specified via the supplied parameter. The lookup will
-     * either return the object or null if the supplied template does
-     * not match the class. If the specified argument is null the method
-     * will end with NullPointerException.
-     * @return Fully initialized lookup object ready to use
-     * @throws NullPointerException if the supplied argument is null
-     * @since 2.21
-     */
-    public static Lookup singleton(Object objectToLookup) {
-        if (objectToLookup == null) {
-            throw new NullPointerException();
-        }
-
-        return new SingletonLookup(objectToLookup);
-    }
-
-    /**
-     * Creates a lookup that contains an array of objects specified via the
-     * parameter. The resulting lookup is fixed in the following sense: it
-     * contains only fixed set of objects passed in by the array parameter.
-     * Its contents never changes so registering listeners on such lookup
-     * does not have any observable effect (the listeners are never called).
-     *
-     * @param objectsToLookup list of objects to include
-     * @return Fully initialized lookup object ready to use
-     * @throws NullPointerException if the supplied argument is null
-     * @since 2.21
-     *
-     */
-    public static Lookup fixed(Object... objectsToLookup) {
-        if (objectsToLookup == null) {
-            throw new NullPointerException();
-        }
-
-        if (objectsToLookup.length == 0) {
-            return Lookup.EMPTY;
-        }
-
-        if (objectsToLookup.length == 1) {
-            return singleton(objectsToLookup[0]);
-        }
-
-        return new SimpleLookup(Arrays.asList(objectsToLookup));
-    }
-
-    /**
-     * Creates a lookup that contains an array of objects specified via the
-     * parameter. The resulting lookup is fixed in the following sense: it
-     * contains only fixed set of objects passed in by the array parameter.
-     * The objects returned from this lookup are converted to real objects
-     * before they are returned by the lookup.
-     * Its contents never changes so registering listeners on such lookup
-     * does not have any observable effect (the listeners are never called).
-     *
-     * @return Fully initialized lookup object ready to use
-     * @throws NullPointerException if the any of the arguments is null
-     * @since 2.21
-     *
-     */
-    public static  Lookup fixed(T[] keys, InstanceContent.Convertor convertor) {
-        if (keys == null) {
-            throw new NullPointerException();
-        }
-
-        if (convertor == null) {
-            throw new NullPointerException();
-        }
-
-        return new SimpleLookup(Arrays.asList(keys), convertor);
-    }
-
-    /** Creates a lookup that delegates to another one but that one can change
-     * from time to time. The returned lookup checks every time somebody calls
-     * lookup or lookupItem method whether the
-     * provider still returns the same lookup. If not, it updates state of
-     * all {@link org.openide.util.Lookup.Result}s 
-     * that it created (and that still exists).
-     * 

- * The user of this method has to implement its provider's getLookup - * method (must be thread safe and fast, will be called often and from any thread) - * pass it to this method and use the returned lookup. Whenever the user - * changes the return value from the getLookup method and wants - * to notify listeners on the lookup about that it should trigger the event - * firing, for example by calling lookup.lookup (Object.class) - * directly on the lookup returned by this method - * that forces a check of the return value of {@link org.openide.util.Lookup.Provider#getLookup}. - * - * @param provider the provider that returns a lookup to delegate to - * @return lookup delegating to the lookup returned by the provider - * @since 3.9 - */ - public static Lookup proxy(Lookup.Provider provider) { - return new SimpleProxyLookup(provider); - } - - /** Returns a lookup that implements the JDK1.3 JAR services mechanism and delegates - * to META-INF/services/name.of.class files. - *

Some extensions to the JAR services specification are implemented: - *

    - *
  1. An entry may be followed by a line of the form #position=integer - * to specify ordering. (Smaller numbers first, entries with unspecified position last.) - *
  2. A line of the form #-classname suppresses an entry registered - * in another file, so can be used to supersede one implementation with another. - *
- *

Note: It is not dynamic - so if you need to change the classloader or JARs, - * wrap it in a {@link ProxyLookup} and change the delegate when necessary. - * Existing instances will be kept if the implementation classes are unchanged, - * so there is "stability" in doing this provided some parent loaders are the same - * as the previous ones. - * @since 3.35 - * @see ServiceProvider - */ - public static Lookup metaInfServices(ClassLoader classLoader) { - return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N - } - - /** Returns a lookup that behaves exactly like {@link #metaInfServices(ClassLoader)} - * except that it does not read data from META-INF/services/, but instead - * from the specified prefix. - * @param classLoader class loader to use for loading - * @param prefix prefix to prepend to the class name when searching - * @since 7.9 - */ - public static Lookup metaInfServices(ClassLoader classLoader, String prefix) { - return new MetaInfServicesLookup(classLoader, prefix); - } - - /** Creates a named lookup. - * It is a lookup identified by a given path. - * Two lookups with the same path should have the same content. - *

It is expected that each named lookup - * will contain a superset of what would be created by: - * {@linkplain #metaInfServices(ClassLoader,String) metaInfServices}(theRightLoader, "META-INF/namedservices/" + path + "/") - * - *

Various environments can add their own - * extensions to its content. As such - * {@link Lookups#forPath(java.lang.String)} can combine lookups - * from several sources. In current NetBeans Runtime Container, two lookups are used: - *

- *
    - *
  • Lookups.metaInfServices("META-INF/namedservices/" + path)
  • - *
  • org.openide.loaders.FolderLookup(path)
  • - *
- *

- * Please note that these lookups differ in the way they inspect sub-folders. - * The first lookup just returns instances from the given path, ignoring - * sub-folders, the second one retrieves instances from the whole sub-tree. - *

- *

- * Read more about the usage of this method. - * - * @param path the path identifying the lookup, e.g. Projects/Actions - * @return lookup associated with this path - * @since 7.9 - */ - public static Lookup forPath(String path) { - if (!path.endsWith("/")) { - path = path + "/"; - } - return NamedServicesProvider.forPath(path); - } - - /** Creates a lookup that wraps another one and filters out instances - * of specified classes. If you have a lookup and - * you want to remove all instances of ActionMap you can use: - *

-     * l = Lookups.exclude(lookup, ActionMap.class);
-     * 
- * Then anybody who asks for l.lookup(ActionMap.class) or - * subclass will get null. Even if the original lookup contains the - * value. - * To create empty lookup (well, just an example, otherwise use {@link Lookup#EMPTY}) one could use: - *
-     * Lookup.exclude(anyLookup, Object.class);
-     * 
- * as any instance in any lookup is of type Object and thus would be excluded. - *

- * The complete behavior can be described as classes being - * a barrier. For an object not to be excluded, there has to be an inheritance - * path between the queried class and the actual class of the instance, - * that is not blocked by any of the excluded classes: - *

-     * interface A {}
-     * interface B {}
-     * class C implements A, B {}
-     * Object c = new C();
-     * Lookup l1 = Lookups.singleton(c);
-     * Lookup l2 = Lookups.exclude(l1, A.class);
-     * assertNull("A is directly excluded", l2.lookup(A.class));
-     * assertEquals("Returns C as A.class is not between B and C", c, l2.lookup(B.class));
-     * 
- * For more info check the - * - * excluding lookup tests and the discussion in issue - * 53058. - * - * @param lookup the original lookup that should be filtered - * @param classes array of classes those instances should be excluded - * @since 5.4 - */ - public static Lookup exclude(Lookup lookup, Class... classes) { - return new ExcludingLookup(lookup, classes); - } - - /** Creates Lookup.Item representing the instance passed in. - * - * @param instance the object for which Lookup.Item should be creted - * @param id unique identification of the object, for details see {@link org.openide.util.Lookup.Item#getId}, - * can be null - * @return lookup item representing instance - * @since 4.8 - */ - public static Lookup.Item lookupItem(T instance, String id) { - return new LookupItem(instance, id); - } - - private static class LookupItem extends Lookup.Item { - private String id; - private T instance; - - public LookupItem(T instance) { - this(instance, null); - } - - public LookupItem(T instance, String id) { - this.id = id; - this.instance = instance; - } - - public String getDisplayName() { - return getId(); - } - - public String getId() { - return (id == null) ? instance.toString() : id; - } - - public T getInstance() { - return instance; - } - - @SuppressWarnings("unchecked") - public Class getType() { - return (Class)instance.getClass(); - } - - public @Override boolean equals(Object object) { - if (object instanceof LookupItem) { - return instance == ((LookupItem) object).getInstance(); - } - - return false; - } - - public @Override int hashCode() { - return instance.hashCode(); - } - } - // End of LookupItem class -} diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/src/org/openide/util/lookup/MetaInfServicesLookup.java --- a/openide.util.lookup/src/org/openide/util/lookup/MetaInfServicesLookup.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,576 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.openide.util.Lookup; - -/** - * @author Jaroslav Tulach, Jesse Glick - * @see Lookups#metaInfServices(ClassLoader,String) - * @see "#14722" - */ -final class MetaInfServicesLookup extends AbstractLookup { - - private static final Logger LOGGER = Logger.getLogger(MetaInfServicesLookup.class.getName()); - static final Executor RP; - static { - Executor res = null; - try { - Class seek = Class.forName("org.openide.util.RequestProcessor"); - res = (Executor)seek.newInstance(); - } catch (Throwable t) { - res = Executors.newSingleThreadExecutor(); - } - RP = res; - } - /*TBD: Inject RequestProcessor somehow - new RequestProcessor(MetaInfServicesLookup.class.getName(), 1); - */ - private static int knownInstancesCount; - private static final List> knownInstances; - static { - knownInstances = new ArrayList>(); - for (int i = 0; i < 512; i++) { - knownInstances.add(null); - } - } - - /** A set of all requested classes. - * Note that classes that we actually succeeded on can never be removed - * from here because we hold a strong reference to the loader. - * However we also hold classes which are definitely not loadable by - * our loader. - */ - private final Map classes = new WeakHashMap(); - - /** class loader to use */ - private final ClassLoader loader; - /** prefix to prepend */ - private final String prefix; - - /** Create a lookup reading from a specified classloader. - */ - public MetaInfServicesLookup(ClassLoader loader, String prefix) { - this.loader = loader; - this.prefix = prefix; - - LOGGER.log(Level.FINE, "Created: {0}", this); - } - - @Override - public String toString() { - return "MetaInfServicesLookup[" + loader + "]"; // NOI18N - } - - /* Tries to load appropriate resources from manifest files. - */ - @Override - protected final void beforeLookup(Lookup.Template t) { - Class c = t.getType(); - - Collection> toAdd = null; - synchronized (this) { - if (classes.get(c) == null) { // NOI18N - toAdd = new ArrayList>(); - } else { - // ok, nothing needs to be done - return; - } - } - if (toAdd != null) { - search(c, toAdd); - } - synchronized (this) { - if (classes.put(c, "") == null) { // NOI18N - // Added new class, search for it. - LinkedHashSet> arr = getPairsAsLHS(); - arr.addAll(toAdd); - setPairs(arr, RP); - } - } - } - - /** Finds all pairs and adds them to the collection. - * - * @param clazz class to find - * @param result collection to add Pair to - */ - private void search(Class clazz, Collection> result) { - if (LOGGER.isLoggable(Level.FINER)) { - LOGGER.log(Level.FINER, "Searching for " + clazz.getName() + " in " + clazz.getClassLoader() + " from " + this); - } - - String res = prefix + clazz.getName(); // NOI18N - Enumeration en; - - try { - en = loader.getResources(res); - } catch (IOException ioe) { - // do not use ErrorManager because we are in the startup code - // and ErrorManager might not be ready - ioe.printStackTrace(); - - return; - } - - // Do not create multiple instances in case more than one JAR - // has the same entry in it (and they load to the same class). - // Probably would not happen, assuming JARs only list classes - // they own, but just in case... - List foundClasses = new ArrayList(); - Collection removeClasses = new ArrayList(); - - boolean foundOne = false; - - while (en.hasMoreElements()) { - if (!foundOne) { - foundOne = true; - - // Double-check that in fact we can load the *interface* class. - // For example, say class I is defined in two JARs, J1 and J2. - // There is also an implementation M1 defined in J1, and another - // implementation M2 defined in J2. - // Classloaders C1 and C2 are made from J1 and J2. - // A MetaInfServicesLookup is made from C1. Then the user asks to - // lookup I as loaded from C2. J1 has the services line and lists - // M1, and we can in fact make it. However it is not of the desired - // type to be looked up. Don't do this check, which could be expensive, - // unless we expect to be getting some results, however. - Class realMcCoy = null; - - try { - realMcCoy = loader.loadClass(clazz.getName()); - } catch (ClassNotFoundException cnfe) { - // our loader does not know about it, OK - } - - if (realMcCoy != clazz) { - // Either the interface class is not available at all in our loader, - // or it is not the same version as we expected. Don't provide results. - if (LOGGER.isLoggable(Level.WARNING)) { - if (realMcCoy != null) { - LOGGER.log(Level.WARNING, - clazz.getName() + " is not the real McCoy! Actually found it in " + - realMcCoy.getClassLoader() - ); // NOI18N - } else { - LOGGER.log(Level.WARNING, clazz.getName() + " could not be found in " + loader); // NOI18N - } - } - - return; - } - } - - URL url = en.nextElement(); - Item currentItem = null; - - try { - InputStream is = url.openStream(); - - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N - - while (true) { - String line = reader.readLine(); - - if (line == null) { - break; - } - - line = line.trim(); - - // is it position attribute? - if (line.startsWith("#position=")) { - if (currentItem == null) { - LOGGER.log(Level.WARNING, "Found line '{0}' in {1} but there is no item to associate it with", new Object[] {line, url}); - continue; - } - - try { - currentItem.position = Integer.parseInt(line.substring(10)); - } catch (NumberFormatException e) { - // do not use ErrorManager because we are in the startup code - // and ErrorManager might not be ready - e.printStackTrace(); - } - } - - if (currentItem != null) { - insertItem(currentItem, foundClasses); - currentItem = null; - } - - // Ignore blank lines and comments. - if (line.length() == 0) { - continue; - } - - boolean remove = false; - - if (line.charAt(0) == '#') { - if ((line.length() == 1) || (line.charAt(1) != '-')) { - continue; - } - - // line starting with #- is a sign to remove that class from lookup - remove = true; - line = line.substring(2); - } - - Class inst = null; - - try { - // Most lines are fully-qualified class names. - inst = Class.forName(line, false, loader); - } catch (ClassNotFoundException cnfe) { - if (remove) { - // if we are removing somthing and the something - // cannot be found it is ok to do nothing - continue; - } else { - // but if we are not removing just rethrow - throw cnfe; - } - } - - if (!clazz.isAssignableFrom(inst)) { - throw new ClassNotFoundException(clazzToString(inst) + " not a subclass of " + clazzToString(clazz)); // NOI18N - } - - if (remove) { - removeClasses.add(inst); - } else { - // create new item here, but do not put it into - // foundClasses array yet because following line - // might specify its position - currentItem = new Item(); - currentItem.clazz = inst; - } - } - - if (currentItem != null) { - insertItem(currentItem, foundClasses); - currentItem = null; - } - } finally { - is.close(); - } - } catch (ClassNotFoundException ex) { - LOGGER.log(Level.WARNING, null, ex); - } catch (IOException ex) { - LOGGER.log(Level.WARNING, null, ex); - } - } - - LOGGER.log(Level.FINER, "Found impls of {0}: {1} and removed: {2} from: {3}", new Object[] {clazz.getName(), foundClasses, removeClasses, this}); - - foundClasses.removeAll(removeClasses); - - for (Item item : foundClasses) { - if (removeClasses.contains(item.clazz)) { - continue; - } - - result.add(new P(item.clazz)); - } - } - private static String clazzToString(Class clazz) { - return clazz.getName() + "@" + clazz.getClassLoader() + ":" + clazz.getProtectionDomain().getCodeSource().getLocation(); // NOI18N - } - - /** - * Insert item to the list according to item.position value. - */ - private void insertItem(Item item, List list) { - // no position? -> add it to the end - if (item.position == -1) { - list.add(item); - - return; - } - - int index = -1; - for (Item i : list) { - index++; - - if (i.position == -1) { - list.add(index, item); - - return; - } else { - if (i.position > item.position) { - list.add(index, item); - - return; - } - } - } - - list.add(item); - } - - private static class Item { - private Class clazz; - private int position = -1; - @Override - public String toString() { - return "MetaInfServicesLookup.Item[" + clazz.getName() + "]"; // NOI18N - } - } - - /** Pair that holds name of a class and maybe the instance. - */ - private static final class P extends AbstractLookup.Pair { - /** May be one of three things: - * 1. The implementation class which was named in the services file. - * 2. An instance of it. - * 3. Null, if creation of the instance resulted in an error. - */ - private Object object; - - public P(Class clazz) { - this.object = clazz; - } - - /** Finds the class. - */ - private Class clazz() { - Object o = object; - - if (o instanceof Class) { - return (Class) o; - } else if (o != null) { - return o.getClass(); - } else { - // Broken. - return Object.class; - } - } - - @Override - public boolean equals(Object o) { - if (o instanceof P) { - return ((P) o).clazz().equals(clazz()); - } - - return false; - } - - @Override - public int hashCode() { - return clazz().hashCode(); - } - - protected boolean instanceOf(Class c) { - return c.isAssignableFrom(clazz()); - } - - public Class getType() { - return clazz(); - } - - public Object getInstance() { - Object o = object; // keeping local copy to avoid another - - // thread to modify it under my hands - if (o instanceof Class) { - synchronized (o) { // o is Class and we will not create - // 2 instances of the same class - - try { - Class c = ((Class) o); - o = null; - - synchronized (knownInstances) { // guards only the static cache - int size = knownInstances.size(); - int index = hashForClass(c, size); - for (int i = 0; i < size; i++) { - Reference ref = knownInstances.get(index); - Object obj = ref == null ? null : ref.get(); - if (obj == null) { - break; - } - if (c == obj.getClass()) { - o = obj; - break; - } - if (++index == size) { - index = 0; - } - } - } - - if (o == null) { - o = createInstance(c); - - synchronized (knownInstances) { // guards only the static cache - hashPut(o); - - int size = knownInstances.size(); - if (knownInstancesCount > size * 2 / 3) { - LOGGER.log(Level.CONFIG, "Cache of size {0} is 2/3 full. Rehashing.", size); - HashSet> all = new HashSet>(); - all.addAll(knownInstances); - for (int i = 0; i < size; i++) { - knownInstances.set(i, null); - } - for (int i = 0; i < size; i++) { - knownInstances.add(null); - } - knownInstancesCount = 0; - for (Reference r : all) { - if (r == null) { - continue; - } - Object instance = r.get(); - if (instance == null) { - continue; - } - hashPut(instance); - } - } - - } - } - - // Do not assign to instance var unless there is a complete synch - // block between the newInstance and this line. Otherwise we could - // be assigning a half-constructed instance that another thread - // could see and return immediately. - object = o; - } catch (Exception ex) { - LOGGER.log(Level.WARNING, "Cannot create " + object, ex); - object = null; - } catch (LinkageError x) { // #174055 + NoClassDefFoundError - LOGGER.log(Level.WARNING, "Cannot create " + object, x); - object = null; - } - } - } - - return object; - } - - public String getDisplayName() { - return clazz().getName(); - } - - public String getId() { - return clazz().getName(); - } - - protected boolean creatorOf(Object obj) { - return obj == object; - } - private static int hashForClass(Class c, int size) { - return Math.abs(c.hashCode()) % size; - } - - private static void hashPut(Object o) { - Class c = o.getClass(); - int size = knownInstances.size(); - int index = hashForClass(c, size); - for (int i = 0; i < size; i++) { - Reference ref = knownInstances.get(index); - Object obj = ref == null ? null : ref.get(); - if (obj == null) { - knownInstances.set(index, new WeakReference(o)); - knownInstancesCount++; - break; - } - if (++index == size) { - index = 0; - } - } - } - - private static boolean findSharedClassObjectSkip; - private static Method findSharedClassObject; - /** Basically does c.newInstance(), however the method is complicated - * with a special behaviour for old and almost obsoleted NetBeans - * class: SharedClassObject. - */ - private static Object createInstance(Class c) throws InstantiationException, IllegalAccessException { - if (!findSharedClassObjectSkip) { - try { - if (findSharedClassObject == null) { - Class sco; - try { - sco = Class.forName("org.openide.util.SharedClassObject"); // NOI18N - } catch (ClassNotFoundException ex) { - findSharedClassObjectSkip = true; - return c.newInstance(); - } - findSharedClassObject = sco.getMethod("findObject", Class.class, boolean.class); - } - if (findSharedClassObject.getReturnType().isAssignableFrom(c)) { - return findSharedClassObject.invoke(null, c, true); - } - } catch (Exception problem) { - throw (InstantiationException)new InstantiationException(problem.getMessage()).initCause(problem); - } - } - return c.newInstance(); - } - } -} diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/src/org/openide/util/lookup/implspi/AbstractServiceProviderProcessor.java --- a/openide.util.lookup/src/org/openide/util/lookup/implspi/AbstractServiceProviderProcessor.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,307 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2009 Sun Microsystems, Inc. - */ - -package org.openide.util.lookup.implspi; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; -import javax.tools.Diagnostic.Kind; -import javax.tools.FileObject; -import javax.tools.StandardLocation; - -/** - * Infrastructure for generating {@code META-INF/services/*} and - * {@code META-INF/namedservices/*} registrations from annotations. - * @since 8.1 - */ -public abstract class AbstractServiceProviderProcessor extends AbstractProcessor { - - private final Map>> outputFilesByProcessor = new WeakHashMap>>(); - private final Map>> originatingElementsByProcessor = new WeakHashMap>>(); - private final Map verifiedClasses = new WeakHashMap(); - - /** Throws IllegalStateException. For access by selected subclasses. */ - protected AbstractServiceProviderProcessor() { - if (getClass().getName().equals("org.netbeans.modules.openide.util.ServiceProviderProcessor")) { // NOI18N - // OK subclass - return; - } - if (getClass().getName().equals("org.netbeans.modules.openide.util.URLStreamHandlerRegistrationProcessor")) { // NOI18N - // OK subclass - return; - } - throw new IllegalStateException(); - } - - public @Override final boolean process(Set annotations, RoundEnvironment roundEnv) { - if (roundEnv.errorRaised()) { - return false; - } - if (roundEnv.processingOver()) { - writeServices(); - outputFilesByProcessor.clear(); - originatingElementsByProcessor.clear(); - return true; - } else { - return handleProcess(annotations, roundEnv); - } - } - - /** - * The regular body of {@link #process}. - * Called during regular rounds if there are no outstanding errors. - * In the last round, one of the processors will write out generated registrations. - * @param annotations as in {@link #process} - * @param roundEnv as in {@link #process} - * @return as in {@link #process} - */ - protected abstract boolean handleProcess(Set annotations, RoundEnvironment roundEnv); - - /** - * Register a service. - * If the class does not have an appropriate signature, an error will be printed and the registration skipped. - * @param clazz the service implementation type - * @param annotation the (top-level) annotation registering the service, for diagnostic purposes - * @param type the type to which the implementation must be assignable - * @param path a path under which to register, or "" if inapplicable - * @param position a position at which to register, or {@link Integer#MAX_VALUE} to skip - * @param supersedes possibly empty list of implementation to supersede - */ - protected final void register(TypeElement clazz, Class annotation, - TypeMirror type, String path, int position, String[] supersedes) { - Boolean verify = verifiedClasses.get(clazz); - if (verify == null) { - verify = verifyServiceProviderSignature(clazz, annotation); - verifiedClasses.put(clazz, verify); - } - if (!verify) { - return; - } - String impl = processingEnv.getElementUtils().getBinaryName(clazz).toString(); - String xface = processingEnv.getElementUtils().getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(type)).toString(); - if (!processingEnv.getTypeUtils().isAssignable(clazz.asType(), type)) { - AnnotationMirror ann = findAnnotationMirror(clazz, annotation); - processingEnv.getMessager().printMessage(Kind.ERROR, impl + " is not assignable to " + xface, - clazz, ann, findAnnotationValue(ann, "service")); - return; - } - processingEnv.getMessager().printMessage(Kind.NOTE, - impl + " to be registered as a " + xface + (path.length() > 0 ? " under " + path : "")); - String rsrc = (path.length() > 0 ? "META-INF/namedservices/" + path + "/" : "META-INF/services/") + xface; - { - Map> originatingElements = originatingElementsByProcessor.get(processingEnv); - if (originatingElements == null) { - originatingElements = new HashMap>(); - originatingElementsByProcessor.put(processingEnv, originatingElements); - } - List origEls = originatingElements.get(rsrc); - if (origEls == null) { - origEls = new ArrayList(); - originatingElements.put(rsrc, origEls); - } - origEls.add(clazz); - } - Map> outputFiles = outputFilesByProcessor.get(processingEnv); - if (outputFiles == null) { - outputFiles = new HashMap>(); - outputFilesByProcessor.put(processingEnv, outputFiles); - } - List lines = outputFiles.get(rsrc); - if (lines == null) { - lines = new ArrayList(); - try { - try { - FileObject in = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", rsrc); - in.openInputStream().close(); - processingEnv.getMessager().printMessage(Kind.ERROR, - "Cannot generate " + rsrc + " because it already exists in sources: " + in.toUri()); - return; - } catch (NullPointerException ex) { - // trying to prevent java.lang.NullPointerException - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1078) - // at com.sun.tools.javac.util.DefaultFileManager.getFileForOutput(DefaultFileManager.java:1054) - // at com.sun.tools.javac.processing.JavacFiler.getResource(JavacFiler.java:434) - // at org.netbeans.modules.openide.util.AbstractServiceProviderProcessor.register(AbstractServiceProviderProcessor.java:163) - // at org.netbeans.modules.openide.util.ServiceProviderProcessor.register(ServiceProviderProcessor.java:99) - } catch (FileNotFoundException x) { - // Good. - } - try { - FileObject in = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", rsrc); - InputStream is = in.openInputStream(); - try { - BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8")); - String line; - while ((line = r.readLine()) != null) { - lines.add(line); - } - } finally { - is.close(); - } - } catch (FileNotFoundException x) { - // OK, created for the first time - } - } catch (IOException x) { - processingEnv.getMessager().printMessage(Kind.ERROR, x.toString()); - return; - } - outputFiles.put(rsrc, lines); - } - int idx = lines.indexOf(impl); - if (idx != -1) { - lines.remove(idx); - while (lines.size() > idx && lines.get(idx).matches("#position=.+|#-.+")) { - lines.remove(idx); - } - } - lines.add(impl); - if (position != Integer.MAX_VALUE) { - lines.add("#position=" + position); - } - for (String exclude : supersedes) { - lines.add("#-" + exclude); - } - } - - /** - * @param element a source element - * @param annotation a type of annotation - * @return the instance of that annotation on the element, or null if not found - */ - private AnnotationMirror findAnnotationMirror(Element element, Class annotation) { - for (AnnotationMirror ann : element.getAnnotationMirrors()) { - if (processingEnv.getElementUtils().getBinaryName((TypeElement) ann.getAnnotationType().asElement()). - contentEquals(annotation.getName())) { - return ann; - } - } - return null; - } - - /** - * @param annotation an annotation instance (null permitted) - * @param name the name of an attribute of that annotation - * @return the corresponding value if found - */ - private AnnotationValue findAnnotationValue(AnnotationMirror annotation, String name) { - if (annotation != null) { - for (Map.Entry entry : annotation.getElementValues().entrySet()) { - if (entry.getKey().getSimpleName().contentEquals(name)) { - return entry.getValue(); - } - } - } - return null; - } - - private final boolean verifyServiceProviderSignature(TypeElement clazz, Class annotation) { - AnnotationMirror ann = findAnnotationMirror(clazz, annotation); - if (!clazz.getModifiers().contains(Modifier.PUBLIC)) { - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must be public", clazz, ann); - return false; - } - if (clazz.getModifiers().contains(Modifier.ABSTRACT)) { - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must not be abstract", clazz, ann); - return false; - } - { - boolean hasDefaultCtor = false; - for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) { - if (constructor.getModifiers().contains(Modifier.PUBLIC) && constructor.getParameters().isEmpty()) { - hasDefaultCtor = true; - break; - } - } - if (!hasDefaultCtor) { - processingEnv.getMessager().printMessage(Kind.ERROR, clazz + " must have a public no-argument constructor", clazz, ann); - return false; - } - } - return true; - } - - private void writeServices() { - for (Map.Entry>> outputFiles : outputFilesByProcessor.entrySet()) { - for (Map.Entry> entry : outputFiles.getValue().entrySet()) { - try { - FileObject out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", entry.getKey(), - originatingElementsByProcessor.get(outputFiles.getKey()).get(entry.getKey()).toArray(new Element[0])); - OutputStream os = out.openOutputStream(); - try { - PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8")); - for (String line : entry.getValue()) { - w.println(line); - } - w.flush(); - w.close(); - } finally { - os.close(); - } - } catch (IOException x) { - processingEnv.getMessager().printMessage(Kind.ERROR, "Failed to write to " + entry.getKey() + ": " + x.toString()); - } - } - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/src/org/openide/util/lookup/implspi/ActiveQueue.java --- a/openide.util.lookup/src/org/openide/util/lookup/implspi/ActiveQueue.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -package org.openide.util.lookup.implspi; - -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Implementation of the active reference queue. - * @since 8.1 - */ -public final class ActiveQueue { - - private ActiveQueue() {} - - private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.')); - private static Impl activeReferenceQueue; - - /** - * Gets the active reference queue. - * @return the singleton queue - */ - public static synchronized ReferenceQueue queue() { - if (activeReferenceQueue == null) { - activeReferenceQueue = new Impl(false); - } - - activeReferenceQueue.ping(); - - return activeReferenceQueue; - } - - private static final class Impl extends ReferenceQueue implements Runnable { - - /** number of known outstanding references */ - private int count; - private boolean deprecated; - - Impl(boolean deprecated) { - super(); - this.deprecated = deprecated; - } - - @Override - public Reference poll() { - throw new UnsupportedOperationException(); - } - - @Override - public Reference remove(long timeout) throws IllegalArgumentException, InterruptedException { - throw new InterruptedException(); - } - - @Override - public Reference remove() throws InterruptedException { - throw new InterruptedException(); - } - - public void run() { - while (true) { - try { - Reference ref = super.remove(0); - LOGGER.finer("dequeued reference"); - if (!(ref instanceof Runnable)) { - LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass()); - continue; - } - if (deprecated) { - LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue"); - } - // do the cleanup - try { - ((Runnable) ref).run(); - } catch (ThreadDeath td) { - throw td; - } catch (Throwable t) { - // Should not happen. - // If it happens, it is a bug in client code, notify! - LOGGER.log(Level.WARNING, null, t); - } finally { - // to allow GC - ref = null; - } - } catch (InterruptedException ex) { - // Can happen during VM shutdown, it seems. Ignore. - continue; - } - synchronized (this) { - assert count > 0; - count--; - if (count == 0) { - // We have processed all we have to process (for now at least). - // Could be restarted later if ping() called again. - // This could also happen in case someone called queue() once and tried - // to use it for several references; in that case run() might never be called on - // the later ones to be collected. Can't really protect against that situation. - // See issue #86625 for details. - LOGGER.fine("stopping thread"); - break; - } - } - } - } - - synchronized void ping() { - if (count == 0) { - Thread t = new Thread(this, "Active Reference Queue Daemon"); - t.setPriority(Thread.MIN_PRIORITY); - t.setDaemon(true); - t.start(); - LOGGER.fine("starting thread"); - } else { - LOGGER.finer("enqueuing reference"); - } - count++; - } - - } - -} diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/src/org/openide/util/lookup/implspi/NamedServicesProvider.java --- a/openide.util.lookup/src/org/openide/util/lookup/implspi/NamedServicesProvider.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. - * - * Portions Copyrighted 2006 Sun Microsystems, Inc. - */ - -package org.openide.util.lookup.implspi; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.openide.util.Lookup; -import org.openide.util.lookup.Lookups; - -/** Infrastructure provider interface for those who control the overall - * registration of services in the system. The first instance of this interface - * found in {@link Lookup#getDefault()} is consulted when providing answers - * to {@link Lookups#forPath(java.lang.String)} queries. Current implementation - * is not ready for multiple instances of this interface (the first one wins) - * and also changing the instances during runtime. - * - *
- * The basic implementation of this interface is provided in - * Filesystem API - * and recognizes the - * .instance files - * registered in XML layers. As such one can rely on - * .instance files - * being recognized in unit tests, if the - * Filesystem API - * is included. - * The implementation - * is then refined in - * Settings API - * to handle also .settings files. - * Again, including this module in unit tests - * ensures - * .settings files - * files are recognized. - *
- * - * @author Jaroslav Tulach - * @since 8.1 - */ -public abstract class NamedServicesProvider { - private static final Map> namedServicesProviders = Collections.synchronizedMap(new HashMap>()); - - public static Lookup forPath(String path) { - - Reference ref = namedServicesProviders.get(path); - Lookup lkp = ref == null ? null : ref.get(); - if (lkp != null) { - return lkp; - } - NamedServicesProvider prov = Lookup.getDefault().lookup(NamedServicesProvider.class); - if (prov != null && - /* avoid stack overflow during initialization */ - !path.startsWith( - "URLStreamHandler/" - /*URLStreamHandlerRegistrationProcessor.REGISTRATION_PREFIX*/ - ) - ) { - lkp = prov.create(path); - } else { - ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class); - if (l == null) { - l = Thread.currentThread().getContextClassLoader(); - if (l == null) { - l = NamedServicesProvider.class.getClassLoader(); - } - } - lkp = Lookups.metaInfServices(l, "META-INF/namedservices/" + path); - } - - namedServicesProviders.put(path, new WeakReference(lkp)); - return lkp; - } - - /** Throws an exception. Prevents unwanted instantiation of this class - * by unknown subclasses. - */ - protected NamedServicesProvider() { - if (getClass().getName().equals("org.openide.util.lookup.PathInLookupTest$P")) { // NOI18N - // OK for tests - return; - } - if (getClass().getName().equals("org.openide.util.UtilitiesTest$NamedServicesProviderImpl")) { // NOI18N - // OK for tests - return; - } - if (getClass().getName().equals("org.netbeans.modules.openide.filesystems.RecognizeInstanceFiles")) { // NOI18N - // OK for openide.filesystems - return; - } - if (getClass().getName().equals("org.netbeans.modules.settings.RecognizeInstanceObjects")) { // NOI18N - // OK for settings - return; - } - throw new IllegalStateException(); - } - - /** Create the lookup for given path. Called as a result of query to - * {@link Lookups#forPath(java.lang.String)}. - * - * @param path the identification of the path - * @return the lookup representing objects in this path. - */ - protected abstract Lookup create(String path); - -} diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/src/org/openide/util/lookup/implspi/package-info.java --- a/openide.util.lookup/src/org/openide/util/lookup/implspi/package-info.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2010 Sun Microsystems, Inc. - */ - -/** - * Interfaces intended to be used within the NetBeans Platform. - */ -package org.openide.util.lookup.implspi; diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/test/unit/src/org/netbeans/modules/openide/util/ActiveQueueTest.java --- a/openide.util.lookup/test/unit/src/org/netbeans/modules/openide/util/ActiveQueueTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2009 Sun Microsystems, Inc. - */ - -package org.netbeans.modules.openide.util; - -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.net.URL; -import java.net.URLClassLoader; -import org.netbeans.junit.NbTestCase; -import org.openide.util.lookup.implspi.ActiveQueue; - -/** - * - * @author Jaroslav Tulach - */ -public class ActiveQueueTest extends NbTestCase{ - - public ActiveQueueTest(String name) { - super(name); - } - - public void testMemoryLeak() throws Exception { - final Class u1 = ActiveQueue.class; - class L extends URLClassLoader { - public L() { - super(new URL[] {u1.getProtectionDomain().getCodeSource().getLocation()}, u1.getClassLoader().getParent()); - } - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (name.equals(u1.getName()) || name.startsWith(u1.getName() + "$")) { - Class c = findLoadedClass(name); - if (c == null) { - c = findClass(name); - } - if (resolve) { - resolveClass(c); - } - return c; - } else { - return super.loadClass(name, resolve); - } - } - } - ClassLoader l = new L(); - Class u2 = l.loadClass(u1.getName()); - assertEquals(l, u2.getClassLoader()); - Object obj = new Object(); - @SuppressWarnings("unchecked") - ReferenceQueue q = (ReferenceQueue) u2.getMethod("queue").invoke(null); - RunnableRef ref = new RunnableRef(obj, q); - synchronized (ref) { - obj = null; - assertGC("Ref should be GC'ed as usual", ref); - ref.wait(); - assertTrue("Run method has been executed", ref.executed); - } - Reference r = new WeakReference(u2); - q = null; - u2 = null; - l = null; - assertGC("#86625: Utilities.class can also be collected now", r); - } - - - private static class RunnableRef extends WeakReference - implements Runnable { - public boolean wait; - public boolean entered; - public boolean executed; - - public RunnableRef (Object o) { - this(o, ActiveQueue.queue()); - } - - public RunnableRef(Object o, ReferenceQueue q) { - super(o, q); - } - - public synchronized void run () { - entered = true; - if (wait) { - // notify we are here - notify (); - try { - wait (); - } catch (InterruptedException ex) { - } - } - executed = true; - - notifyAll (); - } - } - -} \ No newline at end of file diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupMemoryTest.java --- a/openide.util.lookup/test/unit/src/org/openide/util/lookup/AbstractLookupMemoryTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.util.Arrays; -import java.util.Collections; -import org.netbeans.junit.NbTestCase; -import org.netbeans.junit.NbTestSuite; -import org.openide.util.Lookup; -import org.openide.util.lookup.implspi.ActiveQueue; - -/** Testing memory consumption of various AbstractLookup aspects. - */ -public class AbstractLookupMemoryTest extends NbTestCase { - public AbstractLookupMemoryTest(java.lang.String testName) { - super(testName); - } - - public static void main(java.lang.String[] args) { - junit.textui.TestRunner.run(new NbTestSuite(AbstractLookupMemoryTest.class)); - } - - public void testEmptySize () { - AbstractLookup instanceLookup = new AbstractLookup (); - assertSize ("Empty lookup should be small", 16, instanceLookup); - - InstanceContent ic = new InstanceContent (); - instanceLookup = new AbstractLookup (ic); - assertSize ("Lookup with InstanceContent should be small as well", 16, instanceLookup); - } - - public void testPairSize () { - AbstractLookup.Pair pair = new EmptyPair (); - assertSize ("Pair occupies only 16 bytes", 16, pair); - } - - public void testPairWithOnePointerSize () { - AbstractLookup.Pair pair = new OneItemPair (); - assertSize ("Pair occupies only 16 bytes", 16, pair); - } - - public void testLookupWithPairs () { - Lookup.Template t = new Lookup.Template(Object.class); - class L implements org.openide.util.LookupListener { - public int cnt; - public void resultChanged (org.openide.util.LookupEvent ev) { - cnt++; - } - } - L listener = new L (); - L listener2 = new L (); - - EmptyPair[] pairs = { - new EmptyPair(), - new EmptyPair(), - new EmptyPair(), - new EmptyPair(), - }; - Object[] ignore = { - pairs[0], - pairs[1], - pairs[2], - pairs[3], - t, - ActiveQueue.queue(), - listener, - listener2, - new Integer (11) // trashhold is shared - }; - - AbstractLookup.Content c = new AbstractLookup.Content (); - AbstractLookup l = new AbstractLookup (c, (Integer)ignore[ignore.length - 1]); - - c.addPair ((EmptyPair)ignore[0]); - assertSize ("Should be really small (not counting the pair sizes)", Collections.singleton (l), 56, ignore); - - c.addPair ((EmptyPair)ignore[1]); - assertSize ("Is bigger I guess (not counting the pair sizes)", Collections.singleton (l), 56, ignore); - - c.setPairs(Arrays.asList(pairs).subList(0, 3)); - assertSize ("Even bigger (not counting the pair sizes)", Collections.singleton (l), 64, ignore); - - c.setPairs(Arrays.asList(pairs).subList(0, 4)); - assertSize ("Now not that much(not counting the pair sizes)", Collections.singleton (l), 64, ignore); - - Lookup.Result res = l.lookup (t); - - assertSize ("After creating a result", Collections.singleton (l), 120, ignore); - - res.addLookupListener (listener); - - assertSize ("And attaching one listener", Collections.singleton (l), 120, ignore); - - res.addLookupListener (listener2); - assertSize ("Second listener makes the situation much worse", Collections.singleton (l), 200, ignore); - res.removeLookupListener(listener2); - assertSize ("But removing it returns us back to original size", Collections.singleton (l), 120, ignore); - - - assertEquals ("Current for pairs are in", res.allItems ().size (), 4); // also activates the listener - assertSize ("and making the listener to work", Collections.singleton (l), 120, ignore); - - c.removePair ((EmptyPair)ignore[0]); - assertEquals ("A changes has been delivered", 1, listener.cnt); - } - - /** Simple pair with no data */ - private static class EmptyPair extends AbstractLookup.Pair { - protected boolean creatorOf(Object obj) { return false; } - public String getDisplayName() { return ""; } - public String getId() { return ""; } - public Object getInstance() { return null; } - public Class getType() { return Object.class; } - protected boolean instanceOf(Class c) { return c == getType (); } - } // end of EmptyPair - - /** Pair with one item (like InstanceContent.Pair) */ - private static class OneItemPair extends EmptyPair { - private Object pointer; - } -} diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/test/unit/src/org/openide/util/lookup/PathInLookupTest.java --- a/openide.util.lookup/test/unit/src/org/openide/util/lookup/PathInLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.lang.reflect.Field; -import java.util.logging.Level; -import org.netbeans.junit.MockServices; -import org.netbeans.junit.NbTestCase; -import org.openide.util.Lookup; -import org.openide.util.lookup.implspi.NamedServicesProvider; - -/** - * @author Jaroslav Tulach - */ -public class PathInLookupTest extends NbTestCase { - public PathInLookupTest(String name) { - super(name); - } - - @Override - protected Level logLevel() { - return Level.FINE; - } - - @Override - protected void setUp() throws Exception { - Lookup.getDefault(); - Field f = Lookup.class.getDeclaredField("defaultLookup"); - f.setAccessible(true); - f.set(null, null); - System.setProperty("org.openide.util.Lookup.paths", "MyServices:YourServices"); - MockServices.setServices(P.class); - Lookup.getDefault(); - } - - public void testInterfaceFoundInMyServices() throws Exception { - assertNull("not found", Lookup.getDefault().lookup(Shared.class)); - Shared v = new Shared(); - P.ic1.add(v); - assertNotNull("found", Lookup.getDefault().lookup(Shared.class)); - P.ic1.remove(v); - assertNull("not found again", Lookup.getDefault().lookup(Shared.class)); - } - public void testInterfaceFoundInMyServices2() throws Exception { - assertNull("not found", Lookup.getDefault().lookup(Shared.class)); - Shared v = new Shared(); - P.ic2.add(v); - assertNotNull("found", Lookup.getDefault().lookup(Shared.class)); - P.ic2.remove(v); - assertNull("not found again", Lookup.getDefault().lookup(Shared.class)); - } - - static final class Shared extends Object {} - - public static final class P extends NamedServicesProvider { - static InstanceContent ic1 = new InstanceContent(); - static InstanceContent ic2 = new InstanceContent(); - static AbstractLookup[] arr = { - new AbstractLookup(ic1), new AbstractLookup(ic2) - }; - - public Lookup create(String path) { - int indx = -1; - if (path.equals("MyServices/")) { - indx = 0; - } - if (path.equals("YourServices/")) { - indx = 1; - } - if (indx == -1) { - fail("Unexpected lookup query: " + path); - } - return arr[indx]; - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 openide.util.lookup/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java --- a/openide.util.lookup/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,657 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.lookup; - -import java.io.Serializable; - -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.concurrent.Executor; -import junit.framework.Test; -import org.netbeans.junit.NbTestSuite; -import org.openide.util.Lookup; -import org.openide.util.Lookup.Result; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; -import org.openide.util.lookup.implspi.ActiveQueue; - -/** Runs all NbLookupTest tests on ProxyLookup and adds few additional. - */ -@SuppressWarnings("unchecked") // XXX ought to be corrected, just a lot of them -public class ProxyLookupTest extends AbstractLookupBaseHid -implements AbstractLookupBaseHid.Impl { - public ProxyLookupTest(java.lang.String testName) { - super(testName, null); - } - - public static Test suite() { - return new NbTestSuite (ProxyLookupTest.class); -// return new ProxyLookupTest("testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679"); - } - - /** Creates an lookup for given lookup. This class just returns - * the object passed in, but subclasses can be different. - * @param lookup in lookup - * @return a lookup to use - */ - public Lookup createLookup (Lookup lookup) { - return new ProxyLookup (new Lookup[] { lookup }); - } - - public Lookup createInstancesLookup (InstanceContent ic) { - return new AbstractLookup (ic); - } - - - public void clearCaches () { - } - - - /** Check whether setLookups method does not fire when there is no - * change in the lookups. - */ - public void testProxyListener () { - ProxyLookup lookup = new ProxyLookup (new Lookup[0]); - - final Lookup.Template template = new Lookup.Template(Object.class); - final Object[] IGNORE = { - ProxyLookup.ImmutableInternalData.EMPTY, - ProxyLookup.ImmutableInternalData.EMPTY_ARR, - ActiveQueue.queue(), - Collections.emptyMap(), - Collections.emptyList(), - Collections.emptySet() - }; - - assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE); - - Lookup.Result res = lookup.lookup (template); - - assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE); - - LL ll = new LL (); - res.addLookupListener (ll); - Collection allRes = res.allInstances (); - - lookup.setLookups (new Lookup[0]); - - if (ll.getCount () != 0) { - fail ("Calling setLookups (emptyarray) fired a change"); - } - - InstanceContent t = new InstanceContent(); - Lookup del = new AbstractLookup (t); - t.add("Ahoj"); - lookup.setLookups (new Lookup[] { del }); - - if (ll.getCount () != 1) { - fail ("Changing lookups did not generate an event"); - } - - lookup.setLookups (new Lookup[] { del }); - - if (ll.getCount () != 0) { - fail ("Calling setLookups (thesamearray) fired a change"); - } - } - - public void testNoListenersProxyListener () { - ProxyLookup lookup = new ProxyLookup (new Lookup[0]); - class E implements Executor { - Runnable r; - public void execute(Runnable command) { - assertNull("NO previous", r); - r = command; - } - public void perform() { - assertNotNull("We shall have a runnable", r); - r.run(); - r = null; - } - } - E executor = new E(); - - - final Lookup.Template template = new Lookup.Template(Object.class); - final Object[] IGNORE = { - ProxyLookup.ImmutableInternalData.EMPTY, - ProxyLookup.ImmutableInternalData.EMPTY_ARR, - ActiveQueue.queue(), - Collections.emptyMap(), - Collections.emptyList(), - Collections.emptySet() - }; - - assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE); - - Lookup.Result res = lookup.lookup (template); - - assertSize("Bigger", Collections.singleton(lookup), 216, IGNORE); - - LL ll = new LL (); - res.addLookupListener (ll); - Collection allRes = res.allInstances (); - - lookup.setLookups (executor, new Lookup[0]); - if (ll.getCount () != 0) { - fail ("Calling setLookups (emptyarray) fired a change"); - } - - InstanceContent t = new InstanceContent(); - Lookup del = new AbstractLookup (t); - t.add("Ahoj"); - lookup.setLookups (executor, new Lookup[] { del }); - assertEquals("No change yet", 0, ll.getCount()); - executor.perform(); - if (ll.getCount () != 1) { - fail ("Changing lookups did not generate an event"); - } - - lookup.setLookups (executor, new Lookup[] { del }); - if (ll.getCount () != 0) { - fail ("Calling setLookups (thesamearray) fired a change"); - } - } - - public void testSetLookups () throws Exception { - AbstractLookup a1 = new AbstractLookup (new InstanceContent ()); - AbstractLookup a2 = new AbstractLookup (new InstanceContent ()); - - InstanceContent i3 = new InstanceContent (); - i3.add (i3); - AbstractLookup a3 = new AbstractLookup (i3); - - final ProxyLookup p = new ProxyLookup (new Lookup[] { a1, a2 }); - final Lookup.Result res1 = p.lookup (new Lookup.Template (Object.class)); - Collection c1 = res1.allInstances(); - - Lookup.Result res2 = p.lookup (new Lookup.Template (String.class)); - Collection c2 = res2.allInstances (); - - - assertTrue ("We need two results", res1 != res2); - - final Object blocked = new Object (); - - class L extends Object implements LookupListener { - public void resultChanged (LookupEvent ev) { - try { - res1.removeLookupListener(this); - - // waiting for second thread to start #111# - blocked.wait (); - - } catch (Exception ex) { - ex.printStackTrace(); - fail ("An exception occured "); - } - } - } - - final L listener1 = new L (); - res1.addLookupListener (listener1); - - - Runnable newLookupSetter = new Runnable() { - public void run () { - synchronized (blocked) { - try { - p.setLookups (new Lookup[0]); - } catch (Exception ex) { - ex.printStackTrace(); - fail ("setLookups failed."); - } finally { - // starts the main thread #111# - blocked.notify (); - } - } - } - }; - - synchronized (blocked) { - new Thread (newLookupSetter).start (); - - p.setLookups (new Lookup[] { a1, a2, a3 }); - } - } - - public void testProxyLookupTemplateCaching(){ - Lookup lookups[] = new Lookup[1]; - doProxyLookupTemplateCaching(lookups, false); - } - - public void testProxyLookupTemplateCachingOnSizeTwoArray() { - Lookup lookups[] = new Lookup[2]; - lookups[1] = Lookup.EMPTY; - doProxyLookupTemplateCaching(lookups, false); - } - public void testProxyLookupShallNotAllowModificationOfGetLookups(){ - Lookup lookups[] = new Lookup[1]; - doProxyLookupTemplateCaching(lookups, true); - } - - public void testProxyLookupShallNotAllowModificationOfGetLookupsOnSizeTwoArray() { - Lookup lookups[] = new Lookup[2]; - lookups[1] = Lookup.EMPTY; - doProxyLookupTemplateCaching(lookups, true); - } - - /** Index 0 of lookups will be modified, the rest is up to the - * setup code. - */ - private void doProxyLookupTemplateCaching(Lookup[] lookups, boolean reget) { - // Create MyProxyLookup with one lookup containing the String object - InstanceContent inst = new InstanceContent(); - inst.add(new String("Hello World")); //NOI18N - lookups[0] = new AbstractLookup(inst); - ProxyLookup proxy = new ProxyLookup(lookups); - if (reget) { - lookups = proxy.getLookups(); - } - - // Performing template lookup for String object - Lookup.Result result = proxy.lookup(new Lookup.Template(String.class, null, null)); - int stringTemplateResultSize = result.allInstances().size(); - assertEquals ("Ensure, there is only one instance of String.class in proxyLookup:", //NOI18N - 1, stringTemplateResultSize); - - // Changing lookup in proxy lookup, now it will contain - // StringBuffer Object instead of String - InstanceContent ic2 = new InstanceContent(); - ic2.add(new Integer(1234567890)); - lookups[0] = new AbstractLookup(ic2); - proxy.setLookups(lookups); - - assertEquals ("the old result is updated", 0, result.allInstances().size()); - - // Instance of String.class should not appear in proxyLookup - Lookup.Result r2 = proxy.lookup(new Lookup.Template(String.class, null, null)); - assertEquals ("Instance of String.class should not appear in proxyLookup:", //NOI18N - 0, r2.allInstances().size()); - - Lookup.Result r3 = proxy.lookup(new Lookup.Template(Integer.class, null, null)); - assertEquals ("There is only one instance of Integer.class in proxyLookup:", //NOI18N - 1, r3.allInstances().size()); - } - - public void testListeningAndQueryingByTwoListenersInstancesSetLookups() { - doListeningAndQueryingByTwoListenersSetLookups(0, 1); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups() { - doListeningAndQueryingByTwoListenersSetLookups(1, 1); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups() { - doListeningAndQueryingByTwoListenersSetLookups(2, 1); - } - - public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() { - doListeningAndQueryingByTwoListenersSetLookups(0, 2); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups2() { - doListeningAndQueryingByTwoListenersSetLookups(1, 2); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups2() { - doListeningAndQueryingByTwoListenersSetLookups(2, 2); - } - public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() { - doListeningAndQueryingByTwoListenersSetLookups(0, 22); - } - public void testListeningAndQueryingByTwoListenersClassesSetLookups22() { - doListeningAndQueryingByTwoListenersSetLookups(1, 22); - } - public void testListeningAndQueryingByTwoListenersItemsSetLookups22() { - doListeningAndQueryingByTwoListenersSetLookups(2, 22); - } - - private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth) { - ProxyLookup orig = new ProxyLookup(); - ProxyLookup on = orig; - - while (--depth > 0) { - on = new ProxyLookup(new Lookup[] { on }); - } - - - final ProxyLookup lookup = on; - - class L implements LookupListener { - Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class)); - Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class)); - Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class)); - - { - integer.addLookupListener(this); - number.addLookupListener(this); - serial.addLookupListener(this); - } - - int round; - - public void resultChanged(LookupEvent ev) { - Collection c1 = get(type, integer); - Collection c2 = get(type, number); - Collection c3 = get(type, serial); - - assertEquals("round " + round + " c1 vs. c2", c1, c2); - assertEquals("round " + round + " c1 vs. c3", c1, c3); - assertEquals("round " + round + " c2 vs. c3", c2, c3); - - round++; - } - - private Collection get(int type, Lookup.Result res) { - Collection c; - switch(type) { - case 0: c = res.allInstances(); break; - case 1: c = res.allClasses(); break; - case 2: c = res.allItems(); break; - default: c = null; fail("Type: " + type); break; - } - - assertNotNull(c); - return new ArrayList(c); - } - } - - L listener = new L(); - listener.resultChanged(null); - ArrayList arr = new ArrayList(); - for(int i = 0; i < 100; i++) { - arr.add(new Integer(i)); - - orig.setLookups(new Lookup[] { Lookups.fixed(arr.toArray()) }); - } - - assertEquals("3x100+1 checks", 301, listener.round); - } - - static Object holder; - - public void testProxyWithLiveResultCanBeCollected() { - Lookup layer0 = Lookups.singleton("Hello"); - Lookup layer1 = new ProxyLookup(new Lookup[] { layer0 }); - Lookup layer2 = new ProxyLookup(new Lookup[] { layer1 }); - Lookup.Result result1 = layer1.lookup(new Lookup.Template(String.class)); - - assertEquals("One instance", 1, result1.allInstances().size()); - - // this will create ProxyLookup$R which listens on origResult - Lookup.Result result2 = layer2.lookup(new Lookup.Template(String.class)); - - // this line is necessary. W/o actually querying the result, - // it will nether compute it nor attach the listener. - assertEquals("One instance", 1, result2.allInstances().size()); - - result2.addLookupListener(new LookupListener() { - public void resultChanged(LookupEvent ev) {} - }); - - Reference ref = new WeakReference(layer2); - layer2 = null; - result2 = null; - try { - holder = result1; - assertGC ("The proxy lookup not been garbage collected!", ref); - } finally { - holder = null; - } - } - - public void testArrayIndexAsInIssue119292() throws Exception { - final ProxyLookup pl = new ProxyLookup(); - final int[] cnt = { 0 }; - - class L extends Lookup { - L[] set; - Lookup l; - - public L(String s) { - l = Lookups.singleton(s); - } - - @Override - public T lookup(Class clazz) { - return l.lookup(clazz); - } - - @Override - public Result lookup(Template template) { - return l.lookup(template); - } - - @Override - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - public boolean equals(Object obj) { - if (set != null) { - cnt[0]++; - pl.setLookups(set); - } - return super.equals(obj); - } - - @Override - public int hashCode() { - int hash = 3; - return hash; - } - } - - Result res = pl.lookupResult(String.class); - assertEquals(Collections.EMPTY_LIST, res.allItems()); - - L[] old = { new L("A"), new L("B") }; - L[] now = { new L("C") }; - - pl.setLookups(old); - cnt[0] = 0; - - old[0].set = new L[0]; - pl.setLookups(now); - - assertEquals("No call to equals", 0, cnt[0]); - - assertEquals("Still assigned to C", Collections.singletonList("C"), res.allInstances()); - } - - public void testArrayIndexWithAddRemoveListenerAsInIssue119292() throws Exception { - final ProxyLookup pl = new ProxyLookup(); - final int[] cnt = { 0 }; - - class L extends Lookup { - L[] set; - Lookup l; - - public L(String s) { - l = Lookups.singleton(s); - } - - @Override - public T lookup(Class clazz) { - return l.lookup(clazz); - } - - @Override - public Result lookup(Template template) { - Result r = l.lookup(template); - return new R(r); - } - - final class R extends Result { - private Result delegate; - - public R(Result delegate) { - this.delegate = delegate; - } - - @Override - public void addLookupListener(LookupListener l) { - cnt[0]++; - if (set != null) { - pl.setLookups(set); - } - delegate.addLookupListener(l); - } - - @Override - public void removeLookupListener(LookupListener l) { - cnt[0]++; - if (set != null) { - pl.setLookups(set); - } - delegate.removeLookupListener(l); - } - - @Override - public Collection allInstances() { - return delegate.allInstances(); - } - } - } - - Result res = pl.lookupResult(String.class); - assertEquals(Collections.EMPTY_LIST, res.allItems()); - - L[] old = { new L("A"), new L("B") }; - L[] now = { new L("C") }; - - pl.setLookups(old); - cnt[0] = 0; - - old[0].set = new L[0]; - pl.setLookups(now); - - if (cnt[0] == 0) { - fail("There should be calls to listeners"); - } - - assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances()); - } - - - public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception { - final ProxyLookup pl = new ProxyLookup(); - final int[] cnt = { 0 }; - - class L extends Lookup { - L[] set; - Lookup l; - Collection res; - - public L(String s) { - l = Lookups.singleton(s); - } - - @Override - public T lookup(Class clazz) { - return l.lookup(clazz); - } - - @Override - public Result lookup(Template template) { - cnt[0]++; - if (set != null) { - pl.setLookups(set); - res = pl.lookupAll(Serializable.class); - } - Result r = l.lookup(template); - return r; - } - } - - L[] now = { new L("A"), new L("B") }; - L[] old = { new L("C") }; - pl.setLookups(old); - old[0].set = now; - - Result res = pl.lookupResult(String.class); - assertEquals("New items visible", 2, res.allItems().size()); - - - pl.setLookups(new L("X"), new L("Y"), new L("Z")); - } - - public void testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679() throws Exception { - final ProxyLookup pl = new ProxyLookup(); - final int[] cnt = { 0 }; - - class L extends Lookup { - L[] set; - Lookup l; - Collection res; - - public L(String s) { - l = Lookups.singleton(s); - } - - @Override - public T lookup(Class clazz) { - return l.lookup(clazz); - } - - @Override - public Result lookup(Template template) { - cnt[0]++; - if (set != null) { - pl.setLookups(set); - res = pl.lookupAll(Serializable.class); - } - Result r = l.lookup(template); - return r; - } - } - - L dupl = new L("A"); - L[] now = { dupl }; - L[] old = { new L("C") }; - pl.setLookups(old); - old[0].set = now; - - Result res = pl.lookupResult(String.class); - assertEquals("New items visible", 1, res.allItems().size()); - - - pl.setLookups(old); - } -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/apichanges.xml --- a/openide.util/apichanges.xml Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1492 +0,0 @@ - - - - - - Utilities API - XML API - Actions API - - - - - Action SPI interfaces added - - - - - -

- Added some internal SPI interfaces. -

-
- - - -
- - - NbPreferences.Provider added - - - - - -

- Added an internal SPI interface. -

-
- - -
- - - Lookup API extracted - - - - -

- Runtime compatibility remains, compile time compatibility is - mostly preserved too. It is however recommended to upgrade - dependencies of your modules. Try running - ant fix-dependencies in your Ant module. -

-
- -

- Lookup - and its associated interfaces are now available as a - separate module. -

-
- -
- - - Added @URLStreamHandlerRegistration - - - - -

- Modules registering URLStreamHandlerFactorys into - global lookup will still work but are advised to switch to this - annotation, which is both easier to use and more efficient. -

-
- -

- Introduced an annotation to register URL protocols. -

-
- - -
- - - ImageUtilities.createDisabledIcon and ImageUtilities.createDisabledImage added. - - - - - -

- ImageUtilities.createDisabledIcon now can be used - to create low color saturation icon for disabled buttons. Also - ImageUtilities.createDisabledImage was added. -

-
- - -
- - - NbBundle.getMessage can take arbitrarily many format arguments - - - - - -

- NbBundle.getMessage now has a varargs overload that - permits you to specify four or more format arguments without - explicitly constructing an array. -

-
- -
- - - Copied API from project.ant for EditableProperties. - - - - - -

- EditableProperties now available in Utilities API - so it can be used more broadly. -

-
- - -
- - - Added way to request that the platform restart. - - - - - -

- Can now use LifecycleManager.markForRestart to cause - the application to restart after exiting. Formerly needed to - create special files in the userdir or use similar tricks. -

-
- - -
- - - Added constructor RequestProcessor(String name, int throughput, boolean interruptThread, boolean enableStackTraces) - - - - - -

- Newly added constructor allows to disable (slow) filling stack traces before posting each task. -

-
- - -
- - - Added loadImageIcon(String resource, boolean localized) - - - - - -

- Convenient method for loading icons. -

-
- - -
- - - Added keyToString(KeyStroke stroke, boolean portable) - - - - - -

- keyToString(KeyStroke stroke, boolean portable) - provides cross-platform compitable keystroke textual representation - instead of hardcoding Ctrl, Meta or Alt key. -

-
- - -
- - - Added OS_OPENBSD and OS_UNIX_OTHER fields - - - - - -

- Added a new Utilities.OS_OPENBSD and OS_UNIX_OTHER - fields. Deprecated OS_WINDOWS_MASK and OS_UNIX_MASK. -

-
- - -
- - - Added OS_WINVISTA field - - - - - -

- Added a new Utilities.OS_WINVISTA field to be able - to recognize Windows Vista operating system. -

-
- - -
- - - Added XMLUtil.validate - - - - - -

- Added a new method to validate XML documents against schemas. -

-
- - -
- - - RequestProcessor implements Executor interface - - - - - -

- In order to align RequestProcessor closer to standard - Java 5 concurrency utilities, the class now implements - Executor - interfaces and its execute(Runnable) method. -

-
- - -
- - - ImageUtilities class (with additional methods) was created as - replacement for "image methods" in Utilities. - - - - - -

- Image methods were separated to ImageUtilities - (renamed IconManager) as replacement for methods in Utilities. - There are some additional methods for image tool tips manipulation. -

-

- New methods for tool tips manipulation: - Image assignToolTipToImage(Image image, String text); - String getImageToolTip(Image image); - Image addToolTipToImage(Image image, String text); -

-

- New method for conversion from Image to Icon: - Icon image2Icon(Image image); -

-

- "Moved" methods from Utilities: - Image icon2Image(Icon icon); - Image loadImage(String resourceID); - Image loadImage(String resource, boolean localized); - Image mergeImages(Image image1, Image image2, int x, int y); -

-
- - - -
- - - Mutex made pluggable - - - - - -

- Added new constructor - Mutex(Privileged, Executor) - that allows creators of the mutex to intercept and wrap all actions running - inside the mutex with custom code. -

-
- - -
- - - Obsolete method Utilities.isLargeFrameIcons deprecated. - - - - - -

- Javadoc says: Test whether the operating system supports icons on frames (windows). - But window system used this method to decide if small 16x16 or bigger 32x32 icon - should be used for frame (main window). So usage and Javadoc is inconsistent. - All OS support small icon in frame. From JDK 6 it is possible to set multiple size - icons for frame so OS WM selects appropriate size. - I removed useless usage of this method from window system code and this method is - not used elsewhere. -

-
- - -
- - - - Added ChangeSupport - - - - - -

- Added a ChangeSupport class to simplify - the management of ChangeListeners and the - firing of ChangeEvents. -

-
- - -
- - - - Added Utilities.isMac() method - - - - - -

- Added a Utilities.isMac() method for checking - if current platform is Mac. -

-
- - -
- - - - Added Parameters - - - - - -

- Added a Parameters class for checking the - values of method parameters. -

-
- - -
- - - - Added NbCollections.iterable(...) methods - - - - - -

- Added two new methods to make enhanced for-loops easier to use - with legacy APIs returning Iterator or Enumeration. -

-
- - -
- - - - Added NbPreferences.forModule(Class cls) and - NbPreferences.root() methods as static factory methods - for getting preference node from NetBeans preference tree. - - - - - -

- NetBeans preference tree is provided by NetBeans implementation of preferences - which uses userdir as a storage. Both newly added methods return - preferences node from NetBeans preference tree. - Method NbPreferences.root() returns root preference - node. - Method NbPreferences.forModule(Class cls) returns - preference node whose - path depends whether class provided as a parameter - was loaded as a part of any module or not. If so, then absolute path corresponds to slashified - code name base of module. If not, then absolute path corresponds to class's package. - See document - Preferences in NetBeans - to learn more about preferences in NetBeans. -

-
- - -
- - - - Added Utilities.icon2Image method to perform conversion from Icon to Image - - - - - -

- Conversion from Icon to Image is done - at various places and newly introduced method avoids the need to - duplicate the same code. -

-
- - -
- - - - Added Exceptions class as a replacement for ErrorManager - - - - - -

- ErrorManager is now deprecated and its replacement - is either Logger - or Exceptions. -

-
- - -
- - - - Added NbCollections and Union2 - - - - - -

- Added two new classes useful for transitioning to JDK 5 generics. -

-
- - - -
- - - - Do not use ErrorManager for logging - - - - - - ErrorManager - is no longer the recommended way to do logging in NetBeans based - application. Instead NetBeans now fully support logging two JDK's - standard Logger. - See the - NetBeans logging guide - to learn the best practises for logging in NetBeans. -
- ErrorManager - is still kept around for annotating exceptions with localized - messages and advanced manipulation and its behaviour is fully - backward compatible. However modules are adviced to migrate to - logging whereever - possible. -
- To migrate your modules you can install Jackpot modules from - autoupdate (if they are not yet part of your IDE) and apply - precreate - javapot error manager rule. -
- There is one possible incompatibility from end user point of view. - The way to enable logging for certain components when - running inside the whole NetBeans container has changed: - If there is - Logger or - ErrorManager - named org.mymodule.MyComponent then the correct way - to turn the logging is now to invoke NetBeans with - -J-Dorg.mymodule.MyComponent.level=100 - (where the possible constants are taken form - a JDK's definition of level). - There is however a certain benefit in this change, the value - of the property (like org.mymodule.MyComponent.level) - can be changed during runtime and thus the logging can be - enabled or disabled dynamically (after changing the value, it is - necessary to call - LogManager.readConfiguration()). -
- - -
- - - Ability to create finished RequestProcessor task - - - - - - RequestProcessor.create(Runnable, boolean) - has been added to allow creation of - Task - that has not executed its runnable yet, but looks like it is finished. - - - - - - - - DynamicMenuContent interface added - - - - - - In order to support MacOSX top menus and to fix problems with deprecated JInlineMenu, this new - interface was added that allows to handle dynamic content in -Presenter.Menu - and Presenter.Popup. - If the instance returned by Presenter.Menu/Popup is an instance of -DynamicMenuContent, it's methods are - consulted when creating/updating the menu. - - - - - - - - - - Support for interruption of RequestProcessor tasks - - - - - - When one calls RequestProcessor.Task.cancel(), - the running thread gets interrupted if the - - RequestProcessor(string, int, boolean) - - constructor is used. - There always was a way how to cancel not yet running Task, - but if the task was already running, one was out of luck. Since now - the thread running the task is interrupted and the Runnable can check - for that and terminate its execution sooner. In the runnable one shall - check for thread interruption and - if true, return immediatelly as in this example: -
-public void run () {
-  while (veryLongTimeLook) {
-    doAPieceOfIt ();
-
-    if (Thread.interrupted ()) return;
-  }
-}
-
-
- - -
- - - Can create textual icons for actions - - - - - iconResource may now return null to indicate no - icon. getIcon(true) may be used to get an icon created from - the label if there is no icon specified. - - - - - - - SystemAction refers to Icon rather than ImageIcon - - - - - First broken, later restored binary compatibility in trunk and - boston. Any code explicitly using this calls before may break - (source code may be compatible in many cases; binary compatibility has - been preserved). These calls were known to be used only for - Actions to create presenters; normal code which constructs - SystemActions and implements iconResource should - be unaffected. Actions using the "grouping action" template should check - their getMenuPresenter method which may be - binary-incompatible; it is easy to replace the code with safer code such - as: -
-// ....
-
-private static Icon icon = null;
-// ....
-
-public JMenuItem getMenuPresenter() {
-    JMenu menu = new JMenu(getName ());
-    if (icon == null) {
-        icon = new ImageIcon(MyAction.class.getResource(iconResource()));
-    }
-    menu.setIcon(icon);
-    // ....
-
-
- - getIcon and setIcon now use the interface - Icon rather than the particular implementation - ImageIcon. This corrects an API bug (excessive specificity). - - -
- - - New Actions system - part I. - - - - - - -

- Introduction of new action system, which generally means - move from usage of SystemAction to Action instances. - That document also focuses on declarative actions - usage which is not subject of current change, it will be part of later changes. -

-
- - - - -
- - - - New method task.waitFinished(timeout) added - - - - - -

It is not possible to wait for a limited amount of time for - completion of any task. The RequestProcessor.Task - version is optimized, the Task version ensures that - the sematics will be compatible for all subclasses, even they did - not know about the method at all. -

-
- - - -
- - - Added field OS_FREEBSD to Utilities - - - - - - -

FreeBSD was not recognized as Unix OS. Utilities has been - enlarged with new field OS_FREEBSD, part of OS Unix mask. Utilities.isUnix() - now returns true for applications run on FreeBSD. -

-
- -
- - - Added Mutex.isReadAccess() and Mutex.isWriteAcess() - - - - - - - A thread can now check whether read or write access on a Mutex - has already been - granted to it and use it to decide whether it is safe to perform - certain operations or delay them. - - - - - - - Added SharedClassObject.reset method to allow subclasses to implement reset correctly - - - - - - The new SharedClassObject.reset method is called - by the infrastructure in moments when an original (at the time - of start) state of an option or any other SharedClassObject - is requested. Interested subclasses are free to implement any kind of clean - they need. The SystemOption provides a default - implementation based on fired property changed events, so - its correctly written subclasses do not need - to do anything. - - - - - - - enum package deprecated and replaced by Enumerations factory class - - - - - - enum is a keyword in JDK 1.5 and as such it should not be used. - That is the reason why we had to deprecated our - org.openide.util.enum package. We are providing - replacements of the original classes in form of factory methods - org.openide.util.Enumerations. - - - - - - - Support for complicated listeners - - - - - - Improved support for hierarchic listeners (aka NamingListener vs. ObjectChangeListener from - javax.naming.event package). - - - - - - - Global action context as Lookup - - - - - - - As part of the work on separation of openide.jar into smaller parts - a new interface ContextGlobalProvider and new method - in utilities Utilities.actionsGlobalContext() had to be - added in order to separate the implementation of actions like - CallbackSystemAction and NodeAction from - their dependency on window system. - - - - - - - - Old WeakListener replaced by WeakListeners class - - - - - -

- As part of the work on separation of openide.jar into smaller parts - the WeakListener had to be deprecated as it referenced too - many classes around and replaced by more general WeakListeners - factory class that provides a generic create method and - specialized factory methods just for JDK own interfaces. -

-

- Also few factory methods were spread into appropriate packages like - FileUtil.weakFileChangeListener and - NodeOp.weakNodeListener. -

-
- - -
- - - New method to find HelpCtx - - - - - - A new method for finding HelpCtx (HelpCtx.findHelp(Object)) - has been added to replace - the old InstanceSupport.findHelp that has been - separated out from the openide.jar. - - - - - - - Retrofit of interface Cancellable into RequestProcessor.Task - - - - - - RequestProcessor.Task was made to implement util.Cancellable interface. - No change of implementation at all, RP.Task already had method from - interface implemented, this is just a logical retrofit. - - - - - - Support for asynchronous init of UI components - - - - - -

- Performance related API addition, allows clients to write asynchronous - initialization of UI components easily by providing AsyncGUIJob - implementation. Also introduced Cancellable ability. - Utilities.attachInitJob couples init job with target - UI component. -

-
- - - - -
- - - org.openide.util.Utilities.createProgressCursor added - - - - - - Method java.awt.Cursor createProgressCursor(java.awt.Component comp) was - added into Utilities class. Method creates mouse cursor suitable for - components which are busy, but still reacts to the input events. (don't - block UI). - - - - - - Added interface HelpCtx.Provider - - - - - - An interface HelpCtx.Provider with one method getHelpCtx was added - and the logic in HelpCtx.findHelp and InstanceSupport.findHelp - was extended to take this interface into accout. - Various classes with existing getHelpCtx method were retrofitted - to implement this interface. - - - - - - - - - - Can load localized cached images - - - - - - Added method Utilities.loadImage(String, boolean) - which works like Utilities.loadImage(String) except - that it will search for localized images. Also - SystemAction.getIcon() will load a localized image now - if there is one. - - - - - - - - Utilities.activeReferenceQueue() - - - - - - Active java.util.ref.ReferenceQueue that polls for all - enqued instances (that should implement Runnable) and - invokes their run method to do actual cleanup. - - - - - - - Deprecation of parts of MouseUtils.PopupMenuAdapter - - - - - - Constructor MouseUtils.PopupMenuAdapter(int) and public static field - DEFAULT_THESHOLD are now obsoleted, performs no action. - PopupMenuAdapter now delegates to isPopupTrigger crossplatform call, - should be constructed via default constructor. - - - - - -Utilities.toFile and toURL added - - - - - Existing code which uses the JDK 1.3 method File.toURL should be - examined, as it may be better to call Utilities.toURL. - Similarly, code which gets the path from a URL and calls the File - constructor may need to be changed to call Utilities.toFile. - Such changes should improve robustness of code when used in strangely - named directories. - - - Two new utility methods were added which permit easy interconversion between - files and URLs using the file protocol. This task is easy and - safe under JDK 1.4, yet JDK 1.3 lacks a single call to do these tasks which - will handle unusual characters in file names, especially hash marks. The - utility methods use the JDK 1.4 variants when possible, else use specially - coded versions of the JDK 1.3 variants which handle hash marks. - - - - - - - Added RequestProcessor.getDefault(), deprecated static methods in RequestProcessor - - - - - Sharing of singlethreaded - RequestProcessor.DEFAULT - through the static methods is inherently deadlock-prone, - so the methods are deprecated and their usage should phase out - in the favor of using private RequestProcessors - or the shared multithreaded instance available through the new - static method RequestProcessor.getDefault(). - - - - - - Added helper methods to aid module developers to write code which works correctly with multiple monitors - - - - - - The added methods are -
-public static Rectangle getUsableScreenBounds();
-public static Rectangle getUsableScreenBounds(GraphicsConfiguration gconf);
-public static Rectangle findCenterBounds(Dimension componentSize);
-
- One should use these methods instead of calling - Toolkit.getScreenSize(). For the same reason - Utilities.getScreenSize() is now deprecated. -
- - -
- - - Added accessibility method ErrorManager.getDefault () that always returns non-null values - - - - - -

- This method allows independent libraries (nodes, filesystems, utilities) to use the ErrorManager without - testing if it is really present. Just call ErrorManager.getDefault () and you can be sure - that a valid instance will be returned. -

-

- Also TopManager.getErrorManager is no longer useful (see change) and is now deprecated. - It is also not abstract as it just delegates. - notifyException is similarly deprecated. -

-
- - -
- - - -ErrorManager.isLoggable added - - - - isLoggable(int severity) added to ErrorManager. - - - - - - Logging and hierarchy support added to ErrorManager - - - - - getInstance(String name), log(int severity, String s), and - log(String s) added to ErrorManager. - - - - - - Can register entity resolvers - - - Subsequently deprecated on by - -EntityCatalog -. - - - addEntityResolver and removeEntityResolver - added. These methods allow a user to develop own implementation of - functionality similar to registerCatalogEntry. E.g. a user - can register EntityResolver that reads data from persistent - catalog avoiding bunch of calls to the register method in module - restore code. - - - - - - Updated DOM to level 2 and added document writability - - - - Any code implementing DOM interfaces could be broken by the level 2 - interfaces. Clients of the DOM API should be unaffected. - - -
    -
  • All level 1 Documents interfaces became level 2 ones.
  • -
  • Deprecated write(Document, Writer) -

    A conflict between encoding declared in document and - actual Writer encoding can cause data loss. Suitable - just for UTF-8 and UTF-16 writers. -

    -
  • -
  • introduced write(Document, OutputStream, String encoding) -

    - The write method is supposed to be used as an implementation - independent way for writing DOM documents until self-writable - documents specification will be introduced. The self-writability - is considered to be a part of DOM level 3 specs. -

    -

    - Nowadays it is implemented that it can handle following DOM implementations: -

    -
      -
    • Crimson
    • -
    • JAXP 1.0 reference implementation
    • -
    • All others using Apache's serializers if available.
    • -
    -
  • -
-
- -
- - - Improved method for topological sort - - - - - - The method Utilities.topologicalSort was added. It should be - faster and probably more robust than the older partialSort - method, which required a Comparator; the new method requires - a list of ordering constraints, which should be O(n + m) - rather than O(n2) (where n is the number of - nodes to sort and m the number of edges). If the graph is - not a DAG a TopologicalSortException is thrown containing - description of unsortable parts of the graph and the best partitial sort - that fullfils as much of ordering constraints as possible. These - information can be used for error reporting and recovery. - - - - - - - - Moved XML static methods into separate inner class - - - - XMLDataObject.Util itself deprecated on - in favor of - -XMLUtil -. - - -
    -
  • - Deprecated all static: write()s, parse()s, - createDocument(), createInputSource() and - createParser()s methods. -
  • -
  • - Introduced public static inner class named Util providing - utility methods replacing deprecated ones. -
  • -
-
- -
- - - Permit privileged access to mutexes to avoid inner classes - - - - - Added a new inner class and a constructor that takes an instance of that - inner class as a parameter. The inner class is Privileged. - Through its public methods one can enter internal states of the - Mutex to which it was passed. - - - - - - More flexibility in controlling running of tasks - - - - - Task has new protected constructor for subclasses and - methods notifyRunning () and also non-final version of - waitFinished (). - - - - - - - ErrorManager.isNotifiable added - - - - - Existing code which assumes (incorrectly) that isLoggable - can be used for this purpose, or which calls notify at a low - level such as INFORMATIONAL without first checking - isNotifiable for efficiency, should be revised. - - - The method ErrorManager.isNotifiable was added to capture - the fact that an error manager implementation might be more aggressive - about displaying stack traces than log messages. - - - - - - - - ServiceType.createClone added - - Subclasses are encouraged to implement Cloneable. - - public final ServiceType createClone() added. - - - - - - Icon & image cache manager added - - - - Loading icons and images can be done through - Utilities.loadImage() that uses cache to avoid duplicate - loading of images. mergeImages uses the cache, too, for the - results of merge. - - - - - - Updated DEC -> Compaq OS names - - - - Operating system OS_DEC changed to OS_TRU64, - and added OS_VMS. - - - - - - Proper break iterators used when wrapping text strings - - - Deprecated version first removed, later re-added with deprecation in the - trunk. - - - Added method wrapString which uses - BreakIterator instead of a flag and a heuristic solution. - wrapString(String,int,boolean,boolean) deprecated. - - - - - - Support for merging icons added - - - - Added method mergeImages(Image image1, Image image2, int x, int - y) for merging images. - - - - - - Can get a list of localizing suffixes - - - - - getLocalizingSuffixes added. - - - - - - Can find localized variants of extensionless resources - - - - - getLocalizedFile now accepts null extensions - to suppress the addition of a dot to the resource name. - - - - - - Added search for branded variants as part of locale lookup - - - - - Added methods getBranding and setBranding. - Normally these should only be called by the core implementation during - startup, not module authors. All methods to look up localized objects - may now also search for branded variants, if applicable. - - - - - - Classloader finder for NbBundle is obsolete - - - First removed, later re-added but deprecated in trunk and - boston. No one outside of NbBundle and the - core implementation should have been using these classes to begin with. - - - NbBundle.ClassLoaderFinder and - NbBundle.setClassLoaderFinder have been deprecated; they - were quite obsolete. - - - - - - Special exception thrown to request interaction with user - - - - Added the first revision. This exception is thrown when a process is - about to perform some action that requires user confirmation. - - - - - - -SafeException is a FoldingIOException - - - - - Now extends FoldingIOException, meaning that it should - delegate the detail message, etc. to the original. - - - - - - Independent XML API created - - - - - XMLUtil utility class introduced. The class provides set of - static methods useful for XML processing. EntityCatalog - class introduced. It provides access to entity mapping registrations - provided by installed modules. - - - - - - - - XML attribute and hexadecimal utilities added - - - - - toAttribute(String, char, boolean), toContent(String, - boolean), toHex(byte[], int, int) and - fromHex(char[], int, int) methods added. - - - - - - XML attribute and hexadecimal utilities modified - - - - The original versions of these methods were not in any public release. - - - toAttribute(String, char, boolean) method replaced by - toAttributeValue(String) - and - toContent(String, boolean) method replaced by - toElementContent(String). These new simplified - signatures and particular semantics should cover 99% usage of - previous ones. See the original additions. - - - - -
- - -Change History for the Utilities API - - - - -

Introduction

-

What do the Dates Mean?

-

The supplied dates indicate when the API change was made, on the CVS -trunk. From this you can generally tell whether the change should be -present in a given build or not; for trunk builds, simply whether it -was made before or after the change; for builds on a stabilization -branch, whether the branch was made before or after the given date. In -some cases corresponding API changes have been made both in the trunk -and in an in-progress stabilization branch, if they were needed for a -bug fix; this ought to be marked in this list.

-
    -
  • The release41 branch was made on Apr 03 '05 for use in the NetBeans 4.1 release. -Specification versions: 6.0 begins after this point.
  • -
  • The release40 branch was made on Nov 01 '04 for use in the NetBeans 4.0 release. -Specification versions: 5.0 begins after this point.
  • -
-
- -
-

@FOOTER@

- -
-
diff -r b3ae88304dd0 -r a2947558c966 openide.util/manifest.mf --- a/openide.util/manifest.mf Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: org.openide.util -OpenIDE-Module-Localizing-Bundle: org/openide/util/Bundle.properties -OpenIDE-Module-Specification-Version: 8.1 - diff -r b3ae88304dd0 -r a2947558c966 openide.util/nbproject/project.properties --- a/openide.util/nbproject/project.properties Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. -# -# Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. -# -# The contents of this file are subject to the terms of either the GNU -# General Public License Version 2 only ("GPL") or the Common -# Development and Distribution License("CDDL") (collectively, the -# "License"). You may not use this file except in compliance with the -# License. You can obtain a copy of the License at -# http://www.netbeans.org/cddl-gplv2.html -# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the -# specific language governing permissions and limitations under the -# License. When distributing the software, include this License Header -# Notice in each file and include the License file at -# nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun in the GPL Version 2 section of the License file that -# accompanied this code. If applicable, add the following below the -# License Header, with the fields enclosed by brackets [] replaced by -# your own identifying information: -# "Portions Copyrighted [year] [name of copyright owner]" -# -# Contributor(s): -# -# The Original Software is NetBeans. The Initial Developer of the Original -# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun -# Microsystems, Inc. All Rights Reserved. -# -# If you wish your version of this file to be governed by only the CDDL -# or only the GPL Version 2, indicate your decision by adding -# "[Contributor] elects to include this software in this distribution -# under the [CDDL or GPL Version 2] license." If you do not indicate a -# single choice of license, a recipient has the option to distribute -# your version of this file under either the CDDL, the GPL Version 2 or -# to extend the choice of license to its licensees as provided above. -# However, if you add GPL Version 2 code and therefore, elected the GPL -# Version 2 license, then the option applies only if the new code is -# made subject to such option by the copyright holder. - -javac.compilerargs=-Xlint -Xlint:-serial -javac.source=1.6 -module.jar.dir=lib - - -# For XMLSerializer, needed for XMLUtil.write to work w/ namespaces under JDK 1.4: - -javadoc.main.page=org/openide/util/doc-files/api.html -javadoc.arch=${basedir}/arch.xml -javadoc.apichanges=${basedir}/apichanges.xml diff -r b3ae88304dd0 -r a2947558c966 openide.util/nbproject/project.xml --- a/openide.util/nbproject/project.xml Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ - - - - org.netbeans.modules.apisupport.project - - - org.openide.util - - - org.openide.util.lookup - - - - 8.1 - - - - - - unit - - org.netbeans.libs.junit4 - - - - org.netbeans.modules.nbjunit - - - - - org.openide.util.lookup - - - - - - - org.openide - org.openide.util - org.openide.util.actions - org.openide.util.datatransfer - org.openide.util.io - org.openide.xml - - - - diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/netbeans/modules/openide/util/URLStreamHandlerRegistrationProcessor.java --- a/openide.util/src/org/netbeans/modules/openide/util/URLStreamHandlerRegistrationProcessor.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2009 Sun Microsystems, Inc. - */ - -package org.netbeans.modules.openide.util; - -import java.net.URLStreamHandler; -import java.util.Collections; -import java.util.Set; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; -import org.openide.util.URLStreamHandlerRegistration; -import org.openide.util.lookup.implspi.AbstractServiceProviderProcessor; - -@SupportedSourceVersion(SourceVersion.RELEASE_6) -public class URLStreamHandlerRegistrationProcessor extends AbstractServiceProviderProcessor { - - public @Override Set getSupportedAnnotationTypes() { - return Collections.singleton(URLStreamHandlerRegistration.class.getCanonicalName()); - } - - public static final String REGISTRATION_PREFIX = "URLStreamHandler/"; // NOI18N - - /** public for ServiceLoader */ - public URLStreamHandlerRegistrationProcessor() {} - - protected boolean handleProcess(Set annotations, RoundEnvironment roundEnv) { - for (Element el : roundEnv.getElementsAnnotatedWith(URLStreamHandlerRegistration.class)) { - TypeElement clazz = (TypeElement) el; - URLStreamHandlerRegistration r = clazz.getAnnotation(URLStreamHandlerRegistration.class); - TypeMirror type = processingEnv.getTypeUtils().getDeclaredType( - processingEnv.getElementUtils().getTypeElement(URLStreamHandler.class.getName())); - for (String protocol : r.protocol()) { - register(clazz, URLStreamHandlerRegistration.class, type, - REGISTRATION_PREFIX + protocol, r.position(), new String[0]); - } - } - return true; - } - -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/Enumerations.java --- a/openide.util/src/org/openide/util/Enumerations.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,601 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Set; - -/** - * Factory methods for various types of {@link Enumeration}. - * Allows composition of existing enumerations, filtering their contents, and/or modifying them. - * All of this is designed to be done lazily, i.e. elements created on demand. - * @since 4.37 - * @author Jaroslav Tulach - * @see NbCollections#checkedEnumerationByFilter - * @see NbCollections#iterable(Enumeration) - */ -public final class Enumerations extends Object { - /** No instances */ - private Enumerations() { - } - - /** - * An empty enumeration. - * Always returns false from - * empty().hasMoreElements() and throws NoSuchElementException - * from empty().nextElement(). - * @return the enumeration - */ - public static final Enumeration empty() { - Collection emptyL = Collections.emptyList(); - return Collections.enumeration(emptyL); - } - - /** - * Creates an enumeration with one element. - * @param obj the element to be present in the enumeration. - * @return enumeration - */ - public static Enumeration singleton(T obj) { - return Collections.enumeration(Collections.singleton(obj)); - } - - /** - * Concatenates the content of two enumerations into one. - * Until the - * end of en1 is reached its elements are being served. - * As soon as the en1 has no more elements, the content - * of en2 is being returned. - * - * @param en1 first enumeration - * @param en2 second enumeration - * @return enumeration - */ - public static Enumeration concat(Enumeration en1, Enumeration en2) { - ArrayList> two = new ArrayList>(); - two.add(en1); - two.add(en2); - return new SeqEn(Collections.enumeration(two)); - } - - /** - * Concatenates the content of many enumerations. - * The input value - * is enumeration of Enumeration elements and the result is composed - * all their content. Each of the provided enumeration is fully read - * and their content returned before the next enumeration is asked for - * their elements. - * - * @param enumOfEnums Enumeration of Enumeration elements - * @return enumeration - */ - public static Enumeration concat(Enumeration> enumOfEnums) { - return new SeqEn(enumOfEnums); - } - - /** - * Filters the input enumeration to new one that should contain - * each of the provided elements just once. - * The elements are compared - * using their default equals and hashCode methods. - * - * @param en enumeration to filter - * @return enumeration without duplicated items - */ - public static Enumeration removeDuplicates(Enumeration en) { - class RDupls implements Processor { - private Set set = new HashSet(); - - public T process(T o, Collection nothing) { - return set.add(o) ? o : null; - } - } - - return filter(en, new RDupls()); - } - - /** - * Returns an enumeration that iterates over provided array. - * @param arr the array of object - * @return enumeration of those objects - */ - public static Enumeration array(T... arr) { - return Collections.enumeration(Arrays.asList(arr)); - } - - /** - * Removes all nulls from the input enumeration. - * @param en enumeration that can contain nulls - * @return new enumeration without null values - */ - public static Enumeration removeNulls(Enumeration en) { - return filter(en, new RNulls()); - } - - /** - * For each element of the input enumeration en asks the - * {@link Processor} to provide a replacement. - * The toAdd argument of the processor is always null. - *

- * Example to convert any objects into strings: - *

-     * Processor convertToString = new Processor() {
-     *     public Object process(Object obj, Collection alwaysNull) {
-     *         return obj.toString(); // converts to string
-     *     }
-     * };
-     * Enumeration strings = Enumerations.convert(elems, convertToString);
-     * 
- * - * @param en enumeration of any objects - * @param processor a callback processor for the elements (its toAdd arguments is always null) - * @return new enumeration where all elements has been processed - */ - public static Enumeration convert(Enumeration en, Processor processor) { - return new AltEn(en, processor); - } - - /** - * Filters some elements out from the input enumeration. - * Just make the - * {@link Processor} return null. Please notice the toAdd - * argument of the processor is always null. - *

- * Example to remove all objects that are not strings: - *

-     * Processor onlyString = new Processor() {
-     *     public Object process(Object obj, Collection alwaysNull) {
-     *         if (obj instanceof String) {
-     *             return obj;
-     *         } else {
-     *             return null;
-     *         }
-     *     }
-     * };
-     * Enumeration strings = Enumerations.filter(elems, onlyString);
-     * 
- * - * @param en enumeration of any objects - * @param filter a callback processor for the elements (its toAdd arguments is always null) - * @return new enumeration which does not include non-processed (returned null from processor) elements - * @see NbCollections#checkedEnumerationByFilter - */ - public static Enumeration filter(Enumeration en, Processor filter) { - Parameters.notNull("en", en); - Parameters.notNull("filter", filter); - return new FilEn(en, filter); - } - - /** - * Support for breadth-first enumerating. - * Before any element is returned - * for the resulting enumeration it is processed in the {@link Processor} and - * the processor is allowed to modify it and also add additional elements - * at the (current) end of the queue by calling toAdd.add - * or toAdd.addAll. No other methods can be called on the - * provided toAdd collection. - *

- * Example of doing breadth-first walk through a tree: - *

-     * Processor queueSubnodes = new Processor() {
-     *     public Object process(Object obj, Collection toAdd) {
-     *         Node n = (Node)obj;
-     *         toAdd.addAll (n.getChildrenList());
-     *         return n;
-     *     }
-     * };
-     * Enumeration strings = Enumerations.queue(elems, queueSubnodes);
-     * 
- * - * @param en initial content of the resulting enumeration - * @param filter the processor that is called for each element and can - * add and addAll elements to its toAdd Collection argument and - * also change the value to be returned - * @return enumeration with the initial and queued content (it can contain - * null if the filter returned null from its - * {@link Processor#process} method. - */ - public static Enumeration queue(Enumeration en, Processor filter) { - QEn q = new QEn(filter); - - while (en.hasMoreElements()) { - q.put(en.nextElement()); - } - - return q; - } - - /** - * Processor interface that can filter out objects from the enumeration, - * change them or add aditional objects to the end of the current enumeration. - */ - public static interface Processor { - /** @param original the object that is going to be returned from the enumeration right now - * @return a replacement for this object - * @param toAdd can be non-null if one can add new objects at the end of the enumeration - */ - public R process(T original, Collection toAdd); - } - - /** Altering enumeration implementation */ - private static final class AltEn extends Object implements Enumeration { - /** enumeration to filter */ - private Enumeration en; - - /** map to alter */ - private Processor process; - - /** - * @param en enumeration to filter - */ - public AltEn(Enumeration en, Processor process) { - this.en = en; - this.process = process; - } - - /** @return true if there is more elements in the enumeration - */ - public boolean hasMoreElements() { - return en.hasMoreElements(); - } - - /** @return next object in the enumeration - * @exception NoSuchElementException can be thrown if there is no next object - * in the enumeration - */ - public R nextElement() { - return process.process(en.nextElement(), null); - } - } - // end of AltEn - - /** Sequence of enumerations */ - private static final class SeqEn extends Object implements Enumeration { - /** enumeration of Enumerations */ - private Enumeration> en; - - /** current enumeration */ - private Enumeration current; - - /** is {@link #current} up-to-date and has more elements? - * The combination current == null and - * checked == true means there are no more elements - * in this enumeration. - */ - private boolean checked = false; - - /** Constructs new enumeration from already existing. The elements - * of en should be also enumerations. The resulting - * enumeration contains elements of such enumerations. - * - * @param en enumeration of Enumerations that should be sequenced - */ - public SeqEn(Enumeration> en) { - this.en = en; - } - - /** Ensures that current enumeration is set. If there aren't more - * elements in the Enumerations, sets the field current to null. - */ - private void ensureCurrent() { - while ((current == null) || !current.hasMoreElements()) { - if (en.hasMoreElements()) { - current = en.nextElement(); - } else { - // no next valid enumeration - current = null; - - return; - } - } - } - - /** @return true if we have more elements */ - public boolean hasMoreElements() { - if (!checked) { - ensureCurrent(); - checked = true; - } - - return current != null; - } - - /** @return next element - * @exception NoSuchElementException if there is no next element - */ - public T nextElement() { - if (!checked) { - ensureCurrent(); - } - - if (current != null) { - checked = false; - - return current.nextElement(); - } else { - checked = true; - throw new java.util.NoSuchElementException(); - } - } - } - // end of SeqEn - - /** QueueEnumeration - */ - private static class QEn extends Object implements Enumeration { - /** next object to be returned */ - private ListItem next = null; - - /** last object in the queue */ - private ListItem last = null; - - /** processor to use */ - private Processor processor; - - public QEn(Processor p) { - this.processor = p; - } - - /** Put adds new object to the end of queue. - * @param o the object to add - */ - public void put(T o) { - if (last != null) { - ListItem li = new ListItem(o); - last.next = li; - last = li; - } else { - next = last = new ListItem(o); - } - } - - /** Adds array of objects into the queue. - * @param arr array of objects to put into the queue - */ - public void put(Collection arr) { - for (T e : arr) { - put(e); - } - } - - /** Is there any next object? - * @return true if there is next object, false otherwise - */ - public boolean hasMoreElements() { - return next != null; - } - - /** @return next object in enumeration - * @exception NoSuchElementException if there is no next object - */ - public R nextElement() { - if (next == null) { - throw new NoSuchElementException(); - } - - T res = next.object; - - if ((next = next.next) == null) { - last = null; - } - - ; - - ToAdd toAdd = new ToAdd(this); - R out = processor.process(res, toAdd); - toAdd.finish(); - - return out; - } - - /** item in linked list of Objects */ - private static final class ListItem { - T object; - ListItem next; - - /** @param o the object for this item */ - ListItem(T o) { - object = o; - } - } - - /** Temporary collection that supports only add and addAll operations*/ - private static final class ToAdd extends Object implements Collection { - private QEn q; - - public ToAdd(QEn q) { - this.q = q; - } - - public void finish() { - this.q = null; - } - - public boolean add(T o) { - q.put(o); - - return true; - } - - public boolean addAll(Collection c) { - q.put(c); - - return true; - } - - private String msg() { - return "Only add and addAll are implemented"; // NOI18N - } - - public void clear() { - throw new UnsupportedOperationException(msg()); - } - - public boolean contains(Object o) { - throw new UnsupportedOperationException(msg()); - } - - public boolean containsAll(Collection c) { - throw new UnsupportedOperationException(msg()); - } - - public boolean isEmpty() { - throw new UnsupportedOperationException(msg()); - } - - public Iterator iterator() { - throw new UnsupportedOperationException(msg()); - } - - public boolean remove(Object o) { - throw new UnsupportedOperationException(msg()); - } - - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException(msg()); - } - - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException(msg()); - } - - public int size() { - throw new UnsupportedOperationException(msg()); - } - - public Object[] toArray() { - throw new UnsupportedOperationException(msg()); - } - - public X[] toArray(X[] a) { - throw new UnsupportedOperationException(msg()); - } - } - // end of ToAdd - } - // end of QEn - - /** Filtering enumeration */ - private static final class FilEn extends Object implements Enumeration { - /** marker object stating there is no nexte element prepared */ - private static final Object EMPTY = new Object(); - - /** enumeration to filter */ - private Enumeration en; - - /** element to be returned next time or {@link #EMPTY} if there is - * no such element prepared */ - private R next = empty(); - - /** the set to use as filter */ - private Processor filter; - - /** - * @param en enumeration to filter - */ - public FilEn(Enumeration en, Processor filter) { - this.en = en; - this.filter = filter; - } - - /** @return true if there is more elements in the enumeration - */ - public boolean hasMoreElements() { - if (next != empty()) { - // there is a object already prepared - return true; - } - - while (en.hasMoreElements()) { - // read next - next = filter.process(en.nextElement(), null); - - if (next != null) { - // if the object is accepted - return true; - } - - ; - } - - next = empty(); - - return false; - } - - /** @return next object in the enumeration - * @exception NoSuchElementException can be thrown if there is no next object - * in the enumeration - */ - public R nextElement() { - if ((next == EMPTY) && !hasMoreElements()) { - throw new NoSuchElementException(); - } - - R res = next; - next = empty(); - - return res; - } - - @SuppressWarnings("unchecked") - private R empty() { - return (R)EMPTY; - } - } - // end of FilEn - - /** Returns true from contains if object is not null */ - private static class RNulls implements Processor { - public T process(T original, Collection toAdd) { - return original; - } - } - // end of RNulls -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/NbPreferences.java --- a/openide.util/src/org/openide/util/NbPreferences.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.prefs.Preferences; - -/** - * Provides an implementation of the Preferences API which may be backed by - * a NetBeans-specific implementation. - * @see Preferences API in NetBeans - * @since org.openide.util 7.4 - * @author Radek Matous - */ -public final class NbPreferences { - private static Provider PREFS_IMPL; - - private NbPreferences() {} - - /** - * Returns user preference node . {@link Preferences#absolutePath} of such - * a node depends whether class provided as a parameter was loaded as a part of any module - * or not. If so, then absolute path corresponds to slashified code name base of module. - * If not, then absolute path corresponds to class's package. - * - * @param cls the class for which a user preference node is desired. - * @return the user preference node - */ - public static Preferences forModule(Class cls) { - if (PREFS_IMPL == null) { - PREFS_IMPL = getPreferencesProvider(); - } - return PREFS_IMPL.preferencesForModule(cls); - } - - /** - * Returns the root preference node. - * - * @return the root preference node. - */ - public static Preferences root() { - if (PREFS_IMPL == null) { - PREFS_IMPL = getPreferencesProvider(); - } - return PREFS_IMPL.preferencesRoot(); - } - - private static Provider getPreferencesProvider() { - Provider retval = Lookup.getDefault().lookup(Provider.class); - if (retval == null) { - retval = new Provider() { - public Preferences preferencesForModule(Class cls) { - return Preferences.userNodeForPackage(cls); - } - - public Preferences preferencesRoot() { - return Preferences.userRoot(); - } - }; - // Avoided warning in case it is set - //(e.g. from NbTestCase - org.netbeans.junit.internal.MemoryPreferencesFactory). - String prefsFactory = System.getProperty("java.util.prefs.PreferencesFactory");//NOI18N - if (!"org.netbeans.junit.internal.MemoryPreferencesFactory".equals(prefsFactory)) {//NOI18N - Logger logger = Logger.getLogger(NbPreferences.class.getName()); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - new Exception().printStackTrace(new PrintStream(bos)); - logger.log(prefsFactory == null ? Level.WARNING : Level.FINE, - "NetBeans implementation of Preferences not found: " + bos.toString() );//NOI18N - } - } - return retval; - } - - /** - * Implementation of {@link NbPreferences} methods. - * Not intended for use outside the NetBeans Platform. - * @since org.openide.util 8.1 - */ - public interface Provider { - /** - * Returns user preference node. {@link Preferences#absolutePath} of such - * a node depends whether class provided as a parameter was loaded as a part of any module - * or not. If so, then absolute path corresponds to slashified code name base of module. - * If not, then absolute path corresponds to class's package. - * - * @param cls the class for which a user preference node is desired. - * @return the user preference node - */ - Preferences preferencesForModule(Class cls); - /** - * Returns the root preference node. - * - * @return the root preference node. - */ - Preferences preferencesRoot(); - } - -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/Utilities.java --- a/openide.util/src/org/openide/util/Utilities.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3115 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.Dialog; -import java.awt.Dimension; -import java.awt.Event; -import java.awt.Frame; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsEnvironment; -import java.awt.Image; -import java.awt.Insets; -import java.awt.KeyboardFocusManager; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.SoftReference; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.text.BreakIterator; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeSet; -import java.util.Vector; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.JSeparator; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import org.openide.util.actions.Presenter; -import org.openide.util.lookup.Lookups; -import org.openide.util.lookup.implspi.ActiveQueue; -import org.openide.util.actions.ActionPresenterProvider; - -/** Otherwise uncategorized useful static methods. -* -* @author Jan Palka, Ian Formanek, Jaroslav Tulach -*/ -public final class Utilities { - - private static final Logger LOG = Logger.getLogger(Utilities.class.getName()); - - /** Operating system is Windows NT. */ - public static final int OS_WINNT = 1 << 0; - - /** Operating system is Windows 95. */ - public static final int OS_WIN95 = OS_WINNT << 1; - - /** Operating system is Windows 98. */ - public static final int OS_WIN98 = OS_WIN95 << 1; - - /** Operating system is Solaris. */ - public static final int OS_SOLARIS = OS_WIN98 << 1; - - /** Operating system is Linux. */ - public static final int OS_LINUX = OS_SOLARIS << 1; - - /** Operating system is HP-UX. */ - public static final int OS_HP = OS_LINUX << 1; - - /** Operating system is IBM AIX. */ - public static final int OS_AIX = OS_HP << 1; - - /** Operating system is SGI IRIX. */ - public static final int OS_IRIX = OS_AIX << 1; - - /** Operating system is Sun OS. */ - public static final int OS_SUNOS = OS_IRIX << 1; - - /** Operating system is Compaq TRU64 Unix */ - public static final int OS_TRU64 = OS_SUNOS << 1; - - /** @deprecated please use OS_TRU64 instead */ - @Deprecated - public static final int OS_DEC = OS_TRU64 << 1; - - /** Operating system is OS/2. */ - public static final int OS_OS2 = OS_DEC << 1; - - /** Operating system is Mac. */ - public static final int OS_MAC = OS_OS2 << 1; - - /** Operating system is Windows 2000. */ - public static final int OS_WIN2000 = OS_MAC << 1; - - /** Operating system is Compaq OpenVMS */ - public static final int OS_VMS = OS_WIN2000 << 1; - - /** - *Operating system is one of the Windows variants but we don't know which - *one it is - */ - public static final int OS_WIN_OTHER = OS_VMS << 1; - - /** Operating system is unknown. */ - public static final int OS_OTHER = OS_WIN_OTHER << 1; - - /** Operating system is FreeBSD - * @since 4.50 - */ - public static final int OS_FREEBSD = OS_OTHER << 1; - - /** Operating system is Windows Vista. - * @since 7.17 - */ - public static final int OS_WINVISTA = OS_FREEBSD << 1; - - /** Operating system is one of the Unix variants but we don't know which - * one it is. - * @since 7.18 - */ - public static final int OS_UNIX_OTHER = OS_WINVISTA << 1; - - /** Operating system is OpenBSD. - * @since 7.18 - */ - public static final int OS_OPENBSD = OS_UNIX_OTHER << 1; - - /** A mask for Windows platforms. - * @deprecated Use {@link #isWindows()} instead. - */ - @Deprecated - public static final int OS_WINDOWS_MASK = OS_WINNT | OS_WIN95 | OS_WIN98 | OS_WIN2000 | OS_WINVISTA | OS_WIN_OTHER; - - /** A mask for Unix platforms. - * @deprecated Use {@link #isUnix()} instead. - */ - @Deprecated - public static final int OS_UNIX_MASK = OS_SOLARIS | OS_LINUX | OS_HP | OS_AIX | OS_IRIX | OS_SUNOS | OS_TRU64 | - OS_MAC | OS_FREEBSD | OS_OPENBSD | OS_UNIX_OTHER; - - /** A height of the windows's taskbar */ - public static final int TYPICAL_WINDOWS_TASKBAR_HEIGHT = 27; - - /** A height of the Mac OS X's menu */ - private static final int TYPICAL_MACOSX_MENU_HEIGHT = 24; - - /** The operating system on which NetBeans runs*/ - private static int operatingSystem = -1; - private static final String[] keywords = new String[] { - - //If adding to this, insert in alphabetical order! - "abstract", "assert", "boolean", "break", "byte", "case", //NOI18N - "catch", "char", "class", "const", "continue", "default", //NOI18N - "do", "double", "else", "enum", "extends", "false", "final", //NOI18N - "finally", "float", "for", "goto", "if", "implements", //NOI18N - "import", "instanceof", "int", "interface", "long", //NOI18N - "native", "new", "null", "package", "private", //NOI18N - "protected", "public", "return", "short", "static", //NOI18N - "strictfp", "super", "switch", "synchronized", "this", //NOI18N - "throw", "throws", "transient", "true", "try", "void", //NOI18N - "volatile", "while" //NOI18N - }; - private static Timer clearIntrospector; - private static ActionListener doClear; - private static final int CTRL_WILDCARD_MASK = 32768; - private static final int ALT_WILDCARD_MASK = CTRL_WILDCARD_MASK * 2; - - // Package retranslation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - private static final String TRANS_LOCK = "TRANS_LOCK"; - - /** last used classloader or if run in test mode the TRANS_LOCK */ - private static Object transLoader; - - /** regular expression to with all changes */ - private static RE transExp; - - // - // Support for work with actions - // - - /** the found actionsGlobalContext */ - private static Lookup global; - - private Utilities() { - } - - /** - * Useful queue for all parts of system that use java.lang.ref.References - * together with some ReferenceQueue and need to do some clean up - * when the reference is enqueued. Usually, in order to be notified about that, one - * needs to either create a dedicated thread that blocks on the queue and is - * Object.notify-ed, which is the right approach but consumes - * valuable system resources (threads) or one can periodically check the content - * of the queue by RequestProcessor.Task.schedule which is - * completely wrong, because it wakes up the system every (say) 15 seconds. - * In order to provide useful support for this problem, this queue has been - * provided. - *

- * If you have a reference that needs cleanup, make it implement Runnable - * and register it with the queue: - *

-     * class MyReference extends WeakReference implements Runnable {
-     *     private final OtherInfo dataToCleanUp;
-     *     public MyReference(Thing ref, OtherInfo data) {
-     *         super(ref, Utilities.queue());
-     *         dataToCleanUp = data;
-     *     }
-     *     public void run() {
-     *         dataToCleanUp.releaseOrWhateverYouNeed();
-     *     }
-     * }
-     * 
- * When the ref object is garbage collected, your run method - * will be invoked by calling - * ((Runnable) reference).run() - * and you can perform whatever cleanup is necessary. Be sure not to block - * in such cleanup for a long time as this prevents other waiting references - * from cleaning themselves up. - *

- * Do not call any ReferenceQueue methods. They - * will throw exceptions. You may only enqueue a reference. - *

- * Be sure to call this method anew for each reference. - * Do not attempt to cache the return value. - * @since 3.11 - */ - public static ReferenceQueue activeReferenceQueue() { - return ActiveQueue.queue(); - } - - /** Get the operating system on which NetBeans is running. - * @return one of the OS_* constants (such as {@link #OS_WINNT}) - */ - public static final int getOperatingSystem() { - if (operatingSystem == -1) { - String osName = System.getProperty("os.name"); - - if ("Windows NT".equals(osName)) { // NOI18N - operatingSystem = OS_WINNT; - } else if ("Windows 95".equals(osName)) { // NOI18N - operatingSystem = OS_WIN95; - } else if ("Windows 98".equals(osName)) { // NOI18N - operatingSystem = OS_WIN98; - } else if ("Windows 2000".equals(osName)) { // NOI18N - operatingSystem = OS_WIN2000; - } else if ("Windows Vista".equals(osName)) { // NOI18N - operatingSystem = OS_WINVISTA; - } else if (osName.startsWith("Windows ")) { // NOI18N - operatingSystem = OS_WIN_OTHER; - } else if ("Solaris".equals(osName)) { // NOI18N - operatingSystem = OS_SOLARIS; - } else if (osName.startsWith("SunOS")) { // NOI18N - operatingSystem = OS_SOLARIS; - } - // JDK 1.4 b2 defines os.name for me as "Redhat Linux" -jglick - else if (osName.endsWith("Linux")) { // NOI18N - operatingSystem = OS_LINUX; - } else if ("HP-UX".equals(osName)) { // NOI18N - operatingSystem = OS_HP; - } else if ("AIX".equals(osName)) { // NOI18N - operatingSystem = OS_AIX; - } else if ("Irix".equals(osName)) { // NOI18N - operatingSystem = OS_IRIX; - } else if ("SunOS".equals(osName)) { // NOI18N - operatingSystem = OS_SUNOS; - } else if ("Digital UNIX".equals(osName)) { // NOI18N - operatingSystem = OS_TRU64; - } else if ("OS/2".equals(osName)) { // NOI18N - operatingSystem = OS_OS2; - } else if ("OpenVMS".equals(osName)) { // NOI18N - operatingSystem = OS_VMS; - } else if (osName.equals("Mac OS X")) { // NOI18N - operatingSystem = OS_MAC; - } else if (osName.startsWith("Darwin")) { // NOI18N - operatingSystem = OS_MAC; - } else if (osName.toLowerCase(Locale.US).startsWith("freebsd")) { // NOI18N - operatingSystem = OS_FREEBSD; - } else if ("OpenBSD".equals(osName)) { // NOI18N - operatingSystem = OS_OPENBSD; - } else if (File.pathSeparatorChar == ':') { // NOI18N - operatingSystem = OS_UNIX_OTHER; - } else { - operatingSystem = OS_OTHER; - } - } - - return operatingSystem; - } - - /** Test whether NetBeans is running on some variant of Windows. - * @return true if Windows, false if some other manner of operating system - */ - public static final boolean isWindows() { - return (getOperatingSystem() & OS_WINDOWS_MASK) != 0; - } - - /** Test whether NetBeans is running on MacOS. - * @since 7.7 - * @return true if Mac, false if some other manner of operating system - */ - public static final boolean isMac() { - return (getOperatingSystem() & OS_MAC) != 0; - } - - /** Test whether NetBeans is running on some variant of Unix. - * Linux is included as well as the commercial vendors. - * @return true some sort of Unix, false if some other manner of operating system - */ - public static final boolean isUnix() { - return (getOperatingSystem() & OS_UNIX_MASK) != 0; - } - - // only for UtilitiesTest purposes - final static void resetOperatingSystem() { - operatingSystem = -1; - } - - /** Test whether a given string is a valid Java identifier. - * @param id string which should be checked - * @return true if a valid identifier - */ - public static final boolean isJavaIdentifier(String id) { - if (id == null) { - return false; - } - - if (id.equals("")) { - return false; - } - - if (!(java.lang.Character.isJavaIdentifierStart(id.charAt(0)))) { - return false; - } - - for (int i = 1; i < id.length(); i++) { - if (!(java.lang.Character.isJavaIdentifierPart(id.charAt(i)))) { - return false; - } - } - - return Arrays.binarySearch(keywords, id) < 0; - } - - /** Central method for obtaining BeanInfo for potential JavaBean classes. - * @param clazz class of the bean to provide the BeanInfo for - * @return the bean info - * @throws java.beans.IntrospectionException for the usual reasons - * @see java.beans.Introspector#getBeanInfo(Class) - */ - public static java.beans.BeanInfo getBeanInfo(Class clazz) - throws java.beans.IntrospectionException { - java.beans.BeanInfo bi; - - try { - bi = java.beans.Introspector.getBeanInfo(clazz); - } catch (java.beans.IntrospectionException ie) { - Exceptions.attachMessage(ie, - "Encountered while introspecting " + - clazz.getName()); // NOI18N - throw ie; - } catch (Error e) { - // Could be a bug in Introspector triggered by NB code. - Exceptions.attachMessage(e, - "Encountered while introspecting " + - clazz.getName()); // NOI18N - throw e; - } - - if (java.awt.Component.class.isAssignableFrom(clazz)) { - java.beans.PropertyDescriptor[] pds = bi.getPropertyDescriptors(); - - for (int i = 0; i < pds.length; i++) { - if (pds[i].getName().equals("cursor")) { // NOI18N - - try { - Method getter = Component.class.getDeclaredMethod("getCursor", new Class[0]); // NOI18N - Method setter = Component.class.getDeclaredMethod("setCursor", new Class[] { Cursor.class }); // NOI18N - pds[i] = new java.beans.PropertyDescriptor("cursor", getter, setter); // NOI18N - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - - break; - } - } - } - - // clears about 1000 instances of Method - if (bi != null) { - if (clearIntrospector == null) { - doClear = new ActionListener() { - public void actionPerformed(ActionEvent ev) { - java.beans.Introspector.flushCaches(); - } - }; - clearIntrospector = new Timer(15000, doClear); - clearIntrospector.setRepeats(false); - } - - clearIntrospector.restart(); - } - - return bi; - } - - /** Central method for obtaining BeanInfo for potential JavaBean classes, with a stop class. - * @param clazz class of the bean to provide the BeanInfo for - * @param stopClass the stop class - * @return the bean info - * @throws java.beans.IntrospectionException for the usual reasons - * @see java.beans.Introspector#getBeanInfo(Class, Class) - */ - public static java.beans.BeanInfo getBeanInfo(Class clazz, Class stopClass) - throws java.beans.IntrospectionException { - return java.beans.Introspector.getBeanInfo(clazz, stopClass); - } - - /** Wrap multi-line strings (and get the individual lines). - * @param original the original string to wrap - * @param width the maximum width of lines - * @param wrapWords if true, the lines are wrapped on word boundaries (if possible); - * if false, character boundaries are used - * @param removeNewLines if true, any newlines in the original string are ignored - * @return the lines after wrapping - * @deprecated use {@link #wrapStringToArray(String, int, BreakIterator, boolean)} since it is better for I18N - */ - @Deprecated - public static String[] wrapStringToArray(String original, int width, boolean wrapWords, boolean removeNewLines) { - BreakIterator bi = (wrapWords ? BreakIterator.getWordInstance() : BreakIterator.getCharacterInstance()); - - return wrapStringToArray(original, width, bi, removeNewLines); - } - - /** Wrap multi-line strings (and get the individual lines). - * @param original the original string to wrap - * @param width the maximum width of lines - * @param breakIterator breaks original to chars, words, sentences, depending on what instance you provide. - * @param removeNewLines if true, any newlines in the original string are ignored - * @return the lines after wrapping - */ - public static String[] wrapStringToArray( - String original, int width, BreakIterator breakIterator, boolean removeNewLines - ) { - if (original.length() == 0) { - return new String[] { original }; - } - - String[] workingSet; - - // substitute original newlines with spaces, - // remove newlines from head and tail - if (removeNewLines) { - original = trimString(original); - original = original.replace('\n', ' '); - workingSet = new String[] { original }; - } else { - StringTokenizer tokens = new StringTokenizer(original, "\n"); // NOI18N - int len = tokens.countTokens(); - workingSet = new String[len]; - - for (int i = 0; i < len; i++) { - workingSet[i] = tokens.nextToken(); - } - } - - if (width < 1) { - width = 1; - } - - if (original.length() <= width) { - return workingSet; - } - -widthcheck: { - boolean ok = true; - - for (int i = 0; i < workingSet.length; i++) { - ok = ok && (workingSet[i].length() < width); - - if (!ok) { - break widthcheck; - } - } - - return workingSet; - } - - java.util.ArrayList lines = new java.util.ArrayList(); - - int lineStart = 0; // the position of start of currently processed line in the original string - - for (int i = 0; i < workingSet.length; i++) { - if (workingSet[i].length() < width) { - lines.add(workingSet[i]); - } else { - breakIterator.setText(workingSet[i]); - - int nextStart = breakIterator.next(); - int prevStart = 0; - - do { - while (((nextStart - lineStart) < width) && (nextStart != BreakIterator.DONE)) { - prevStart = nextStart; - nextStart = breakIterator.next(); - } - - if (nextStart == BreakIterator.DONE) { - nextStart = prevStart = workingSet[i].length(); - } - - if (prevStart == 0) { - prevStart = nextStart; - } - - lines.add(workingSet[i].substring(lineStart, prevStart)); - - lineStart = prevStart; - prevStart = 0; - } while (lineStart < workingSet[i].length()); - - lineStart = 0; - } - } - - String[] s = new String[lines.size()]; - - return lines.toArray(s); - } - - /** trims String - * @param s a String to trim - * @return trimmed String - */ - private static String trimString(String s) { - int idx = 0; - char c; - final int slen = s.length(); - - if (slen == 0) { - return s; - } - - do { - c = s.charAt(idx++); - } while (((c == '\n') || (c == '\r')) && (idx < slen)); - - s = s.substring(--idx); - idx = s.length() - 1; - - if (idx < 0) { - return s; - } - - do { - c = s.charAt(idx--); - } while (((c == '\n') || (c == '\r')) && (idx >= 0)); - - return s.substring(0, idx + 2); - } - - /** Wrap multi-line strings. - * @param original the original string to wrap - * @param width the maximum width of lines - * @param breakIterator algorithm for breaking lines - * @param removeNewLines if true, any newlines in the original string are ignored - * @return the whole string with embedded newlines - */ - public static String wrapString(String original, int width, BreakIterator breakIterator, boolean removeNewLines) { - String[] sarray = wrapStringToArray(original, width, breakIterator, removeNewLines); - StringBuffer retBuf = new StringBuffer(); - - for (int i = 0; i < sarray.length; i++) { - retBuf.append(sarray[i]); - retBuf.append('\n'); - } - - return retBuf.toString(); - } - - /** Wrap multi-line strings. - * @param original the original string to wrap - * @param width the maximum width of lines - * @param wrapWords if true, the lines are wrapped on word boundaries (if possible); - * if false, character boundaries are used - * @param removeNewLines if true, any newlines in the original string are ignored - * @return the whole string with embedded newlines - * @deprecated Use {@link #wrapString (String, int, BreakIterator, boolean)} as it is friendlier to I18N. - */ - @Deprecated - public static String wrapString(String original, int width, boolean wrapWords, boolean removeNewLines) { - // substitute original newlines with spaces, - // remove newlines from head and tail - if (removeNewLines) { - while (original.startsWith("\n")) // NOI18N - - original = original.substring(1); - - while (original.endsWith("\n")) // NOI18N - - original = original.substring(0, original.length() - 1); - - original = original.replace('\n', ' '); - } - - if (width < 1) { - width = 1; - } - - if (original.length() <= width) { - return original; - } - - java.util.Vector lines = new java.util.Vector(); - int lineStart = 0; // the position of start of currently processed line in the original string - int lastSpacePos = -1; - - for (int i = 0; i < original.length(); i++) { - if (lineStart >= (original.length() - 1)) { - break; - } - - // newline in the original string - if (original.charAt(i) == '\n') { - lines.addElement(original.substring(lineStart, i)); - lineStart = i + 1; - lastSpacePos = -1; - - continue; - } - - // remember last space position - if (Character.isSpaceChar(original.charAt(i))) { - lastSpacePos = i; - } - - // last position in the original string - if (i == (original.length() - 1)) { - lines.addElement(original.substring(lineStart)); - - break; - } - - // reached width - if ((i - lineStart) == width) { - if (wrapWords && (lastSpacePos != -1)) { - lines.addElement(original.substring(lineStart, lastSpacePos)); - lineStart = lastSpacePos + 1; // the space is consumed for the newline - lastSpacePos = -1; - } else { - lines.addElement(original.substring(lineStart, i)); - lineStart = i; - lastSpacePos = -1; - } - } - } - - StringBuffer retBuf = new StringBuffer(); - - for (java.util.Enumeration e = lines.elements(); e.hasMoreElements();) { - retBuf.append((String) e.nextElement()); - retBuf.append('\n'); - } - - return retBuf.toString(); - } - - /** Search-and-replace fixed string matches within a string. - * @param original the original string - * @param replaceFrom the substring to be find - * @param replaceTo the substring to replace it with - * @return a new string with all occurrences replaced - * @deprecated Use {@link String#replace(CharSequence,CharSequence)} instead - */ - @Deprecated - public static String replaceString(String original, String replaceFrom, String replaceTo) { - int index = 0; - - if ("".equals(replaceFrom)) { - return original; // NOI18N - } - - StringBuffer buf = new StringBuffer(); - - while (true) { - int pos = original.indexOf(replaceFrom, index); - - if (pos == -1) { - buf.append(original.substring(index)); - - return buf.toString(); - } - - buf.append(original.substring(index, pos)); - buf.append(replaceTo); - index = pos + replaceFrom.length(); - - if (index == original.length()) { - return buf.toString(); - } - } - } - - /** Turn full name of an inner class into its pure form. - * @param fullName e.g. some.pkg.SomeClass$Inner - * @return e.g. Inner - */ - public static final String pureClassName(final String fullName) { - final int index = fullName.indexOf('$'); - - if ((index >= 0) && (index < fullName.length())) { - return fullName.substring(index + 1, fullName.length()); - } - - return fullName; - } - - /** Test whether the operating system supports icons on frames (windows). - * @return true if it does not - * @deprecated Obsolete, useless method, no replacement. - */ - @Deprecated public static final boolean isLargeFrameIcons() { - return (getOperatingSystem() == OS_SOLARIS) || (getOperatingSystem() == OS_HP); - } - - /** Compute hash code of array. - * Asks all elements for their own code and composes the - * values. - * @param arr array of objects, can contain nulls - * @return the hash code - * @see Object#hashCode - */ - public static int arrayHashCode(Object[] arr) { - int c = 0; - int len = arr.length; - - for (int i = 0; i < len; i++) { - Object o = arr[i]; - int v = (o == null) ? 1 : o.hashCode(); - c += (v ^ i); - } - - return c; - } - - /** Safe equality check. - * The supplied objects are equal if:
    - *
  • both are null - *
  • both are arrays with same length and equal items (if the items are arrays, - * they are not checked the same way again) - *
  • the two objects are {@link Object#equals} - *
- * This method is null-safe, so if one of the parameters is true and the second not, - * it returns false. - * @param o1 the first object to compare - * @param o2 the second object to compare - * @return true if the objects are equal - */ - public static boolean compareObjects(Object o1, Object o2) { - return compareObjectsImpl(o1, o2, 1); - } - - /** Safe equality check with array recursion. - * @param o1 the first object to compare - * @param o2 the second object to compare - * @param checkArraysDepth the depth to which arrays should be compared for equality (negative for infinite depth, zero for no comparison of elements, one for shallow, etc.) - * @return true if the objects are equal - * @see #compareObjects(Object, Object) - */ - public static boolean compareObjectsImpl(Object o1, Object o2, int checkArraysDepth) { - // handle null values - if (o1 == null) { - return (o2 == null); - } else if (o2 == null) { - return false; - } - - // handle arrays - if (checkArraysDepth > 0) { - if ((o1 instanceof Object[]) && (o2 instanceof Object[])) { - // Note: also handles multidimensional arrays of primitive types correctly. - // I.e. new int[0][] instanceof Object[] - Object[] o1a = (Object[]) o1; - Object[] o2a = (Object[]) o2; - int l1 = o1a.length; - int l2 = o2a.length; - - if (l1 != l2) { - return false; - } - - for (int i = 0; i < l1; i++) { - if (!compareObjectsImpl(o1a[i], o2a[i], checkArraysDepth - 1)) { - return false; - } - } - - return true; - } else if ((o1 instanceof byte[]) && (o2 instanceof byte[])) { - byte[] o1a = (byte[]) o1; - byte[] o2a = (byte[]) o2; - int l1 = o1a.length; - int l2 = o2a.length; - - if (l1 != l2) { - return false; - } - - for (int i = 0; i < l1; i++) - if (o1a[i] != o2a[i]) { - return false; - } - - return true; - } else if ((o1 instanceof short[]) && (o2 instanceof short[])) { - short[] o1a = (short[]) o1; - short[] o2a = (short[]) o2; - int l1 = o1a.length; - int l2 = o2a.length; - - if (l1 != l2) { - return false; - } - - for (int i = 0; i < l1; i++) - if (o1a[i] != o2a[i]) { - return false; - } - - return true; - } else if ((o1 instanceof int[]) && (o2 instanceof int[])) { - int[] o1a = (int[]) o1; - int[] o2a = (int[]) o2; - int l1 = o1a.length; - int l2 = o2a.length; - - if (l1 != l2) { - return false; - } - - for (int i = 0; i < l1; i++) - if (o1a[i] != o2a[i]) { - return false; - } - - return true; - } else if ((o1 instanceof long[]) && (o2 instanceof long[])) { - long[] o1a = (long[]) o1; - long[] o2a = (long[]) o2; - int l1 = o1a.length; - int l2 = o2a.length; - - if (l1 != l2) { - return false; - } - - for (int i = 0; i < l1; i++) - if (o1a[i] != o2a[i]) { - return false; - } - - return true; - } else if ((o1 instanceof float[]) && (o2 instanceof float[])) { - float[] o1a = (float[]) o1; - float[] o2a = (float[]) o2; - int l1 = o1a.length; - int l2 = o2a.length; - - if (l1 != l2) { - return false; - } - - for (int i = 0; i < l1; i++) - if (o1a[i] != o2a[i]) { - return false; - } - - return true; - } else if ((o1 instanceof double[]) && (o2 instanceof double[])) { - double[] o1a = (double[]) o1; - double[] o2a = (double[]) o2; - int l1 = o1a.length; - int l2 = o2a.length; - - if (l1 != l2) { - return false; - } - - for (int i = 0; i < l1; i++) - if (o1a[i] != o2a[i]) { - return false; - } - - return true; - } else if ((o1 instanceof char[]) && (o2 instanceof char[])) { - char[] o1a = (char[]) o1; - char[] o2a = (char[]) o2; - int l1 = o1a.length; - int l2 = o2a.length; - - if (l1 != l2) { - return false; - } - - for (int i = 0; i < l1; i++) - if (o1a[i] != o2a[i]) { - return false; - } - - return true; - } else if ((o1 instanceof boolean[]) && (o2 instanceof boolean[])) { - boolean[] o1a = (boolean[]) o1; - boolean[] o2a = (boolean[]) o2; - int l1 = o1a.length; - int l2 = o2a.length; - - if (l1 != l2) { - return false; - } - - for (int i = 0; i < l1; i++) - if (o1a[i] != o2a[i]) { - return false; - } - - return true; - } - - // else not array type - } - - // handle common objects--non-arrays, or arrays when depth == 0 - return o1.equals(o2); - } - - /** Assemble a human-presentable class name for a specified class. - * Arrays are represented as e.g. java.lang.String[]. - * @param clazz the class to name - * @return the human-presentable name - */ - public static String getClassName(Class clazz) { - // if it is an array, get short name of element type and append [] - if (clazz.isArray()) { - return getClassName(clazz.getComponentType()) + "[]"; // NOI18N - } else { - return clazz.getName(); - } - } - - /** Assemble a human-presentable class name for a specified class (omitting the package). - * Arrays are represented as e.g. String[]. - * @param clazz the class to name - * @return the human-presentable name - */ - public static String getShortClassName(Class clazz) { - // if it is an array, get short name of element type and append [] - if (clazz.isArray()) { - return getShortClassName(clazz.getComponentType()) + "[]"; // NOI18N - } - - String name = clazz.getName().replace('$', '.'); - - return name.substring(name.lastIndexOf(".") + 1, name.length()); // NOI18N - } - - /** - * Convert an array of objects to an array of primitive types. - * E.g. an Integer[] would be changed to an int[]. - * @param array the wrapper array - * @return a primitive array - * @throws IllegalArgumentException if the array element type is not a primitive wrapper - */ - public static Object toPrimitiveArray(Object[] array) { - if (array instanceof Integer[]) { - int[] r = new int[array.length]; - int i; - int k = array.length; - - for (i = 0; i < k; i++) - r[i] = (((Integer) array[i]) == null) ? 0 : ((Integer) array[i]).intValue(); - - return r; - } - - if (array instanceof Boolean[]) { - boolean[] r = new boolean[array.length]; - int i; - int k = array.length; - - for (i = 0; i < k; i++) - r[i] = (((Boolean) array[i]) == null) ? false : ((Boolean) array[i]).booleanValue(); - - return r; - } - - if (array instanceof Byte[]) { - byte[] r = new byte[array.length]; - int i; - int k = array.length; - - for (i = 0; i < k; i++) - r[i] = (((Byte) array[i]) == null) ? 0 : ((Byte) array[i]).byteValue(); - - return r; - } - - if (array instanceof Character[]) { - char[] r = new char[array.length]; - int i; - int k = array.length; - - for (i = 0; i < k; i++) - r[i] = (((Character) array[i]) == null) ? 0 : ((Character) array[i]).charValue(); - - return r; - } - - if (array instanceof Double[]) { - double[] r = new double[array.length]; - int i; - int k = array.length; - - for (i = 0; i < k; i++) - r[i] = (((Double) array[i]) == null) ? 0 : ((Double) array[i]).doubleValue(); - - return r; - } - - if (array instanceof Float[]) { - float[] r = new float[array.length]; - int i; - int k = array.length; - - for (i = 0; i < k; i++) - r[i] = (((Float) array[i]) == null) ? 0 : ((Float) array[i]).floatValue(); - - return r; - } - - if (array instanceof Long[]) { - long[] r = new long[array.length]; - int i; - int k = array.length; - - for (i = 0; i < k; i++) - r[i] = (((Long) array[i]) == null) ? 0 : ((Long) array[i]).longValue(); - - return r; - } - - if (array instanceof Short[]) { - short[] r = new short[array.length]; - int i; - int k = array.length; - - for (i = 0; i < k; i++) - r[i] = (((Short) array[i]) == null) ? 0 : ((Short) array[i]).shortValue(); - - return r; - } - - throw new IllegalArgumentException(); - } - - /** - * Convert an array of primitive types to an array of objects. - * E.g. an int[] would be turned into an Integer[]. - * @param array the primitive array - * @return a wrapper array - * @throws IllegalArgumentException if the array element type is not primitive - */ - public static Object[] toObjectArray(Object array) { - if (array instanceof Object[]) { - return (Object[]) array; - } - - if (array instanceof int[]) { - int i; - int k = ((int[]) array).length; - Integer[] r = new Integer[k]; - - for (i = 0; i < k; i++) - r[i] = new Integer(((int[]) array)[i]); - - return r; - } - - if (array instanceof boolean[]) { - int i; - int k = ((boolean[]) array).length; - Boolean[] r = new Boolean[k]; - - for (i = 0; i < k; i++) - r[i] = ((boolean[]) array)[i] ? Boolean.TRUE : Boolean.FALSE; - - return r; - } - - if (array instanceof byte[]) { - int i; - int k = ((byte[]) array).length; - Byte[] r = new Byte[k]; - - for (i = 0; i < k; i++) - r[i] = new Byte(((byte[]) array)[i]); - - return r; - } - - if (array instanceof char[]) { - int i; - int k = ((char[]) array).length; - Character[] r = new Character[k]; - - for (i = 0; i < k; i++) - r[i] = new Character(((char[]) array)[i]); - - return r; - } - - if (array instanceof double[]) { - int i; - int k = ((double[]) array).length; - Double[] r = new Double[k]; - - for (i = 0; i < k; i++) - r[i] = new Double(((double[]) array)[i]); - - return r; - } - - if (array instanceof float[]) { - int i; - int k = ((float[]) array).length; - Float[] r = new Float[k]; - - for (i = 0; i < k; i++) - r[i] = new Float(((float[]) array)[i]); - - return r; - } - - if (array instanceof long[]) { - int i; - int k = ((long[]) array).length; - Long[] r = new Long[k]; - - for (i = 0; i < k; i++) - r[i] = new Long(((long[]) array)[i]); - - return r; - } - - if (array instanceof short[]) { - int i; - int k = ((short[]) array).length; - Short[] r = new Short[k]; - - for (i = 0; i < k; i++) - r[i] = new Short(((short[]) array)[i]); - - return r; - } - - throw new IllegalArgumentException(); - } - - /** - * Get the object type for given primitive type. - * - * @param c primitive type (e.g. int) - * @return object type (e.g. Integer) - */ - public static Class getObjectType(Class c) { - if (!c.isPrimitive()) { - return c; - } - - if (c == Integer.TYPE) { - return Integer.class; - } - - if (c == Boolean.TYPE) { - return Boolean.class; - } - - if (c == Byte.TYPE) { - return Byte.class; - } - - if (c == Character.TYPE) { - return Character.class; - } - - if (c == Double.TYPE) { - return Double.class; - } - - if (c == Float.TYPE) { - return Float.class; - } - - if (c == Long.TYPE) { - return Long.class; - } - - if (c == Short.TYPE) { - return Short.class; - } - - throw new IllegalArgumentException(); - } - - /** - * Get the primitive type for given object type. - * - * @param c object type (e.g. Integer) - * @return primitive type (e.g. int) - */ - public static Class getPrimitiveType(Class c) { - if (!c.isPrimitive()) { - return c; - } - - if (c == Integer.class) { - return Integer.TYPE; - } - - if (c == Boolean.class) { - return Boolean.TYPE; - } - - if (c == Byte.class) { - return Byte.TYPE; - } - - if (c == Character.class) { - return Character.TYPE; - } - - if (c == Double.class) { - return Double.TYPE; - } - - if (c == Float.class) { - return Float.TYPE; - } - - if (c == Long.class) { - return Long.TYPE; - } - - if (c == Short.class) { - return Short.TYPE; - } - - throw new IllegalArgumentException(); - } - - /** Find a focus-traverable component. - * @param c the component to look in - * @return the same component if traversable, else a child component if present, else null - * @see Component#isFocusTraversable - */ - public static Component getFocusTraversableComponent(Component c) { - if (c.isFocusable()) { - return c; - } - - if (!(c instanceof Container)) { - return null; - } - - int i; - int k = ((Container) c).getComponentCount(); - - for (i = 0; i < k; i++) { - Component v = ((Container) c).getComponent(i); - - if (v != null) { - return v; - } - } - - return null; - } - - /** Parses parameters from a given string in shell-like manner. - * Users of the Bourne shell (e.g. on Unix) will already be familiar with the behavior. - * For example, when using org.openide.execution.NbProcessDescriptor (Execution API) - * you should be able to: - *
    - *
  • Include command names with embedded spaces, such as c:\Program Files\jdk\bin\javac. - *
  • Include extra command arguments, such as -Dname=value. - *
  • Do anything else which might require unusual characters or processing. For example: - *

    -    * "c:\program files\jdk\bin\java" -Dmessage="Hello /\\/\\ there!" -Xmx128m
    -    * 
    - *

    This example would create the following executable name and arguments: - *

      - *
    1. c:\program files\jdk\bin\java - *
    2. -Dmessage=Hello /\/\ there! - *
    3. -Xmx128m - *
    - * Note that the command string does not escape its backslashes--under the assumption - * that Windows users will not think to do this, meaningless escapes are just left - * as backslashes plus following character. - *
- * Caveat: even after parsing, Windows programs (such as the Java launcher) - * may not fully honor certain - * characters, such as quotes, in command names or arguments. This is because programs - * under Windows frequently perform their own parsing and unescaping (since the shell - * cannot be relied on to do this). On Unix, this problem should not occur. - * @param s a string to parse - * @return an array of parameters - */ - public static String[] parseParameters(String s) { - int NULL = 0x0; // STICK + whitespace or NULL + non_" - int INPARAM = 0x1; // NULL + " or STICK + " or INPARAMPENDING + "\ // NOI18N - int INPARAMPENDING = 0x2; // INPARAM + \ - int STICK = 0x4; // INPARAM + " or STICK + non_" // NOI18N - int STICKPENDING = 0x8; // STICK + \ - Vector params = new Vector(5, 5); - char c; - - int state = NULL; - StringBuffer buff = new StringBuffer(20); - int slength = s.length(); - - for (int i = 0; i < slength; i++) { - c = s.charAt(i); - - if (Character.isWhitespace(c)) { - if (state == NULL) { - if (buff.length() > 0) { - params.addElement(buff.toString()); - buff.setLength(0); - } - } else if (state == STICK) { - params.addElement(buff.toString()); - buff.setLength(0); - state = NULL; - } else if (state == STICKPENDING) { - buff.append('\\'); - params.addElement(buff.toString()); - buff.setLength(0); - state = NULL; - } else if (state == INPARAMPENDING) { - state = INPARAM; - buff.append('\\'); - buff.append(c); - } else { // INPARAM - buff.append(c); - } - - continue; - } - - if (c == '\\') { - if (state == NULL) { - ++i; - - if (i < slength) { - char cc = s.charAt(i); - - if ((cc == '"') || (cc == '\\')) { - buff.append(cc); - } else if (Character.isWhitespace(cc)) { - buff.append(c); - --i; - } else { - buff.append(c); - buff.append(cc); - } - } else { - buff.append('\\'); - - break; - } - - continue; - } else if (state == INPARAM) { - state = INPARAMPENDING; - } else if (state == INPARAMPENDING) { - buff.append('\\'); - state = INPARAM; - } else if (state == STICK) { - state = STICKPENDING; - } else if (state == STICKPENDING) { - buff.append('\\'); - state = STICK; - } - - continue; - } - - if (c == '"') { - if (state == NULL) { - state = INPARAM; - } else if (state == INPARAM) { - state = STICK; - } else if (state == STICK) { - state = INPARAM; - } else if (state == STICKPENDING) { - buff.append('"'); - state = STICK; - } else { // INPARAMPENDING - buff.append('"'); - state = INPARAM; - } - - continue; - } - - if (state == INPARAMPENDING) { - buff.append('\\'); - state = INPARAM; - } else if (state == STICKPENDING) { - buff.append('\\'); - state = STICK; - } - - buff.append(c); - } - - // collect - if (state == INPARAM) { - params.addElement(buff.toString()); - } else if ((state & (INPARAMPENDING | STICKPENDING)) != 0) { - buff.append('\\'); - params.addElement(buff.toString()); - } else { // NULL or STICK - - if (buff.length() != 0) { - params.addElement(buff.toString()); - } - } - - String[] ret = new String[params.size()]; - params.copyInto(ret); - - return ret; - } - - /** Complementary method to parseParameters - * @see #parseParameters - */ - public static String escapeParameters(String[] params) { - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < params.length; i++) { - escapeString(params[i], sb); - sb.append(' '); - } - - final int len = sb.length(); - - if (len > 0) { - sb.setLength(len - 1); - } - - return sb.toString().trim(); - } - - /** Escapes one string - * @see #escapeParameters - */ - private static void escapeString(String s, StringBuffer sb) { - if (s.length() == 0) { - sb.append("\"\""); - - return; - } - - boolean hasSpace = false; - final int sz = sb.length(); - final int slen = s.length(); - char c; - - for (int i = 0; i < slen; i++) { - c = s.charAt(i); - - if (Character.isWhitespace(c)) { - hasSpace = true; - sb.append(c); - - continue; - } - - if (c == '\\') { - sb.append('\\').append('\\'); - - continue; - } - - if (c == '"') { - sb.append('\\').append('"'); - - continue; - } - - sb.append(c); - } - - if (hasSpace) { - sb.insert(sz, '"'); - sb.append('"'); - } - } - - // - // Key conversions - // - - private static final class NamesAndValues { - final Map keyToString; - final Map stringToKey; - NamesAndValues(Map keyToString, Map stringToKey) { - this.keyToString = keyToString; - this.stringToKey = stringToKey; - } - } - - private static Reference namesAndValues; - - private static synchronized NamesAndValues initNameAndValues() { - if (namesAndValues != null) { - NamesAndValues nav = namesAndValues.get(); - if (nav != null) { - return nav; - } - } - - Field[] fields = KeyEvent.class.getDeclaredFields(); - - Map names = new HashMap(fields.length * 4 / 3 + 5, 0.75f); - Map values = new HashMap(fields.length * 4 / 3 + 5, 0.75f); - - for (Field f : fields) { - if (Modifier.isStatic(f.getModifiers())) { - String name = f.getName(); - if (name.startsWith("VK_")) { // NOI18N - // exclude VK - name = name.substring(3); - try { - int numb = f.getInt(null); - names.put(name, numb); - values.put(numb, name); - } catch (IllegalArgumentException ex) { - } catch (IllegalAccessException ex) { - } - } - } - } - - if (names.get("CONTEXT_MENU") == null) { // NOI18N - names.put("CONTEXT_MENU", 0x20C); // NOI18N - values.put(0x20C, "CONTEXT_MENU"); // NOI18N - names.put("WINDOWS", 0x20D); // NOI18N - values.put(0x20D, "WINDOWS"); // NOI18N - } - - NamesAndValues nav = new NamesAndValues(values, names); - namesAndValues = new SoftReference(nav); - return nav; - } - - /** Converts a Swing key stroke descriptor to a familiar Emacs-like name. - * @param stroke key description - * @return name of the key (e.g. CS-F1 for control-shift-function key one) - * @see #stringToKey - */ - public static String keyToString(KeyStroke stroke) { - StringBuilder sb = new StringBuilder(); - - // add modifiers that must be pressed - if (addModifiers(sb, stroke.getModifiers())) { - sb.append('-'); - } - - appendRest(sb, stroke); - return sb.toString(); - } - - private static void appendRest(StringBuilder sb, KeyStroke stroke) { - String c = initNameAndValues().keyToString.get(Integer.valueOf(stroke.getKeyCode())); - - if (c == null) { - sb.append(stroke.getKeyChar()); - } else { - sb.append(c); - } - } - - /** - * Converts a Swing key stroke descriptor to a familiar Emacs-like name, - * but in a portable way, ie. Meta-C on Mac => D-C - * @param stroke key description - * @return name of the key (e.g. CS-F1 for control-shift-function key one) - * @see #stringToKey - */ - public static String keyToString(KeyStroke stroke, boolean portable) { - if (portable) { - StringBuilder sb = new StringBuilder(); - - // add modifiers that must be pressed - if (addModifiersPortable(sb, stroke.getModifiers())) { - sb.append('-'); - } - - appendRest(sb, stroke); - return sb.toString(); - } - return keyToString(stroke); - } - - /** Construct a new key description from a given universal string - * description. - * Provides mapping between Emacs-like textual key descriptions and the - * KeyStroke object used in Swing. - *

- * This format has following form: - *

[C][A][S][M]-identifier - *

Where: - *

    - *
  • C stands for the Control key - *
  • A stands for the Alt key - *
  • S stands for the Shift key - *
  • M stands for the Meta key - *
- * The format also supports two wildcard codes, to support differences in - * platforms. These are the preferred choices for registering keystrokes, - * since platform conflicts will automatically be handled: - *
    - *
  • D stands for the default menu accelerator - the Control - * key on most platforms, the Command (meta) key on Macintosh
  • - *
  • O stands for the alternate accelerator - the Alt key on - * most platforms, the Ctrl key on Macintosh (Macintosh uses Alt as a - * secondary shift key for composing international characters - if you bind - * Alt-8 to an action, a mac user with a French keyboard will not be able - * to type the [ character, which is a significant handicap
  • - *
- * If you use the wildcard characters, and specify a key which will conflict - * with keys the operating system consumes, it will be mapped to whichever - * choice can work - for example, on Macintosh, Command-Q is always consumed - * by the operating system, so D-Q will always map to Control-Q. - *

- * Every modifier before the hyphen must be pressed. - * identifier can be any text constant from {@link KeyEvent} but - * without the leading VK_ characters. So {@link KeyEvent#VK_ENTER} is described as - * ENTER. - * - * @param s the string with the description of the key - * @return key description object, or null if the string does not represent any valid key - */ - public static KeyStroke stringToKey(String s) { - StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), "-", true); // NOI18N - - int needed = 0; - - Map names = initNameAndValues().stringToKey; - - int lastModif = -1; - - try { - for (;;) { - String el = st.nextToken(); - - // required key - if (el.equals("-")) { // NOI18N - - if (lastModif != -1) { - needed |= lastModif; - lastModif = -1; - } - - continue; - } - - // if there is more elements - if (st.hasMoreElements()) { - // the text should describe modifiers - lastModif = readModifiers(el); - } else { - // last text must be the key code - Integer i = names.get(el); - boolean wildcard = (needed & CTRL_WILDCARD_MASK) != 0; - - //Strip out the explicit mask - KeyStroke won't know - //what to do with it - needed = needed & ~CTRL_WILDCARD_MASK; - - boolean macAlt = (needed & ALT_WILDCARD_MASK) != 0; - needed = needed & ~ALT_WILDCARD_MASK; - - if (i != null) { - //#26854 - Default accelerator should be Command on mac - if (wildcard) { - needed |= getMenuShortcutKeyMask(); - - if (isMac()) { - if (!usableKeyOnMac(i, needed)) { - needed &= ~getMenuShortcutKeyMask(); - needed |= KeyEvent.CTRL_MASK; - } - } - } - - if (macAlt) { - if (getOperatingSystem() == OS_MAC) { - needed |= KeyEvent.CTRL_MASK; - } else { - needed |= KeyEvent.ALT_MASK; - } - } - - return KeyStroke.getKeyStroke(i, needed); - } else { - return null; - } - } - } - } catch (NoSuchElementException ex) { - return null; - } - } - - private static final boolean usableKeyOnMac(int key, int mask) { - //All permutations fail for Q except ctrl - if (key == KeyEvent.VK_Q) { - return false; - } - - boolean isMeta = ((mask & KeyEvent.META_MASK) != 0) || ((mask & KeyEvent.CTRL_DOWN_MASK) != 0); - - boolean isAlt = ((mask & KeyEvent.ALT_MASK) != 0) || ((mask & KeyEvent.ALT_DOWN_MASK) != 0); - - boolean isOnlyMeta = isMeta && ((mask & ~(KeyEvent.META_DOWN_MASK | KeyEvent.META_MASK)) == 0); - - //Mac OS consumes keys Command+ these keys - the app will never see - //them, so CTRL should not be remapped for these - if (isOnlyMeta) { - return (key != KeyEvent.VK_H) && (key != KeyEvent.VK_SPACE) && (key != KeyEvent.VK_TAB); - } else if ((key == KeyEvent.VK_D) && isMeta && isAlt) { - return false; - } else { - return true; - } - } - - private static final int getMenuShortcutKeyMask() { - // #152050 - work in headless environment too - if (GraphicsEnvironment.isHeadless()) { - return Event.CTRL_MASK; - } - return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - } - - /** Convert a space-separated list of user-friendly key binding names to a list of Swing key strokes. - * @param s the string with keys - * @return array of key strokes, or null if the string description is not valid - * @see #stringToKey - */ - public static KeyStroke[] stringToKeys(String s) { - StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), " "); // NOI18N - ArrayList arr = new ArrayList(); - - while (st.hasMoreElements()) { - s = st.nextToken(); - - KeyStroke k = stringToKey(s); - - if (k == null) { - return null; - } - - arr.add(k); - } - - return arr.toArray(new KeyStroke[arr.size()]); - } - - /** Adds characters for modifiers to the buffer. - * @param buf buffer to add to - * @param modif modifiers to add (KeyEvent.XXX_MASK) - * @return true if something has been added - */ - private static boolean addModifiers(StringBuilder buf, int modif) { - boolean b = false; - - if ((modif & KeyEvent.CTRL_MASK) != 0) { - buf.append("C"); // NOI18N - b = true; - } - - if ((modif & KeyEvent.ALT_MASK) != 0) { - buf.append("A"); // NOI18N - b = true; - } - - if ((modif & KeyEvent.SHIFT_MASK) != 0) { - buf.append("S"); // NOI18N - b = true; - } - - if ((modif & KeyEvent.META_MASK) != 0) { - buf.append("M"); // NOI18N - b = true; - } - - if ((modif & CTRL_WILDCARD_MASK) != 0) { - buf.append("D"); - b = true; - } - - if ((modif & ALT_WILDCARD_MASK) != 0) { - buf.append("O"); - b = true; - } - - return b; - } - - private static boolean addModifiersPortable(StringBuilder buf, int modifiers) { - boolean b = false; - - if ((modifiers & KeyEvent.SHIFT_MASK) != 0) { - buf.append('S'); - b = true; - } - - if (Utilities.isMac() && ((modifiers & KeyEvent.META_MASK) != 0) || !Utilities.isMac() && ((modifiers & KeyEvent.CTRL_MASK) != 0)) { - buf.append('D'); - b = true; - } - - if (Utilities.isMac() && ((modifiers & KeyEvent.CTRL_MASK) != 0) || !Utilities.isMac() && ((modifiers & KeyEvent.ALT_MASK) != 0)) { - buf.append('O'); - b = true; - } - // mac alt fallback - if (Utilities.isMac() && ((modifiers & KeyEvent.ALT_MASK) != 0)) { - buf.append('A'); - b = true; - } - - return b; - } - - /** Reads for modifiers and creates integer with required mask. - * @param s string with modifiers - * @return integer with mask - * @exception NoSuchElementException if some letter is not modifier - */ - private static int readModifiers(String s) throws NoSuchElementException { - int m = 0; - - for (int i = 0; i < s.length(); i++) { - switch (s.charAt(i)) { - case 'C': - m |= KeyEvent.CTRL_MASK; - - break; - - case 'A': - m |= KeyEvent.ALT_MASK; - - break; - - case 'M': - m |= KeyEvent.META_MASK; - - break; - - case 'S': - m |= KeyEvent.SHIFT_MASK; - - break; - - case 'D': - m |= CTRL_WILDCARD_MASK; - - break; - - case 'O': - m |= ALT_WILDCARD_MASK; - - break; - - default: - throw new NoSuchElementException(s); - } - } - - return m; - } - - /** - * Finds out the monitor where the user currently has the input focus. - * This method is usually used to help the client code to figure out on - * which monitor it should place newly created windows/frames/dialogs. - * - * @return the GraphicsConfiguration of the monitor which currently has the - * input focus - */ - private static GraphicsConfiguration getCurrentGraphicsConfiguration() { - Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - if (focusOwner != null) { - Window w = SwingUtilities.getWindowAncestor(focusOwner); - if (w != null) { - return w.getGraphicsConfiguration(); - } - } - - return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); - } - - /** - * Returns the usable area of the screen where applications can place its - * windows. The method subtracts from the screen the area of taskbars, - * system menus and the like. The screen this method applies to is the one - * which is considered current, ussually the one where the current input - * focus is. - * - * @return the rectangle of the screen where one can place windows - * - * @since 2.5 - */ - public static Rectangle getUsableScreenBounds() { - return getUsableScreenBounds(getCurrentGraphicsConfiguration()); - } - - /** - * Returns the usable area of the screen where applications can place its - * windows. The method subtracts from the screen the area of taskbars, - * system menus and the like. - * - * @param gconf the GraphicsConfiguration of the monitor - * @return the rectangle of the screen where one can place windows - * - * @since 2.5 - */ - public static Rectangle getUsableScreenBounds(GraphicsConfiguration gconf) { - if (gconf == null) { - gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); - } - - Rectangle bounds = new Rectangle(gconf.getBounds()); - - String str; - - str = System.getProperty("netbeans.screen.insets"); // NOI18N - - if (str != null) { - StringTokenizer st = new StringTokenizer(str, ", "); // NOI18N - - if (st.countTokens() == 4) { - try { - bounds.y = Integer.parseInt(st.nextToken()); - bounds.x = Integer.parseInt(st.nextToken()); - bounds.height -= (bounds.y + Integer.parseInt(st.nextToken())); - bounds.width -= (bounds.x + Integer.parseInt(st.nextToken())); - } catch (NumberFormatException ex) { - LOG.log(Level.WARNING, null, ex); - } - } - - return bounds; - } - - str = System.getProperty("netbeans.taskbar.height"); // NOI18N - - if (str != null) { - bounds.height -= Integer.getInteger(str, 0).intValue(); - - return bounds; - } - - try { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - Insets insets = toolkit.getScreenInsets(gconf); - bounds.y += insets.top; - bounds.x += insets.left; - bounds.height -= (insets.top + insets.bottom); - bounds.width -= (insets.left + insets.right); - } catch (Exception ex) { - LOG.log(Level.WARNING, null, ex); - } - - return bounds; - } - - /** - * Helps client code place components on the center of the screen. It - * handles multiple monitor configuration correctly - * - * @param componentSize the size of the component - * @return bounds of the centered component - * - * @since 2.5 - */ - public static Rectangle findCenterBounds(Dimension componentSize) { - return findCenterBounds(getCurrentGraphicsConfiguration(), componentSize); - } - - /** - * Helps client code place components on the center of the screen. It - * handles multiple monitor configuration correctly - * - * @param gconf the GraphicsConfiguration of the monitor - * @param componentSize the size of the component - * @return bounds of the centered component - */ - private static Rectangle findCenterBounds(GraphicsConfiguration gconf, Dimension componentSize) { - if (gconf == null) { - gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); - } - - Rectangle bounds = gconf.getBounds(); - - return new Rectangle( - bounds.x + ((bounds.width - componentSize.width) / 2), - bounds.y + ((bounds.height - componentSize.height) / 2), componentSize.width, componentSize.height - ); - } - - /** @return size of the screen. The size is modified for Windows OS - * - some points are subtracted to reflect a presence of the taskbar - * - * @deprecated this method is almost useless in multiple monitor configuration - * - * @see #getUsableScreenBounds() - * @see #findCenterBounds(Dimension) - */ - @Deprecated - public static final Dimension getScreenSize() { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - if (isWindows() && !Boolean.getBoolean("netbeans.no.taskbar")) { - screenSize.height -= TYPICAL_WINDOWS_TASKBAR_HEIGHT; - } else if (isMac()) { - screenSize.height -= TYPICAL_MACOSX_MENU_HEIGHT; - } - - return screenSize; - } - - /** Utility method for avoiding of memory leak in JDK 1.3 / JFileChooser.showDialog(...) - * @param parent - * @param approveButtonText - * @deprecated Not needed in JDK 1.4. - * @see FileChooserBuilder - */ - @Deprecated - public static final int showJFileChooser( - javax.swing.JFileChooser chooser, java.awt.Component parent, java.lang.String approveButtonText - ) { - if (approveButtonText != null) { - chooser.setApproveButtonText(approveButtonText); - chooser.setDialogType(javax.swing.JFileChooser.CUSTOM_DIALOG); - } - - Frame frame = null; - Dialog parentDlg = null; - - if (parent instanceof Dialog) { - parentDlg = (Dialog) parent; - } else { - frame = (parent instanceof java.awt.Frame) ? (Frame) parent - : (Frame) javax.swing.SwingUtilities.getAncestorOfClass( - Frame.class, parent - ); - } - - String title = chooser.getDialogTitle(); - - if (title == null) { - title = chooser.getUI().getDialogTitle(chooser); - } - - final javax.swing.JDialog dialog; - - if (parentDlg != null) { - dialog = new javax.swing.JDialog(parentDlg, title, true); - } else { - dialog = new javax.swing.JDialog(frame, title, true); - } - - dialog.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - - Container contentPane = dialog.getContentPane(); - contentPane.setLayout(new BorderLayout()); - contentPane.add(chooser, BorderLayout.CENTER); - - dialog.pack(); - dialog.setBounds(findCenterBounds(parent.getGraphicsConfiguration(), dialog.getSize())); - - chooser.rescanCurrentDirectory(); - - final int[] retValue = {javax.swing.JFileChooser.CANCEL_OPTION}; - - java.awt.event.ActionListener l = new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent ev) { - if (javax.swing.JFileChooser.APPROVE_SELECTION.equals(ev.getActionCommand())) { - retValue[0] = javax.swing.JFileChooser.APPROVE_OPTION; - } - - dialog.setVisible(false); - dialog.dispose(); - } - }; - - chooser.addActionListener(l); - - dialog.show(); - - return retValue[0]; - } - - /** Sort a list according to a specified partial order. - * Note that in the current implementation, the comparator will be called - * exactly once for each distinct pair of list elements, ignoring order, - * so caching its results is a waste of time. - * @param l the list to sort (will not be modified) - * @param c a comparator to impose the partial order; "equal" means that the elements - * are not ordered with respect to one another, i.e. may be only a partial order - * @param stable whether to attempt a stable sort, meaning that the position of elements - * will be disturbed as little as possible; might be slightly slower - * @return the partially-sorted list - * @throws UnorderableException if the specified partial order is inconsistent on this list - * @deprecated Deprecated in favor of the potentially much faster (and possibly more correct) {@link #topologicalSort}. - */ - @SuppressWarnings("unchecked") // do not bother, it is deprecated anyway - @Deprecated - public static List partialSort(List l, Comparator c, boolean stable) - throws UnorderableException { - // map from objects in the list to null or sets of objects they are greater than - // (i.e. must appear after): - Map deps = new HashMap(); // Map> - int size = l.size(); - - // Create a table of dependencies. - for (int i = 0; i < size; i++) { - for (int j = i + 1; j < size; j++) { - int cmp = c.compare(l.get(i), l.get(j)); - - if (cmp != 0) { - Object earlier = l.get((cmp < 0) ? i : j); - Object later = l.get((cmp > 0) ? i : j); - Set s = (Set) deps.get(later); - - if (s == null) { - deps.put(later, s = new HashSet()); - } - - s.add(earlier); - } - } - } - - // Lists of items to process, and items sorted. - List left = new LinkedList(l); - List sorted = new ArrayList(size); - - while (left.size() > 0) { - boolean stillGoing = false; - Iterator it = left.iterator(); - - while (it.hasNext()) { - Object elt = it.next(); - Set eltDeps = (Set) deps.get(elt); - - if ((eltDeps == null) || (eltDeps.size() == 0)) { - // This one is OK to add to the result now. - it.remove(); - stillGoing = true; - sorted.add(elt); - - // Mark other elements that should be later - // than this as having their dep satisfied. - Iterator it2 = left.iterator(); - - while (it2.hasNext()) { - Object elt2 = it2.next(); - Set eltDeps2 = (Set) deps.get(elt2); - - if (eltDeps2 != null) { - eltDeps2.remove(elt); - } - } - - if (stable) { - break; - } - } - } - - if (!stillGoing) { - // Clean up deps to only include "interesting" problems. - it = deps.entrySet().iterator(); - - while (it.hasNext()) { - Map.Entry me = (Map.Entry) it.next(); - - if (!left.contains(me.getKey())) { - it.remove(); - } else { - Set s = (Set) me.getValue(); - Iterator it2 = s.iterator(); - - while (it2.hasNext()) { - if (!left.contains(it2.next())) { - it2.remove(); - } - } - - if (s.isEmpty()) { - it.remove(); - } - } - } - - throw new UnorderableException(left, deps); - } - } - - return sorted; - } - - /** - * Topologically sort some objects. - *

There may not be any nulls among the objects, nor duplicates - * (as per hash/equals), nor duplicates among the edge lists. - * The edge map need not contain an entry for every object, only if it - * has some outgoing edges (empty but not null map values are permitted). - * The edge map shall not contain neither keys nor value entries for objects not - * in the collection to be sorted, if that happens they will be ignored (since version 7.9). - *

The incoming parameters will not be modified; they must not be changed - * during the call and possible calls to TopologicalSortException methods. - * The returned list will support modifications. - *

There is a weak stability guarantee: if there are no edges - * which contradict the incoming order, the resulting list will be in the same - * order as the incoming elements. However if some elements need to be rearranged, - * it is not guaranteed that others will not also be rearranged, even - * if they did not strictly speaking need to be. - * @param c a collection of objects to be topologically sorted - * @param edges constraints among those objects, of type Map<Object,Collection>; - * if an object is a key in this map, the resulting order will - * have that object before any objects listed in the value - * @return a partial ordering of the objects in the collection, - * @exception TopologicalSortException if the sort cannot succeed due to cycles in the graph, the - * exception contains additional information to describe and possibly recover from the error - * @since 3.30 - * @see Issue #27286 - */ - public static List topologicalSort(Collection c, Map> edges) - throws TopologicalSortException { - Map finished = new HashMap(); - List r = new ArrayList(Math.max(c.size(), 1)); - List cRev = new ArrayList(c); - Collections.reverse(cRev); - - Iterator it = cRev.iterator(); - - while (it.hasNext()) { - List cycle = visit(it.next(), edges, finished, r); - - if (cycle != null) { - throw new TopologicalSortException(cRev, edges); - } - } - - Collections.reverse(r); - if (r.size() != c.size()) { - r.retainAll(c); - } - - return r; - } - - /** - * Visit one node in the DAG. - * @param node node to visit - * @param edges edges in the DAG - * @param finished which nodes are finished; a node has no entry if it has not yet - * been visited, else it is set to false while recurring and true - * when it has finished - * @param r the order in progress - * @return list with detected cycle - */ - static List visit( - T node, - Map> edges, - Map finished, - List r - ) { - Boolean b = finished.get(node); - - //System.err.println("node=" + node + " color=" + b); - if (b != null) { - if (b.booleanValue()) { - return null; - } - - ArrayList cycle = new ArrayList(); - cycle.add(node); - finished.put(node, null); - - return cycle; - } - - Collection e = edges.get(node); - - if (e != null) { - finished.put(node, Boolean.FALSE); - - Iterator it = e.iterator(); - - while (it.hasNext()) { - List cycle = visit(it.next(), edges, finished, r); - - if (cycle != null) { - if (cycle instanceof ArrayList) { - // if cycle instanceof ArrayList we are still in the - // cycle and we want to collect new members - if (Boolean.FALSE == finished.get(node)) { - // another member in the cycle - cycle.add(node); - } else { - // we have reached the head of the cycle - // do not add additional cycles anymore - Collections.reverse(cycle); - - // changing cycle to not be ArrayList - cycle = Collections.unmodifiableList(cycle); - } - } - - // mark this node as tested - finished.put(node, Boolean.TRUE); - - // and report an error - return cycle; - } - } - } - - finished.put(node, Boolean.TRUE); - r.add(node); - - return null; - } - - /** Provides support for parts of the system that deal with classnames - * (use Class.forName, NbObjectInputStream, etc.). - *

- * Often class names (especially package names) changes during lifecycle - * of a module. When some piece of the system stores the name of a class - * in certain point of a time and wants to find the correct Class - * later it needs to count with the possibility of rename. - *

- * For such purposes this method has been created. It allows modules to - * register their classes that changed names and other parts of system that - * deal with class names to find the correct names. - *

- * To register a mapping from old class names to new ones create a file - * META-INF/netbeans/translate.names in your module and fill it - * with your mapping: - *

-     * #
-     * # Mapping of legacy classes to new ones
-     * #
-     *
-     * org.oldpackage.MyClass=org.newpackage.MyClass # rename of package for one class
-     * org.mypackage.OldClass=org.mypackage.NewClass # rename of class in a package
-     *
-     * # rename of class and package
-     * org.oldpackage.OldClass=org.newpackage.NewClass
-     *
-     * # rename of whole package
-     * org.someoldpackage=org.my.new.package.structure
-     *
-     * # class was removed without replacement
-     * org.mypackage.OldClass=
-     *
-     * 
- * Btw. one can use spaces instead of = sign. - * For a real world example - * check the - * - * xml module. - * - *

- * For purposes of org.openide.util.io.NbObjectInputStream there is - * a following special convention: - * If the - * className is not listed as one that is to be renamed, the returned - * string == className, if the className is registered to be renamed - * than the className != returned value, even in a case when className.equals (retValue) - * - * @param className fully qualified name of a class to translate - * @return new name of the class according to renaming rules. - */ - public static String translate(final String className) { - checkMapping(); - - RE exp; - - synchronized (TRANS_LOCK) { - exp = transExp; - } - - if (exp == null) { - // no transition table found - return className; - } - - synchronized (exp) { - // refusing convertions as fast as possible - return exp.convert(className); - } - } - - /** Loads all resources that contain renaming information. - * @param l classloader to load packages from - */ - private static void checkMapping() { - // test if we run in test mode - if (transLoader == TRANS_LOCK) { - // no check - return; - } - - ClassLoader current = Lookup.getDefault().lookup(ClassLoader.class); - - if (current == null) { - current = ClassLoader.getSystemClassLoader(); - } - - if (transLoader == current) { - // no change, no rescan - return; - } - - initForLoader(current, current); - } - - /* Initializes the content of transition table from a classloader. - * @param loader loader to read data from - * @param set loader to set as the transLoader or null if we run in test mode - */ - static void initForLoader(ClassLoader current, Object set) { - if (set == null) { - set = TRANS_LOCK; - } - - Enumeration en; - - try { - en = current.getResources("META-INF/netbeans/translate.names"); - } catch (IOException ex) { - LOG.log(Level.WARNING, null, ex); - en = null; - } - - if ((en == null) || !en.hasMoreElements()) { - synchronized (TRANS_LOCK) { - transLoader = set; - transExp = null; - } - - return; - } - - // format of line in the meta files - // - // # comments are allowed - // a.name.in.a.Package=another.Name # with comment is allowed - // for.compatibility.one.can.use.Space instead.of.Equal - // - RE re = null; - - // [pnejedly:perf] commented out. The RegExp based translation was way slower - // than the hand-written RE13 - // if (Dependency.JAVA_SPEC.compareTo(new SpecificationVersion("1.4")) >= 0) { // NOI18N - // try { - // re = (RE)Class.forName ("org.openide.util.RE14").newInstance (); - // } catch (ThreadDeath t) { - // throw t; - // } catch (Throwable t) { - // } - // } - // if (re == null) { - re = new RE13(); - - // } - TreeSet list = new TreeSet( - new Comparator() { - public int compare(String[] o1, String[] o2) { - String s1 = o1[0]; - String s2 = o2[0]; - - int i1 = s1.length(); - int i2 = s2.length(); - - if (i1 != i2) { - return i2 - i1; - } - - return s2.compareTo(s1); - } - } - ); - - while (en.hasMoreElements()) { - URL u = (URL) en.nextElement(); - - try { - BufferedReader reader = new BufferedReader( - new InputStreamReader(u.openStream(), "UTF8") // use explicit encoding //NOI18N - ); - loadTranslationFile(re, reader, list); - reader.close(); - } catch (IOException ex) { - LOG.log(Level.WARNING, "Problematic file: " + u); - LOG.log(Level.WARNING, null, ex); - } - } - - // construct a regular expression of following form. Let "1", "2", "3", "4" - // be the keys: - // "^ - // thus if 4 is matched five groups will be created - String[] arr = new String[list.size()]; - String[] pattern = new String[arr.length]; - - int i = 0; - Iterator it = list.iterator(); - - while (it.hasNext()) { - String[] pair = (String[]) it.next(); - arr[i] = pair[1].intern(); // name of the track - pattern[i] = pair[0]; // original object - i++; - } - - synchronized (TRANS_LOCK) { - // last check - if (arr.length == 0) { - transExp = null; - } else { - transExp = re; - transExp.init(pattern, arr); - } - - transLoader = set; - } - } - - /** - * Load single translation file. - * @param resource URL identifiing transaction table - * @param results will be filled with String[2] - */ - private static void loadTranslationFile(RE re, BufferedReader reader, Set results) - throws IOException { - for (;;) { - String line = reader.readLine(); - - if (line == null) { - break; - } - - if ((line.length() == 0) || line.startsWith("#")) { // NOI18N - - continue; - } - - String[] pair = re.readPair(line); - - if (pair == null) { - throw new java.io.InvalidObjectException("Line is invalid: " + line); - } - - results.add(pair); - } - } - - /** This method merges two images into the new one. The second image is drawn - * over the first one with its top-left corner at x, y. Images need not be of the same size. - * New image will have a size of max(second image size + top-left corner, first image size). - * Method is used mostly when second image contains transparent pixels (e.g. for badging). - * @param image1 underlying image - * @param image2 second image - * @param x x position of top-left corner - * @param y y position of top-left corner - * @return new merged image - * @deprecated Use {@link ImageUtilities#mergeImages}. - */ - @Deprecated - public static final Image mergeImages(Image image1, Image image2, int x, int y) { - return ImageUtilities.mergeImages(image1, image2, x, y); - } - - /** - * Loads an image from the specified resource ID. The image is loaded using the "system" classloader registered in - * Lookup. - * @param resourceID resource path of the icon (no initial slash) - * @return icon's Image, or null, if the icon cannot be loaded. - * @deprecated Use {@link ImageUtilities#loadImage(java.lang.String)}. - */ - @Deprecated - public static final Image loadImage(String resourceID) { - return ImageUtilities.loadImage(resourceID); - } - - /** - * Converts given icon to a {@link java.awt.Image}. - * - * @param icon {@link javax.swing.Icon} to be converted. - * @since 7.3 - * @deprecated Use {@link ImageUtilities#icon2Image}. - */ - @Deprecated - public static final Image icon2Image(Icon icon) { - return ImageUtilities.icon2Image(icon); - } - - /** Builds a popup menu from actions for provided context specified by - * Lookup. - * Takes list of actions and for actions whic are instances of - * ContextAwareAction creates and uses the context aware instance. - * Then gets the action presenter or simple menu item for the action to the - * popup menu for each action (or separator for each 'lonely' null array member). - * - * @param actions array of actions to build menu for. Can contain null - * elements, they will be replaced by separators - * @param context the context for which the popup is build - * @return the constructed popup menu - * @see ContextAwareAction - * @since 3.29 - */ - public static JPopupMenu actionsToPopup(Action[] actions, Lookup context) { - // keeps actions for which was menu item created already (do not add them twice) - Set counted = new HashSet(); - // components to be added (separators are null) - List components = new ArrayList(); - - for (Action action : actions) { - if (action != null && counted.add(action)) { - // switch to replacement action if there is some - if (action instanceof ContextAwareAction) { - Action contextAwareAction = ((ContextAwareAction) action).createContextAwareInstance(context); - if (contextAwareAction == null) { - Logger.getLogger(Utilities.class.getName()).warning( - "ContextAwareAction.createContextAwareInstance(context) returns null. That is illegal!" // NOI18N - + " action=" + action + ", context=" + context); // NOI18N - } else { - action = contextAwareAction; - } - } - - JMenuItem item; - if (action instanceof Presenter.Popup) { - item = ((Presenter.Popup) action).getPopupPresenter(); - if (item == null) { - Logger.getLogger(Utilities.class.getName()).warning( - "findContextMenuImpl, getPopupPresenter returning null for " + action); // NOI18N - continue; - } - } else { - // We need to correctly handle mnemonics with '&' etc. - item = ActionPresenterProvider.getDefault().createPopupPresenter(action); - } - - for (Component c : ActionPresenterProvider.getDefault().convertComponents(item)) { - if (c instanceof JSeparator) { - components.add(null); - } else { - components.add(c); - } - } - } else { - components.add(null); - } - } - - // Now create actual menu. Strip adjacent, leading, and trailing separators. - JPopupMenu menu = ActionPresenterProvider.getDefault().createEmptyPopup(); - boolean nonempty = false; // has anything been added yet? - boolean pendingSep = false; // should there be a separator before any following item? - for (Component c : components) { - if (c == null) { - pendingSep = nonempty; - } else { - nonempty = true; - if (pendingSep) { - pendingSep = false; - menu.addSeparator(); - } - menu.add(c); - } - } - return menu; - } - - /** Builds a popup menu for provided component. It retrieves context - * (lookup) from provided component instance or one of its parent - * (it searches up to the hierarchy for Lookup.Provider instance). - * If none of the components is Lookup.Provider instance, then - * it is created context which is fed with composite ActionMap which delegates - * to all components up to hierarchy started from the specified one. - * Then actionsToPopup(Action[], Lookup)} is called with - * the found Lookup instance, which actually creates a popup menu. - * - * @param actions array of actions to build menu for. Can contain null - * elements, they will be replaced by separators - * @param component a component in which to search for a context - * @return the constructed popup menu - * @see Lookup.Provider - * @see #actionsToPopup(Action[], Lookup) - * @since 3.29 - */ - public static javax.swing.JPopupMenu actionsToPopup(Action[] actions, java.awt.Component component) { - Lookup lookup = null; - - for (Component c = component; c != null; c = c.getParent()) { - if (c instanceof Lookup.Provider) { - lookup = ((Lookup.Provider) c).getLookup(); - - if (lookup != null) { - break; - } - } - } - - if (lookup == null) { - // Fallback to composite action map, even it is questionable, - // whether we should support component which is not (nor - // none of its parents) lookup provider. - UtilitiesCompositeActionMap map = new UtilitiesCompositeActionMap(component); - lookup = org.openide.util.lookup.Lookups.singleton(map); - } - - return actionsToPopup(actions, lookup); - } - - /** - * Load a menu sequence from a lookup path. - * Any {@link Action} instances are returned as is; - * any {@link JSeparator} instances are translated to nulls. - * Warnings are logged for any other instances. - * @param path a path as given to {@link Lookups#forPath}, generally a layer folder name - * @return a list of actions interspersed with null separators - * @since org.openide.util 7.14 - */ - public static List actionsForPath(String path) { - List actions = new ArrayList(); - for (Lookup.Item item : Lookups.forPath(path).lookupResult(Object.class).allItems()) { - if (Action.class.isAssignableFrom(item.getType())) { - Object instance = item.getInstance(); - if (instance != null) { - actions.add((Action) instance); - } - } else if (JSeparator.class.isAssignableFrom(item.getType())) { - actions.add(null); - } else { - Logger.getLogger(Utilities.class.getName()).warning("Unrecognized object of " + item.getType() + " found in actions path " + path); - } - } - return actions; - } - - /** - * Global context for actions. Toolbar, menu or any other "global" - * action presenters shall operate in this context. - * Presenters for context menu items should not use - * this method; instead see {@link ContextAwareAction}. - * @see ContextGlobalProvider - * @see ContextAwareAction - * @see NetBeans FAQ - * @return the context for actions - * @since 4.10 - */ - public static Lookup actionsGlobalContext() { - synchronized (ContextGlobalProvider.class) { - if (global != null) { - return global; - } - } - - ContextGlobalProvider p = Lookup.getDefault().lookup(ContextGlobalProvider.class); - Lookup l = (p == null) ? Lookup.EMPTY : p.createGlobalContext(); - - synchronized (ContextGlobalProvider.class) { - if (global == null) { - global = l; - } - - return global; - } - } - - // - // end of actions stuff - // - - /** - * Loads an image based on resource path. - * Exactly like {@link #loadImage(String)} but may do a localized search. - * For example, requesting org/netbeans/modules/foo/resources/foo.gif - * might actually find org/netbeans/modules/foo/resources/foo_ja.gif - * or org/netbeans/modules/foo/resources/foo_mybranding.gif. - * - *

Caching of loaded images can be used internally to improve performance. - * - * @since 3.24 - * @deprecated Use {@link ImageUtilities#loadImage(java.lang.String, boolean)}. - */ - @Deprecated - public static final Image loadImage(String resource, boolean localized) { - return ImageUtilities.loadImage(resource, localized); - } - - /** - * Returns a cursor with an arrow and an hourglass (or stop watch) badge, - * to be used when a component is busy but the UI is still responding to the user. - * - * Similar to the predefined {@link Cursor#WAIT_CURSOR}, but has an arrow to indicate - * a still-responsive UI. - * - *

Typically you will set the cursor only temporarily: - * - *

-     *  // code is running in other then event dispatch thread
-     *  currentComponent.setCursor(Utilities.createProgressCursor(currentComponent));
-     *  try {
-     *      // perform some work in other than event dispatch thread
-     *      // (do not block UI)
-     *  } finally {
-     *      currentComponent.setCursor(null);
-     *  }
-     *  
- * - *

This implementation provides one cursor for all Mac systems, one for all - * Unix systems (regardless of window manager), and one for all other systems - * including Windows. Note: The cursor does not have to look native in some - * cases on some platforms! - * - * @param component the non-null component that will use the progress cursor - * @return a progress cursor (Unix, Windows or Mac) - * - * @since 3.23 - */ - public static final Cursor createProgressCursor(Component component) { - // refuse null component - if (component == null) { - throw new NullPointerException("Given component is null"); //NOI18N - } - - Image image = null; - - // First check for Mac because its part of the Unix_Mask - if (isMac()) { - image = ImageUtilities.loadImage("org/openide/util/progress-cursor-mac.gif"); //NOI18N - } else if (isUnix()) { - image = ImageUtilities.loadImage("org/openide/util/progress-cursor-motif.gif"); //NOI18N - } - // All other OS, including Windows, use Windows cursor - else { - image = ImageUtilities.loadImage("org/openide/util/progress-cursor-win.gif"); //NOI18N - } - - return createCustomCursor(component, image, "PROGRESS_CURSOR"); //NOI18N - } - - // added to fix issue #30665 (bad size on linux) - public static Cursor createCustomCursor(Component component, Image icon, String name) { - Toolkit t = component.getToolkit(); - Dimension d = t.getBestCursorSize(16, 16); - Image i = icon; - - if (d.width != icon.getWidth(null)) { - if (((d.width) == 0) && (d.height == 0)) { - // system doesn't support custom cursors, falling back - return Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); - } - - // need to resize the icon - Image empty = ImageUtilities.createBufferedImage(d.width, d.height); - i = ImageUtilities.mergeImages(icon, empty, 0, 0); - } - - return t.createCustomCursor(i, new Point(1, 1), name); - } - - /** Attaches asynchronous init job to given component. - * {@link AsyncGUIJob#construct()} will be called after first - * paint, when paint event arrives. Later, {@link AsyncGUIJob#finished()} - * will be called according to the rules of the AsyncGUIJob interface. - * - * Useful for components that have slower initialization phase, component - * can benefit from more responsive behaviour during init. - * - * @param comp4Init Regular component in its pre-inited state, state in which - * component will be shown between first paint and init completion. - * @param initJob Initialization job to be called asynchronously. Job can - * optionally implement {@link Cancellable} - * interface for proper cancel logic. Cancel method will be called - * when component stops to be showing during job's progress. - * See {@link java.awt.Component#isShowing} - * - * @since 3.36 - */ - public static final void attachInitJob(Component comp4Init, AsyncGUIJob initJob) { - new AsyncInitSupport(comp4Init, initJob); - } - - /** - * Convert a file to a matching file: URL. - * @param f a file (absolute only) - * @return a URL using the file protocol - * @throws MalformedURLException for no good reason - * @see #toFile - * @see Issue #29711 - * @since 3.26 - * @deprecated Use {@link File#toURI} and {@link URI#toURL} instead under JDK 1.4. - * ({@link File#toURL} is buggy in JDK 1.3 and the bugs are not fixed in JDK 1.4.) - */ - @Deprecated - public static URL toURL(File f) throws MalformedURLException { - if (f == null) { - throw new NullPointerException(); - } - - if (!f.isAbsolute()) { - throw new IllegalArgumentException("Relative path: " + f); // NOI18N - } - - URI uri = f.toURI(); - - return uri.toURL(); - } - - /** - * Convert a file: URL to a matching file. - *

You may not use a URL generated from a file on a different - * platform, as file name conventions may make the result meaningless - * or even unparsable. - * @param u a URL with the file protocol - * @return an absolute file it points to, or null if the URL - * does not seem to point to a file at all - * @see #toURL - * @see Issue #29711 - * @since 3.26 - * @deprecated Use {@link URI#URI(String)} and {@link File#File(URI)} instead under JDK 1.4. - * (There was no proper equivalent under JDK 1.3.) - */ - @Deprecated - public static File toFile(URL u) { - if (u == null) { - throw new NullPointerException(); - } - - try { - URI uri = new URI(u.toExternalForm()); - - return new File(uri); - } catch (URISyntaxException use) { - // malformed URL - return null; - } catch (IllegalArgumentException iae) { - // not a file: URL - return null; - } - } - - /** Interfaces for communication between Utilities.translate and regular - * expression impl. - * - * Order of methods is: - * readPair few times - * init once - * convert many times - */ - static interface RE { - public void init(String[] original, String[] newversion); - - public String convert(String pattern); - - /** Parses line of text to two parts: the key and the rest - */ - public String[] readPair(String line); - } - - /** Exception indicating that a given list could not be partially-ordered. - * @see #partialSort - * @deprecated Used only by the deprecated partialSort - */ - @Deprecated - public static class UnorderableException extends RuntimeException { - static final long serialVersionUID = 6749951134051806661L; - private Collection unorderable; - private Map deps; - - /** Create a new unorderable-list exception with no detail message. - * @param unorderable a collection of list elements which could not be ordered - * (because there was some sort of cycle) - * @param deps dependencies associated with the list; a map from list elements - * to sets of list elements which that element must appear after - */ - public UnorderableException(Collection unorderable, Map deps) { - super( /* "Cannot be ordered: " + unorderable */ - ); // NOI18N - this.unorderable = unorderable; - this.deps = deps; - } - - /** Create a new unorderable-list exception with a specified detail message. - * @param message the detail message - * @param unorderable a collection of list elements which could not be ordered - * (because there was some sort of cycle) - * @param deps dependencies associated with the list; a map from list elements - * to sets of list elements which that element must appear after - */ - public UnorderableException(String message, Collection unorderable, Map deps) { - super(message); - this.unorderable = unorderable; - this.deps = deps; - } - - /** Get the unorderable elements. - * @return the elements - * @see Utilities.UnorderableException#Utilities.UnorderableException(Collection,Map) - */ - public Collection getUnorderable() { - return unorderable; - } - - /** Get the dependencies. - * @return the dependencies - * @see Utilities.UnorderableException#Utilities.UnorderableException(Collection,Map) - */ - public Map getDeps() { - return deps; - } - } -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/WeakSet.java --- a/openide.util/src/org/openide/util/WeakSet.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,579 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.AbstractSet; -import java.util.ArrayList; -import java.util.Collection; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** Set which holds its members by using of WeakReferences. -* MT level: unsafe. - *

Note: you can instead use - *

- * Set<T> s = Collections.newSetFromMap(new WeakHashMap<T, Boolean>());
- * 
-* -* @author Ales Novak -*/ -public class WeakSet extends AbstractSet implements Cloneable, Serializable { - static final long serialVersionUID = 3062376055928236721L; - - /** load factor */ - private float loadFactor; - - /** Number of items. */ - private int size; - - /** Modification count */ - private long modcount; - - /** Reference queue of collected weak refs */ - private transient ReferenceQueue refq; - - /** Count of null in this set */ - long nullCount; - - /** An array of Entries */ - private transient Entry[] entries; - transient Entry iterChain; - - /** Constructs a new set. */ - public WeakSet() { - this(11, 0.75f); - } - - /** Constructs a new set containing the elements in the specified collection. - * @param c a collection to add - */ - public WeakSet(Collection c) { - this(); - addAll(c); - } - - /** Constructs a new, empty set; - * @param initialCapacity initial capacity - */ - public WeakSet(int initialCapacity) { - this(initialCapacity, 0.75f); - } - - /** Constructs a new, empty set; - * - * @param initialCapacity initial capacity - * @param loadFactor load factor - */ - public WeakSet(int initialCapacity, float loadFactor) { - if ((initialCapacity <= 0) || (loadFactor <= 0)) { - throw new IllegalArgumentException(); - } - - size = 0; - modcount = 0; - this.loadFactor = loadFactor; - nullCount = 0; - refq = new ReferenceQueue(); - entries = Entry.createArray(initialCapacity); - iterChain = null; - } - - /** - * logs iterator chain (for debugging) - * @param msg - */ - void logIterChain(String msg) { - Logger log = Logger.getLogger(WeakSet.class.getName()); - log.log(Level.FINE, msg); - if (iterChain == null) { - log.log(Level.FINE, "Empty"); - return; - } - StringBuilder str = new StringBuilder(); - Entry it = iterChain; - str.append(size + ": "); - while (it != null) { - str.append(it.get() + "(" + it.hashcode + ")" + "->"); - it = it.iterChainNext; - } - log.log(Level.FINE, str.toString()); - } - - /** Adds the specified element to this set if it is not already present. - * - * @param o an Object to add - */ - public boolean add(E o) { - if (o == null) { - size++; - nullCount++; - modcount++; - - return true; - } - - Entry e = object2Entry(o); - - if (e != null) { - return false; - } - - modcount++; - size++; - - int hash = hashIt(o); - Entry next = entries[hash]; - iterChain = entries[hash] = new Entry(this, o, refq, next, iterChain); - rehash(); - - return true; - } - - /** Removes all of the elements from this set. */ - public void clear() { - for (int i = 0; i < entries.length; i++) { - entries[i] = null; - } - - nullCount = 0; - modcount++; - size = 0; - iterChain = null; - } - - /** Returns a shallow copy of this WeakSet instance: the elements themselves are not cloned. */ - public Object clone() { - WeakSet nws = new WeakSet(1, loadFactor); - nws.size = size; - nws.nullCount = nullCount; - - Entry[] cloned = Entry.createArray(entries.length); - nws.entries = cloned; - - for (int i = 0; i < cloned.length; i++) { - Object ref; - - if ((entries[i] == null) || ((ref = entries[i].get()) == null)) { - cloned[i] = null; - } else { - cloned[i] = ((entries[i] == null) ? null : entries[i].clone(nws.refq)); - ref = null; - } - - // chains into nws iterator chain - Entry entry = cloned[i]; - - while (entry != null) { - entry.chainIntoIter(nws.iterChain); - nws.iterChain = entry; - entry = entry.next; - } - } - - return nws; - } - - /** Returns true if this set contains the specified element. - * - * @param o an Object to examine - */ - public boolean contains(Object o) { - if (o == null) { - return nullCount > 0; - } - - return object2Entry(o) != null; - } - - /** Returns true if this set contains no elements. - */ - public boolean isEmpty() { - return ((nullCount == 0) && (size() == 0)); - } - - /** Returns an iterator over the elements in this set. */ - public Iterator iterator() { - return new WeakSetIterator(); - } - - /** Removes the given element from this set if it is present. - * - * @param o an Object to remove - * @return true if and only if the Object was successfuly removed. - */ - public boolean remove(Object o) { - if (o == null) { - if (nullCount > 0) { - nullCount--; - modcount++; - size--; - } - - return true; - } - - Entry e = object2Entry(o); - - if (e != null) { - modcount++; - size--; - e.remove(); - rehash(); - - return true; - } - - return false; - } - - /** @return the number of elements in this set (its cardinality). */ - public int size() { - checkRefQueue(); - - return size; - } - - public T[] toArray(T[] array) { - ArrayList list = new ArrayList(array.length); - Iterator it = iterator(); - - while (it.hasNext()) { - list.add(it.next()); - } - - return list.toArray(array); - } - - public Object[] toArray() { - ArrayList list = new ArrayList(); - Iterator it = iterator(); - - while (it.hasNext()) { - list.add(it.next()); - } - - return list.toArray(); - } - - // #14772 - public String toString() { - StringBuffer buf = new StringBuffer(); - Iterator e = iterator(); - buf.append("["); - - while (e.hasNext()) { - buf.append(String.valueOf(e.next())); - - if (e.hasNext()) { - buf.append(", "); - } - } - - buf.append("]"); - - return buf.toString(); - } - - /** Checks if the queue is empty if not pending weak refs are removed. */ - void checkRefQueue() { - for (;;) { - Entry entry = Entry.class.cast(refq.poll()); - - if (entry == null) { - break; - } - - entry.remove(); - size--; - } - } - - /** @return modcount */ - long modCount() { - return modcount; - } - - /** @return an index to entries array */ - int hashIt(Object o) { - return (o.hashCode() & 0x7fffffff) % entries.length; - } - - /** rehashes this Set */ - void rehash() { - /* - float currentLF = ((float) size) / ((float) entries.length); - if (currentLF < loadFactor) { - return; - } - */ - } - - /** @return an Entry with given object */ - private Entry object2Entry(Object o) { - checkRefQueue(); // clear ref q - - int hash = hashIt(o); - Entry e = entries[hash]; - - if (e == null) { - return null; - } - - while ((e != null) && !e.equals(o)) { - e = e.next; - } - - return e; - } - - private void writeObject(ObjectOutputStream obtos) - throws IOException { - obtos.defaultWriteObject(); - obtos.writeObject(toArray()); - } - - @SuppressWarnings("unchecked") - private void readObject(ObjectInputStream obtis) throws IOException, ClassNotFoundException { - obtis.defaultReadObject(); - - Object[] arr = (Object[]) obtis.readObject(); - entries = new Entry[(int) (size * 1.5)]; - refq = new ReferenceQueue(); - - for (int i = 0; i < arr.length; i++) { - add((E)arr[i]); - } - } - - class WeakSetIterator implements Iterator { - Entry current; - Entry next; - E currentObj; - E nextObj; - final long myModcount; - long myNullCount; - - WeakSetIterator() { - myModcount = modCount(); - myNullCount = nullCount; - current = null; - next = null; - - Entry ee = iterChain; - - if (ee == null) { - return; - } - - E o = ee.get(); - - while (ee.isEnqueued()) { - ee = ee.iterChainNext; - - if (ee == null) { - return; - } - - o = ee.get(); - } - - nextObj = o; - next = ee; - } - - public boolean hasNext() { - checkModcount(); - - return ((myNullCount > 0) || (next != null)); - } - - public E next() { - checkModcount(); - checkRefQueue(); - - if (myNullCount > 0) { - myNullCount--; - - return null; - } else { - if (next == null) { - throw new java.util.NoSuchElementException(); - } - - current = next; - currentObj = nextObj; - - // move to next requested - do { - next = next.iterChainNext; - - if (next == null) { - break; - } - - nextObj = next.get(); - } while (next.isEnqueued()); - - return currentObj; - } - } - - public void remove() { - checkModcount(); - - if (current == null) { - throw new IllegalStateException(); - } - - current.remove(); - size--; - } - - void checkModcount() { - if (myModcount != modCount()) { - throw new ConcurrentModificationException(); - } - } - } - - /** Entries of this set */ - static class Entry extends WeakReference { - /** reference to outer WeakSet */ - private WeakSet set; - - // double linked list - Entry prev; - Entry next; - private final int hashcode; - Entry iterChainNext; - Entry iterChainPrev; - - Entry(WeakSet set, E referenced, ReferenceQueue q, Entry next, Entry nextInIter) { - super(referenced, q); - this.set = set; - - this.next = next; - this.prev = null; - - if (next != null) { - next.prev = this; - } - - if (referenced != null) { - hashcode = set.hashIt(referenced); - } else { - hashcode = 0; - } - - chainIntoIter(nextInIter); - } - - @SuppressWarnings("unchecked") - static final Entry[] createArray(int size) { - return new Entry[size]; - } - - void chainIntoIter(Entry nextInIter) { - iterChainNext = nextInIter; - - if (nextInIter != null) { - nextInIter.iterChainPrev = this; - } - } - - /** deques itself */ - void remove() { - if (prev != null) { - prev.next = next; - } - - if (next != null) { - next.prev = prev; - } - - if (iterChainNext != null) { - iterChainNext.iterChainPrev = iterChainPrev; - } - - if (iterChainPrev != null) { - iterChainPrev.iterChainNext = iterChainNext; - } else { // root - set.iterChain = iterChainNext; - } - - if (set.entries[hashcode] == this) { - set.entries[hashcode] = next; - } - - prev = null; - next = null; - iterChainNext = null; - iterChainPrev = null; - } - - public int hashCode() { - return hashcode; - } - - public boolean equals(Object o) { - Object oo = get(); - - if (oo == null) { - return false; - } else { - return oo.equals(o); - } - } - - public Entry clone(ReferenceQueue q) { - return new Entry(set, get(), q, next != null ? next.clone(q) : null, null); - } - } -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/actions/ActionInvoker.java --- a/openide.util/src/org/openide/util/actions/ActionInvoker.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.actions; - -import java.awt.event.ActionEvent; -import java.beans.PropertyChangeListener; -import javax.swing.Action; -import org.openide.util.Lookup; -import org.openide.util.RequestProcessor; -import org.openide.util.actions.SystemAction; -import org.openide.util.lookup.ServiceProvider; - -/** A mixture of a utility class allowing to invoke actions and also a - * - * code injection mechanism to allow overall system to be aware of invoked - * actions. - *

- * Callers shall use the {@link #invokeAction(javax.swing.Action, java.awt.event.ActionEvent, boolean, java.lang.Runnable)} - * method. - *

- * Implementors register an implementation of this class via {@link ServiceProvider} - * annotation. - * - * @since 8.1 - */ -public abstract class ActionInvoker extends Object { - /** thread to run actions in */ - private static final RequestProcessor RP = new RequestProcessor("Module-Actions", Integer.MAX_VALUE); // NOI18N - - /** Subclass constructor. */ - protected ActionInvoker() {} - - /** An infrastructure method that handles invocation of an an action. - * @param action the action to invoke - * @param ev the event used during invocation - */ - protected abstract void invokeAction(Action action, ActionEvent ev); - - /** Invokes the action in the currently registered ActionsBridge. - * - * @param action the action that is to be invoked - * @param ev the event used to invoke the action - * @param asynchronous shall the execution be performed in a background thread? - * @param invoker the actual code that shall be performed to "run" the action. If null, action.actionPerformed(ev) will be called - */ - public static void invokeAction(Action action, ActionEvent ev, boolean asynchronous, final Runnable invoker) { - ActionRunnable r = new ActionRunnable(ev, action, asynchronous) { - @Override - protected void run() { - if (invoker == null) { - action.actionPerformed(ev); - } else { - invoker.run(); - } - } - }; - doPerformAction(action, r); - } - - private static void doPerformAction(Action action, final ActionInvoker.ActionRunnable r) { - assert java.awt.EventQueue.isDispatchThread() : "Action " + action.getClass().getName() + - " may not be invoked from the thread " + Thread.currentThread().getName() + - ", only the event queue: http://www.netbeans.org/download/4_1/javadoc/OpenAPIs/apichanges.html#actions-event-thread"; - - if (r.async && !r.needsToBeSynchronous()) { - Runnable r2 = new Runnable() { - public void run() { - r.doRun(); - } - }; - - RP.post(r2); - } else { - r.run(); - } - } - - /** Special class that can be passed to invokeAction and delegates - * to correct values - */ - private static abstract class ActionRunnable implements Action { - final ActionEvent ev; - final Action action; - final boolean async; - - public ActionRunnable(ActionEvent ev, SystemAction action, boolean async) { - this(ev, (Action)action, async); - } - public ActionRunnable(ActionEvent ev, Action action, boolean async) { - this.ev = ev; - this.action = action; - this.async = async; - } - - public static ActionRunnable create(ActionEvent ev, Action a, boolean async) { - return new ActionRunnable(ev, a, async) { - @Override - protected void run() { - action.actionPerformed(ev); - } - }; - } - - public final boolean needsToBeSynchronous() { - return "waitFinished".equals(ev.getActionCommand()); // NOI18N - } - - public final void doRun() { - ActionInvoker bridge = Lookup.getDefault().lookup(ActionInvoker.class); - if (bridge != null) { - bridge.invokeAction (this, ev); - } else { - this.actionPerformed(ev); - } - } - - protected abstract void run(); - - public final void actionPerformed(ActionEvent e) { - run(); - } - - public final void addPropertyChangeListener(PropertyChangeListener listener) { - throw new UnsupportedOperationException(); - } - - public final Object getValue(String key) { - return action.getValue(key); - } - - public final boolean isEnabled() { - return action.isEnabled(); - } - - public final void putValue(String key, Object value) { - throw new UnsupportedOperationException(); - } - - public final void removePropertyChangeListener(PropertyChangeListener listener) { - throw new UnsupportedOperationException(); - } - - public final void setEnabled(boolean b) { - throw new UnsupportedOperationException(); - } - } - // end of ActionRunnable -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/actions/ActionPresenterProvider.java --- a/openide.util/src/org/openide/util/actions/ActionPresenterProvider.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.actions; - -import java.awt.Component; -import javax.swing.Action; -import javax.swing.JButton; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import org.openide.util.Lookup; - -/** Provider of action presentations. Based on type of the action - * should be able to derive its menu, popup menu and toolbar - * presenter. - *

- * In order to provide greater flexibility this is made as a pluggable component - * to allow other parts of the system to provide more enhanced - * visualizations. - * @since 8.1 - */ -public abstract class ActionPresenterProvider extends Object { - /** Gets the default implementation from lookup. - * @return the presenter - */ - public static ActionPresenterProvider getDefault () { - ActionPresenterProvider ap = Lookup.getDefault().lookup(ActionPresenterProvider.class); - return ap == null ? new Default () : ap; - } - - /** Subclass constructor. */ - protected ActionPresenterProvider() {} - - /** Creates a default empty implementation of popup menu. - * @return popup menu - */ - public abstract JPopupMenu createEmptyPopup(); - - /** Creates a menu item that can present this action in a {@link javax.swing.JMenu}. - * @param action the action to represent - * @return the representation for this action - */ - public abstract JMenuItem createMenuPresenter (Action action); - - /** Get a menu item that can present this action in a {@link javax.swing.JPopupMenu}. - * @param action the action to represent - * @return the representation for this action - */ - public abstract JMenuItem createPopupPresenter (Action action); - - /** Get a component that can present this action in a {@link javax.swing.JToolBar}. - * @param action the action to represent - * @return the representation for this action - */ - public abstract Component createToolbarPresenter (Action action); - - /** - * Used for implementation of DynamicMenuContent. - * @param comp a component - * @return zero or more components to display in its place - */ - public abstract Component[] convertComponents(Component comp); - - // - // Default implementation of the the presenter - // - - private static final class Default extends ActionPresenterProvider { - - public JMenuItem createMenuPresenter(Action action) { - return new JMenuItem(action); - } - - public JMenuItem createPopupPresenter(Action action) { - return new JMenuItem(action); - } - - public Component createToolbarPresenter(Action action) { - return new JButton(action); - } - - public JPopupMenu createEmptyPopup() { - return new JPopupMenu(); - } - - public Component[] convertComponents(Component comp) { - return new Component[] {comp}; - } - } -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/actions/BooleanStateAction.java --- a/openide.util/src/org/openide/util/actions/BooleanStateAction.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.openide.util.actions; - - -/** An action that can be toggled on or off. -* The actual "performing" of the action is the toggle itself, so -* this action should be used by listening to the {@link #PROP_BOOLEAN_STATE} property. -*

The default value of the state is true (on). -* -* -* @author Ian Formanek, Petr Hamernik -*/ -public abstract class BooleanStateAction extends SystemAction implements Presenter.Menu, Presenter.Popup, - Presenter.Toolbar { - /** serialVersionUID */ - static final long serialVersionUID = 6394800019181426199L; - - /** Name of property hold the state of the action. */ - public static final String PROP_BOOLEAN_STATE = "booleanState"; // NOI18N - - /* Returns a JMenuItem that presents the Action, that implements this - * interface, in a MenuBar. - * @return the JMenuItem representation for the Action - */ - public javax.swing.JMenuItem getMenuPresenter() { - return org.openide.util.actions.ActionPresenterProvider.getDefault().createMenuPresenter(this); - } - - /* Returns a JMenuItem that presents the Action, that implements this - * interface, in a Popup Menu. - * The default implmentation returns the same JMenuItem as the getMenuPresenter. - * @return the JMenuItem representation for the Action - */ - public javax.swing.JMenuItem getPopupPresenter() { - return org.openide.util.actions.ActionPresenterProvider.getDefault().createPopupPresenter(this); - } - - /* Returns a Component that presents the Action, that implements this - * interface, in a ToolBar. - * @return the Component representation for the Action - */ - public java.awt.Component getToolbarPresenter() { - return org.openide.util.actions.ActionPresenterProvider.getDefault().createToolbarPresenter(this); - } - - /** Get the current state. - * @return true if on - */ - public boolean getBooleanState() { - return getProperty(PROP_BOOLEAN_STATE).equals(Boolean.TRUE); - } - - /** Set the current state. - * Fires a change event, which should be used to affect other components when - * its state is toggled. - * @param value true to turn on, false to turn off - */ - public void setBooleanState(boolean value) { - Boolean newValue = value ? Boolean.TRUE : Boolean.FALSE; - Boolean oldValue = (Boolean) putProperty(PROP_BOOLEAN_STATE, newValue); - - firePropertyChange(PROP_BOOLEAN_STATE, oldValue, newValue); - } - - /* Initializes its own properties (and let superclass initialize - * too). - */ - protected void initialize() { - putProperty(PROP_BOOLEAN_STATE, Boolean.TRUE); - super.initialize(); - } - - /* Implementation of method of javax.swing.Action interface. - * Changes the boolean state. - * - * @param ev ignored - */ - public void actionPerformed(java.awt.event.ActionEvent ev) { - setBooleanState(!getBooleanState()); - } -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/actions/CallableSystemAction.java --- a/openide.util/src/org/openide/util/actions/CallableSystemAction.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.actions; - -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.util.Set; -import java.util.logging.Logger; -import org.openide.util.WeakSet; - -/** Not preferred anymore, use Actions.alwaysEnabled -* instead. To migrate your -* -* layer definition use: -*

-* <file name="your-pkg-action-id.instance">
-*   <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
-*   <attr name="delegate" methodvalue="your.pkg.YourAction.factoryMethod"/>
-*   <attr name="displayName" bundlevalue="your.pkg.Bundle#key"/>
-*   <attr name="iconBase" stringvalue="your/pkg/YourImage.png"/>
-*   <!-- if desired: <attr name="noIconInMenu" boolvalue="false"/> -->
-* </file>
-* 
-* -* @author Ian Formanek, Jaroslav Tulach, Jan Jancura, Petr Hamernik -*/ -public abstract class CallableSystemAction extends SystemAction implements Presenter.Menu, Presenter.Popup, - Presenter.Toolbar { - /** serialVersionUID */ - static final long serialVersionUID = 2339794599168944156L; - - // ASYNCHRONICITY - // Adapted from org.netbeans.core.ModuleActions by jglick - - /** - * Set of action classes for which we have already issued a warning that - * {@link #asynchronous} was not overridden to return false. - */ - private static final Set warnedAsynchronousActions = new WeakSet(); - private static final boolean DEFAULT_ASYNCH = !Boolean.getBoolean( - "org.openide.util.actions.CallableSystemAction.synchronousByDefault" - ); - - /* Returns a JMenuItem that presents the Action, that implements this - * interface, in a MenuBar. - * @return the JMenuItem representation for the Action - */ - public javax.swing.JMenuItem getMenuPresenter() { - return org.openide.util.actions.ActionPresenterProvider.getDefault().createMenuPresenter(this); - } - - /* Returns a JMenuItem that presents the Action, that implements this - * interface, in a Popup Menu. - * @return the JMenuItem representation for the Action - */ - public javax.swing.JMenuItem getPopupPresenter() { - return org.openide.util.actions.ActionPresenterProvider.getDefault().createPopupPresenter(this); - } - - /* Returns a Component that presents the Action, that implements this - * interface, in a ToolBar. - * @return the Component representation for the Action - */ - public java.awt.Component getToolbarPresenter() { - return org.openide.util.actions.ActionPresenterProvider.getDefault().createToolbarPresenter(this); - } - - /** Actually perform the action. - * This is the method which should be called programmatically. - * Presenters in Actions use this. - *

See {@link SystemAction#actionPerformed} for a note on - * threading usage: in particular, do not access GUI components - * without explicitly asking for the AWT event thread! - */ - public abstract void performAction(); - - /* Implementation of method of javax.swing.Action interface. - * Delegates the execution to performAction method. - * - * @param ev the action event - */ - public void actionPerformed(ActionEvent ev) { - if (isEnabled()) { - org.openide.util.actions.ActionInvoker.invokeAction( - this, ev, asynchronous(), new Runnable() { - public void run() { - performAction(); - } - } - ); - } else { - // Should not normally happen. - Toolkit.getDefaultToolkit().beep(); - } - } - - /** - * If true, this action should be performed asynchronously in a private thread. - * If false, it will be performed synchronously as called in the event thread. - *

The default value is true for compatibility reasons; subclasses are strongly - * encouraged to override it to be false, and to either do their work promptly - * in the event thread and return, or to somehow do work asynchronously (for example - * using {@link org.openide.util.RequestProcessor#getDefault}). - *

You may currently set the global default to false - * by setting the system property - * org.openide.util.actions.CallableSystemAction.synchronousByDefault - * to true.

- *

When true, the current implementation also provides for a wait cursor during - * the execution of the action. Subclasses which override to return false should - * consider directly providing a wait or busy cursor if the nature of the action - * merits it.

- * @return true if this action should automatically be performed asynchronously - * @since 4.11 - */ - protected boolean asynchronous() { - if (warnedAsynchronousActions.add(getClass())) { - Logger.getLogger(CallableSystemAction.class.getName()).warning( - "Warning - " + getClass().getName() + - " should override CallableSystemAction.asynchronous() to return false" - ); - } - - return DEFAULT_ASYNCH; - } -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/actions/CallbackSystemAction.java --- a/openide.util/src/org/openide/util/actions/CallbackSystemAction.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,749 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util.actions; - -import java.awt.Component; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.Action; -import javax.swing.ActionMap; -import org.openide.util.ContextAwareAction; -import org.openide.util.Lookup; -import org.openide.util.LookupListener; -import org.openide.util.Mutex; -import org.openide.util.Utilities; -import org.openide.util.WeakListeners; -import org.openide.util.WeakSet; - -/** Not preferred anymore, the replacement is -* Actions.callback factory method. -* To migrate to the new API just remove the definition of your action in -* -* layer file and replace it with: -*
-* <file name="action-pkg-ClassName.instance">
-*   <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.callback"/>
-*   <attr name="key" stringvalue="KeyInActionMap"/>
-*   <attr name="surviveFocusChange" boolvalue="false"/> <!-- defaults to false -->
-*   <attr name="fallback" newvalue="action.pkg.DefaultAction"/> <!-- may be missing -->
-*   <attr name="displayName" bundlevalue="your.pkg.Bundle#key"/>
-*   <attr name="iconBase" stringvalue="your/pkg/YourImage.png"/>
-*   <!-- if desired: <attr name="noIconInMenu" boolvalue="false"/> -->
-* </file>
-* 
-* -* -* @author Ian Formanek, Jaroslav Tulach, Petr Hamernik -*/ -public abstract class CallbackSystemAction extends CallableSystemAction implements ContextAwareAction { - /** action performer */ - private static final String PROP_ACTION_PERFORMER = "actionPerformer"; // NOI18N - - /** a list of all actions that has survive focus change set to false */ - private static final WeakSet> notSurviving = new WeakSet>(37); - - /** a list of actions surviving focus change */ - private static final WeakSet> surviving = new WeakSet>(37); - - /** key to access listener */ - private static final Object LISTENER = new Object(); - static final long serialVersionUID = -6305817805474624653L; - - /** logging */ - private static final Logger err = Logger.getLogger( - "org.openide.util.actions.CallbackSystemAction" - ); // NOI18N - - /** Initialize the action to have no performer. - */ - protected void initialize() { - super.initialize(); - updateEnabled(); - setSurviveFocusChange(false); - } - - /** Get the current action performer. - * @return the current action performer, or null if there is currently no performer - * @deprecated use TopComponent.getActionMap() as described in the javadoc - */ - @Deprecated - public ActionPerformer getActionPerformer() { - return (ActionPerformer) getProperty(PROP_ACTION_PERFORMER); - } - - /** Set the action performer. - * The specified value can be null, which means that the action will have no performer - * and is disabled. ({@link #isEnabled} will return false regardless its previous state.) - *

- * This method is too dynamic it depends on the actuall order of callers and - * is for example very fragile with respect to focus switching and correct delivering of - * focus change events. That is why an alternative based on - * ActionMap proposal - * has been developed. - *

- * So if you are providing a TopComponent - * and want to provide - * your own handling of CopyAction use following code: - *

-    * TopComponent tc = ...;
-    * javax.swing.Action yourCopyAction = ...; // the action to invoke instead of Copy
-    *
-    * CopyAction globalCopyAction = SystemAction.get (CopyAction.class);
-    * Object key = globalCopyAction.getActionMapKey(); // key is a special value defined by all CallbackSystemActions
-    *
-    * // and finally:
-    * tc.getActionMap ().put (key, yourCopyAction);
-    * 
- * This code registers yourCopyAction with tc - * top component, so whenever a globalCopyAction is invoked, - * your action is being delegated to. - * - * @param performer the new action performer or null to disable - * - * @deprecated use TopComponent.getActionMap() as described in the javadoc - */ - @Deprecated - public void setActionPerformer(ActionPerformer performer) { - putProperty(PROP_ACTION_PERFORMER, performer); - updateEnabled(); - } - - /** Updates the enabled state by checking performer and ActionMap - */ - private void updateEnabled() { - Action action = GlobalManager.getDefault().findGlobalAction( - getActionMapKey(), getSurviveFocusChange() - ); - - if (action != null) { - setEnabled(action.isEnabled()); - - synchronized (LISTENER) { - ActionDelegateListener l = (ActionDelegateListener) getProperty(LISTENER); - - if ((l == null) || (l.get() != this)) { - l = new ActionDelegateListener(this, action); - putProperty(LISTENER, l); - } else { - l.attach(action); - } - } - } else { - if (getActionPerformer() != null) { - // we have performer - setEnabled(true); - } else { - setEnabled(false); - } - - clearListener(); - } - } - - /** Clears the listener. - */ - private void clearListener() { - synchronized (LISTENER) { - // remove listener on any action - ActionDelegateListener l = (ActionDelegateListener) getProperty(LISTENER); - - if (l != null) { - l.clear(); - putProperty(LISTENER, null); - } - } - } - - /** Perform the action. Tries the performer and then scans the ActionMap - * of selected topcomponent. - */ - public void actionPerformed(final ActionEvent ev) { - // First try global context action. - final Action action = GlobalManager.getDefault().findGlobalAction(getActionMapKey(), getSurviveFocusChange()); - - if (action != null) { - if (action.isEnabled()) { - action.actionPerformed(ev); - } else { - Toolkit.getDefaultToolkit().beep(); - } - - return; - } - - final Object ap = getActionPerformer(); - - if (ap != null) { - org.openide.util.actions.ActionInvoker.invokeAction( - this, ev, asynchronous(), new Runnable() { - public void run() { - if (ap == getActionPerformer()) { - getActionPerformer().performAction(CallbackSystemAction.this); - } - } - } - ); - - return; - } - - Toolkit.getDefaultToolkit().beep(); - } - - /** Perform the action. - * This default implementation calls the assigned action performer if it - * exists, otherwise does nothing. - * @deprecated This only uses {@link ActionPerformer}. Use {@link #actionPerformed} instead. - */ - @Deprecated - public void performAction() { - ActionPerformer ap = getActionPerformer(); - - if (ap != null) { - ap.performAction(this); - } - } - - /** Getter for action map key, which is used to find action from provided - * context (i.e. ActionMap provided by the context), - * which acts as a callback. - * Override this method in subclasses to provide 'nice' key. - * @return key which is used to find the action which performs callback, - * default returned key is a class name. - * @since 3.29 */ - public Object getActionMapKey() { - return getClass().getName(); - } - - /** Test whether the action will survive a change in focus. - * By default, it will not. - * @return true if the enabled state of the action survives focus changes - */ - public boolean getSurviveFocusChange() { - getProperty(null); // force initialization - - return !notSurviving.contains(getClass()); - } - - /** Implements ContextAwareAction interface method. */ - public Action createContextAwareInstance(Lookup actionContext) { - return new DelegateAction(this, actionContext); - } - - /** Set whether the action will survive a change in focus. - * If false, then the action will be automatically - * disabled (using {@link #setActionPerformer}) when the window - * focus changes. - * - * @param b true to survive focus changes, false to be sensitive to them - */ - public void setSurviveFocusChange(boolean b) { - synchronized (notSurviving) { - if (b) { - notSurviving.remove(getClass()); - surviving.add(getClass()); - } else { - notSurviving.add(getClass()); - surviving.remove(getClass()); - } - } - } - - /** Array of actions from a set of classes. - */ - private static List toInstances(java.util.Set> s) { - List actions; - - synchronized (notSurviving) { - actions = new ArrayList(s.size()); - - for (Class c : s) { - - CallbackSystemAction a = SystemAction.findObject(c, false); - - if (a != null) { - actions.add(a); - } - } - } - - return actions; - } - - /** Clears all action performers for those that has setSurviveFocusChange - * on true. - */ - private static void clearActionPerformers() { - List actions = toInstances(notSurviving); - - // clear the performers out of any loop - for (CallbackSystemAction a : actions) { - a.setActionPerformer(null); - } - - actions = toInstances(surviving); - - // clear the performers out of any loop - for (CallbackSystemAction a : actions) { - - if (err.isLoggable(Level.FINE)) { - err.fine("updateEnabled: " + a); // NOI18N - } - - a.updateEnabled(); - } - } - - /** Listener on a global context. - */ - private static final class GlobalManager implements LookupListener { - private static GlobalManager instance; - private Lookup.Result result; - private List> actionMaps = new ArrayList>(2); - private final ActionMap survive = new ActionMap(); - - private GlobalManager() { - result = Utilities.actionsGlobalContext().lookup(new Lookup.Template(ActionMap.class)); - result.addLookupListener(this); - resultChanged(null); - } - - public synchronized static GlobalManager getDefault() { - if (instance != null) { - return instance; - } - - instance = new GlobalManager(); - - return instance; - } - - public Action findGlobalAction(Object key, boolean surviveFocusChange) { - // search action in all action maps from global context - Action a = null; - for (Reference ref : actionMaps) { - ActionMap am = ref.get(); - a = am == null ? null : am.get(key); - if (a != null) { - break; - } - } - - if (surviveFocusChange) { - if (a == null) { - a = survive.get(key); - - if (a != null) { - a = ((WeakAction) a).getDelegate(); - } - - if (err.isLoggable(Level.FINE)) { - err.fine("No action for key: " + key + " using delegate: " + a); // NOI18N - } - } else { - if (err.isLoggable(Level.FINE)) { - err.fine("New action for key: " + key + " put: " + a); - } - - survive.put(key, new WeakAction(a)); - } - } - - if (err.isLoggable(Level.FINE)) { - err.fine("Action for key: " + key + " is: " + a); // NOI18N - } - - return a; - } - - /** Change all that do not survive ActionMap change */ - public void resultChanged(org.openide.util.LookupEvent ev) { - Collection ams = result.allInstances(); - - if (err.isLoggable(Level.FINE)) { - err.fine("changed maps : " + ams); // NOI18N - err.fine("previous maps: " + actionMaps); // NOI18N - } - - // do nothing if maps are actually the same - if (ams.size() == actionMaps.size()) { - boolean theSame = true; - int i = 0; - for (Iterator newMaps = ams.iterator(); newMaps.hasNext(); i++) { - ActionMap oldMap = actionMaps.get(i).get(); - if (oldMap == null || oldMap != newMaps.next()) { - theSame = false; - break; - } - } - if (theSame) { - return; - } - } - - // update actionMaps - List> tempActionMaps = new ArrayList>(2); - for (ActionMap actionMap : ams) { - tempActionMaps.add(new WeakReference(actionMap)); - } - actionMaps = tempActionMaps; - - if (err.isLoggable(Level.FINE)) { - err.fine("clearActionPerformers"); // NOI18N - } - - Mutex.EVENT.readAccess(new Runnable() { - public void run() { - clearActionPerformers(); - } - }); - } - } - // end of LookupListener - - /** An action that holds a weak reference to other action. - */ - private static final class WeakAction extends WeakReference implements Action { - public WeakAction(Action delegate) { - super(delegate); - } - - public Action getDelegate() { - return get(); - } - - public Object getValue(String key) { - throw new UnsupportedOperationException(); - } - - public void putValue(String key, Object value) { - throw new UnsupportedOperationException(); - } - - public void actionPerformed(ActionEvent e) { - throw new UnsupportedOperationException(); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - throw new UnsupportedOperationException(); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - throw new UnsupportedOperationException(); - } - - public void setEnabled(boolean b) { - throw new UnsupportedOperationException(); - } - - public boolean isEnabled() { - throw new UnsupportedOperationException(); - } - } - - /** A class that listens on changes in enabled state of an action - * and updates the state of the action according to it. - */ - private static final class ActionDelegateListener extends WeakReference implements PropertyChangeListener { - private Reference delegate; - - public ActionDelegateListener(CallbackSystemAction c, Action delegate) { - super(c); - this.delegate = new WeakReference(delegate); - delegate.addPropertyChangeListener(this); - } - - public void clear() { - Action a; - - Reference d = delegate; - a = d == null ? null : d.get(); - - if (a == null) { - return; - } - - delegate = null; - - a.removePropertyChangeListener(this); - } - - public void attach(Action action) { - Reference d = delegate; - - if ((d != null) && (d.get() == action)) { - return; - } - - Action prev = d.get(); - - // reattaches to different action - if (prev != null) { - prev.removePropertyChangeListener(this); - } - - this.delegate = new WeakReference(action); - action.addPropertyChangeListener(this); - } - - public void propertyChange(java.beans.PropertyChangeEvent evt) { - synchronized (LISTENER) { - Reference d = delegate; - - if ((d == null) || (d.get() == null)) { - return; - } - } - - CallbackSystemAction c = get(); - - if (c != null) { - c.updateEnabled(); - } - } - } - - /** A delegate action that is usually associated with a specific lookup and - * extract the nodes it operates on from it. Otherwise it delegates to the - * regular NodeAction. - */ - private static final class DelegateAction extends Object implements Action, - LookupListener, Presenter.Menu, Presenter.Popup, Presenter.Toolbar, PropertyChangeListener { - /** action to delegate too */ - private CallbackSystemAction delegate; - - /** lookup we are associated with (or null) */ - private Lookup.Result result; - - /** previous state of enabled */ - private boolean enabled; - - /** support for listeners */ - private PropertyChangeSupport support = new PropertyChangeSupport(this); - - /** listener to check listen on state of action(s) we delegate to */ - private PropertyChangeListener weakL; - - /** last action we were listening to */ - private Reference lastRef; - - public DelegateAction(CallbackSystemAction a, Lookup actionContext) { - this.delegate = a; - this.weakL = org.openide.util.WeakListeners.propertyChange(this, null); - this.enabled = a.getActionPerformer() != null; - - this.result = actionContext.lookup(new Lookup.Template(ActionMap.class)); - this.result.addLookupListener(WeakListeners.create(LookupListener.class, this, this.result)); - resultChanged(null); - } - - /** Overrides superclass method, adds delegate description. */ - public String toString() { - return super.toString() + "[delegate=" + delegate + "]"; // NOI18N - } - - /** Invoked when an action occurs. - */ - public void actionPerformed(final java.awt.event.ActionEvent e) { - final Action a = findAction(); - - if (a != null) { - Runnable run = new Runnable() { - public void run() { - a.actionPerformed(e); - } - }; - org.openide.util.actions.ActionInvoker.invokeAction(delegate, e, delegate.asynchronous(), run); - } else { - // XXX #30303 if the action falls back to the old behaviour - // it may not be performed in case it is in dialog and - // is not transmodal. - // This is just a hack, see TopComponent.processKeyBinding. - Object source = e.getSource(); - - if ( - source instanceof Component && - javax.swing.SwingUtilities.getWindowAncestor((Component) source) instanceof java.awt.Dialog - ) { - Object value = delegate.getValue("OpenIDE-Transmodal-Action"); // NOI18N - - if (!Boolean.TRUE.equals(value)) { - return; - } - } - - delegate.actionPerformed(e); - } - } - - public boolean isEnabled() { - Action a = findAction(); - - if (a == null) { - a = delegate; - } - - // 40915 - hold last action weakly - Action last = lastRef == null ? null : lastRef.get(); - - if (a != last) { - if (last != null) { - last.removePropertyChangeListener(weakL); - } - - lastRef = new WeakReference(a); - a.addPropertyChangeListener(weakL); - } - - return a.isEnabled(); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - support.addPropertyChangeListener(listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - support.removePropertyChangeListener(listener); - } - - public void putValue(String key, Object o) { - } - - public Object getValue(String key) { - return delegate.getValue(key); - } - - public void setEnabled(boolean b) { - } - - public void resultChanged(org.openide.util.LookupEvent ev) { - boolean newEnabled = isEnabled(); - - if (newEnabled != enabled) { - support.firePropertyChange(PROP_ENABLED, enabled, newEnabled); - enabled = newEnabled; - } - } - - public void propertyChange(PropertyChangeEvent evt) { - resultChanged(null); - } - - /*** Finds an action that we should delegate to - * @return the action or null - */ - private Action findAction() { - Collection c = result != null ? result.allInstances() : Collections.emptySet(); - - if (!c.isEmpty()) { - Object key = delegate.getActionMapKey(); - for (ActionMap map : c) { - Action action = map.get(key); - if (action != null) { - return action; - } - } - } - - return null; - } - - public javax.swing.JMenuItem getMenuPresenter() { - if (isMethodOverridden(delegate, "getMenuPresenter")) { // NOI18N - - return delegate.getMenuPresenter(); - } else { - return org.openide.util.actions.ActionPresenterProvider.getDefault().createMenuPresenter(this); - } - } - - public javax.swing.JMenuItem getPopupPresenter() { - if (isMethodOverridden(delegate, "getPopupPresenter")) { // NOI18N - - return delegate.getPopupPresenter(); - } else { - return org.openide.util.actions.ActionPresenterProvider.getDefault().createPopupPresenter(this); - } - } - - public java.awt.Component getToolbarPresenter() { - if (isMethodOverridden(delegate, "getToolbarPresenter")) { // NOI18N - - return delegate.getToolbarPresenter(); - } else { - return org.openide.util.actions.ActionPresenterProvider.getDefault().createToolbarPresenter(this); - } - } - - private boolean isMethodOverridden(CallableSystemAction d, String name) { - try { - java.lang.reflect.Method m = d.getClass().getMethod(name, new Class[0]); - - return m.getDeclaringClass() != CallableSystemAction.class; - } catch (java.lang.NoSuchMethodException ex) { - ex.printStackTrace(); - throw new IllegalStateException("Error searching for method " + name + " in " + d); // NOI18N - } - } - - protected void finalize() { - Action last = lastRef == null ? null : lastRef.get(); - - if (last != null) { - last.removePropertyChangeListener(weakL); - } - } - } - // end of DelegateAction -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/src/org/openide/util/doc-files/api.html --- a/openide.util/src/org/openide/util/doc-files/api.html Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1233 +0,0 @@ - - - - -Utility Classes - - - - - - -

Utility Classes

- -Not all of the classes in this package are of interest for all module -writers, but some of them may or even are as they are used through out -our sources. - -

Package org.openide.util

- -
    -
  1. Lookup and its associated - support package as that - is the adaptable interface that objects can provide if - they wish to offer dynamic capabilities. -
  2. - -
  3. NbBundle as our specialized support - for localization and replacement to - ResourceBundle. -
  4. - -
  5. Task and especially - RequestProcessor which - is our way to manage pools of thread workers and execute asynchronous - computations. -
  6. - -
  7. - HelpCtx to specify help ids for - various UI components -
  8. - -
  9. - Utilities which contain - a lot of methods of possible interest. For example - actionsGlobalContext, - loadImage, - mergeImage, - topologicalSort, - activeReferenceQueue, - translate. -
  10. - -
  11. - Enumerations provide - enhacened support for manipulation with - Enumerations and especially - their on-demand generation. -
  12. -
- - - -

Services Registration and Lookup API

- - -

For lookup, this centers around - -Lookup - -and helper implementations in - -org.openide.util.lookup. - - - -

Contents

- - - - -

Lookup

- -
- -The whole NetBeans platform is moving toward -installation of services via XML layer or (via the @ServiceProvider annotation on classes) META-INF/services. -Layer-based installation is more flexible in many ways. - -

The need for having a standard interface to access such -registrations -gave rise to the lookup system first -introduced in NetBeans 3.2 and expanded upon for NetBeans 3.3. The -center of this API from the client perspective is very simple - you -can look up a class, and get an instance of that class (or a -collection of them). The service provider side of it is more complex -but useful lookup implementations are already provided in the -core system; for common cases you can register an object into lookup just by -adding one simple file to an XML layer or META-INF/services/classname -in your module JAR file. - -

This section of the Services API will first discuss what -instances are and how to create them from files, as this is -the core concept for service providers. It will discuss how you can -manually retrieve sets of instances as a client, which is not used -very frequently in new code but helps to understand what lookup is -doing behind the scenes. Then lookup itself is discussed, and how the -standard instance lookup works and how it relates to JDK's - -standard for service provider registration. -Lookup templates, which separate the -provision of instances from the provision of categories, will be -explained. - -

- -

Working with Instances

- -Central to the management of services and many other aspects of -NetBeans' configuration is the notion of -instances. An instance is just any Java object, generally -of a particular type appropriate to its use, which is provided from -some object (generally, a data object) using - -InstanceCookie. - -As an example, menu items may be added by inserting data objects -that provide this cookie into the proper folder, and having the -instance be a system action (or other things). Or an XML DTD may be -registered by placing an object with an instance of -org.xml.sax.EntityResolver in the proper folder. - -

Where do these instances come from? Technically, it is up to you -to decide how to provide InstanceCookie; you could if -really necessary create your own data loader that provides it -according to some unusual scheme, and add files recognized by that -loader to the right folder. Practically, the APIs provide -implementations of this cookie sufficient for normal purposes. - -

The most common way to provide an instance is using - -InstanceDataObject. - -This is a type of data object whose sole purpose is to provide the -instance cookie. It typically does so based on a class name you -supply. There are several styles of instance file; all are empty (i.e. -the file contents are of zero length, and just the file name and -attributes matter). There are then other ways of providing instances -which rely on the file contents. Here are the methods of providing -instances defined in the APIs: - -

- -
Default instance - InstanceDataObject - -

If there is a file with the extension *.instance, then its -name (minus extension) will be converted to a class name by replacing dashes -with dots; and a fresh instance of that class will be created and used as the -instance. For example, com-mycom-mymodule-MyAction.instance -produces an instance of the class com.mycom.mymodule.MyAction.

- -

Since reflection is used to create the new instance, just as in the -realm of JavaBeans, the class must be loadable from your module or -otherwise from within NetBeans (technically, via the classloader found -by querying Lookup for ClassLoader); -public; and have a public no-argument constructor. -(Or be a - -SharedClassObject.) - -This form is often -used for singleton classes such as system actions: there is -no need to specify any parameters to the constructor, any instance -will suffice.

- - -
Default instance with separate class - InstanceDataObject - -

Rather than shoving the class name into -the file name, you can name the file more normally and specify the -class with a file attribute. Then the class name is specified as -a string-valued attribute on the instance named -instanceClass. For example, a keyboard shortcut -could be registered as follows in an XML layer:

- -
-<file name="C-F6.instance">
-    <attr name="instanceClass" stringvalue="com.mycom.mymodule.MyAction"/>
-</file>
-
- -

In addition to instanceClass you may specify an -additional attribute instanceOf giving the name of a -superclass (or implemented interface) of the instance class. In fact -it may be a comma-separated list of superclasses and interfaces. While -its purpose is explained more fully - -below, - -essentially it lets you give the system a hint as to what this -instance is for before your instance class is even loaded into the VM. -For example:

- -
-<file name="com-me-some-service.instance">
-    <attr name="instanceClass" stringvalue="com.me.FactoryForEverything"/>
-    <attr name="instanceOf"
-     stringvalue="org.xml.sax.EntityResolver,org.openide.cookies.ExecCookie"/>
-</file>
-
- -
Non-default instance - InstanceDataObject - -

A powerful way of providing instances is to use the expressiveness -of the XML layer syntax to handle the instance creation. In this case -the file attribute instanceCreate can be defined and the -attribute value becomes the instance. Typically the attribute value -would be specified using the methodvalue syntax of -layers. For example:

- -
-<file name="com-me-some-service.instance">
-    <attr name="instanceClass" stringvalue="com.me.FactoryForEverything"/>
-    <attr name="instanceCreate" methodvalue="com.me.FactoryForEverything.configure"/>
-    <attr name="myParam" urlvalue="nbres:/com/me/config-1.properties"/>
-    <attr name="instanceOf"
-     stringvalue="org.xml.sax.EntityResolver,org.openide.cookies.ExecCookie"/>
-</file>
-
- -

According to the general system for - -XMLFileSystem, - -you now need a method configure in -FactoryForEverything which must be static; the method -need not be public (if you do not want other Java code to see it). It -may take a file object as argument if you wish - this will be the -instance file; typically you use this to pass extra configuration from -the layer, useful if you want to create multiple instances with the -same creation method. So for example you might implement such a method -like this:

- -
-public class FactoryForEverything extends SomeBaseFactory
-        implements EntityResolver, ExecCookie {
-    public FactoryForEverything(Map props) {
-        // ...
-    }
-    // ...
-    // Called directly from XML layer. Pass URL to
-    // properties file from attr 'myParam'.
-    private static Object configure(FileObject inst) throws IOException {
-        URL u = (URL)inst.getAttribute("myParam");
-        Properties p = new Properties();
-        p.load(u.openStream());
-        return new FactoryForEverything(p);
-    }
-}
-
- -
Serialized beans - -

A simple way to provide an instance is to serialize it as a -JavaBean, into a file with the extension *.ser. This is -not very useful from a layer, because you should avoid putting -binary data into a layer, but may be useful in some circumstances.

- -
XML-based instances
- - -EntityCatalog - - -
- -

Again, modules may also have additional ways of providing instances -from files. For example, currently the utilities module -enables any URL file (*.url) to be used directly in a -menu, as the URL file provides an instance of -Presenter.Menu.

- -

As an interactive demonstration of these things, first go into -Filesystem Settings and make the system filesystem (first in -the list) visible; then explore its contents in Filesystems, -going into some subdirectory of Menu. Note the various -actions and menu separators; these are all by default instance data -objects. -You may find some of these on disk in your installation directory -under system/ if you have customized them, but by default -they live in memory only. -You may copy-and-paste these instances from one place to another; -create new ones on disk and watch them be recognized and inserted -into the menus after a few seconds; and you may also choose -Customize Bean (which really customizes the provided instance) on -(say) a toolbar separator (under Toolbars) to change -the separator size, and serialize the result to a new -*.ser file which should then create a toolbar -separator. - -

- -

Folders of Instances

- - -

InstanceCookie.Of and lazy class loading

- -Now it is time to mention the purpose of -InstanceCookie.Of. Suppose that there are two generic -interfaces under consideration: e.g. javax.swing.Action -and org.xml.sax.EntityResolver. For each interface, there -is code to find registered instances, all under the -Services/ folder. Furthermore, using either of these -interfaces is relatively rare, and might not happen at all during a -NetBeans session; and the implementations of the instances are complicated -and involve a lot of code, so it is undesirable (for performance -reasons) to load these implementations unless and until they are -really needed. If you write the layers simply like this: - -
-<filesystem>
-    <folder name="Services">
-        <folder name="Hidden">
-            <file name="com-me-MyAction.instance"/>
-            <file name="com-me-MyResolver.instance"/>
-        </folder>
-    </folder>
-</filesystem>
-
- -everything will work, but this is inefficient. Consider some -piece of code asking for all actions. The search through the services -folder for actions would ask each of these files if it provides an -instance cookie assignable to javax.swing.Action. For -com-me-MyAction.instance, this will load the class -com.me.MyAction, determine that it implements -Action, and thus create a MyAction instance -and return it; so far so good. But when -com-me-MyResolver.instance is encountered, it will again -load com.me.MyResolver, only to find that this does not -implement Action and skip the instance. The behavior is -correct, but now the MyResolver class has been loaded -into the VM even though no one will ever use it (unless a resolver -search is made). This will degrade startup time and memory usage (and -thus performance). - -

So the better solution is to mark each file in advance, saying what -interfaces it is intended to provide in its instance: - -

-<filesystem>
-    <folder name="Services">
-        <folder name="Hidden">
-            <file name="com-me-MyAction.instance">
-                <attr name="instanceOf" stringvalue="javax.swing.Action"/>
-            </file>
-            <file name="com-me-MyResolver.instance">
-                <attr name="instanceOf" stringvalue="org.xml.sax.EntityResolver"/>
-            </file>
-        </folder>
-    </folder>
-</filesystem>
-
- -

-Now the folder instance processor for Action will pass -over com-me-MyResolver.instance without needing to load -com.me.MyResolver, since it sees that its interfaces are -declared, and Action is not among them. Of course, the -interface classes - Action and -EntityResolver - need to be loaded right away, but they -were probably already loaded anyway, so this is acceptable. -

- -

Caution: if you do supply an -instanceOf attribute, but it does not list all -of the implemented interfaces and superclasses of the actual -implementation class (including that implementation class itself, -which is not implied), a lookup query on one of the missing -superclasses may or may not succeed. So you should include in -instanceOf any superclasses and interfaces that you think -someone might use in a lookup query, possibly including the actual -implementation class.

- -

Lookup and Service Installation

- -The client side of the lookup system centers around one class, - -Lookup. - -In the simplest usage, all that is needed is to get some single -instance of a given class (or subclass). For example, if some kind of -service has been defined as an interface or abstract class, and you -wish to find the implementation of it, you -may simply use: - -
-MyService impl = (MyService)Lookup.getDefault().lookup(MyService.class);
-if (impl == null) /* nothing registered */ ...
-impl.useIt();
-
- -Such implementation has to be registered by some module to the system. -Either via layer as described above or as a JDK's - -service provider. If some module wants to register for example -org.me.MyService it shall provide file name -META-INF/services/org.me.MyService in its own JAR -with single line containing name of the implementation class (for example -org.you.MyServiceImpl). -This is normally done more easily by using the @ServiceProvider annotation in MyService.java. -The lookup infrastructure -will then load the implementation class and call its default constructor -to answer the query in the above example. -

- -

- The Lookup supports two small extensions to the - JDK's - standard. It allows a module to remove class registered by - another one. That is why it is possible to write a module that - disables the org.you.MyServiceImpl implementation - and provides its own. This the expected content of its - META-INF/services/org.me.MyService file: -
-  # remove the other implementation (by prefixing the line with #-)
-  #-org.you.MyServiceImpl
-
-  # provide my own
-  org.alien.MyServiceAlienImpl
-    
- The reason why the removal line starts with #- is to keep - compatibility with JDK's implementation. The # means comment - and thus JDK will not interpret the line and will not get confused by - the - before class name. - -

Second extension allows ordering of items. The class implementing - the interface can be followed by advisory position attribute. If - multiple implementations are defined in one file then each can be - followed by its own positioning attribute. When querying - on an interface, items with a smaller position are guaranteed - to be returned before items with a larger position. Items with no defined - position are returned last. Example of content of - META-INF/services/org.me.MyService - file could be: -

-  org.you.MyServiceImpl
-  #position=20
-  org.you.MyMoreImportantServiceImpl
-  #position=10
-    
- The MyMoreImportantServiceImpl - will be returned in lookup before the - MyServiceImpl. - It is recommended to pick up larger numbers so that there is - gap for other modules if they need to get in front of your item. And, - again, to keep compatibility the position attribute must starts with - comment delimiter.

-

Both extensions are supported by @ServiceProvider.

-
- -

-If more than one implementation has been registered, the "first" will -be returned. For example, if the implementations were present in the -Services folder as *.instance files, then -folder order would control this. - -

As mentioned above, the NetBeans default lookup searches in the -Services folder and its subfolders for instances whose -class matches the requested class. Technically, it looks for data -objects with InstanceCookie.Of claiming to match the -requested superclass, or plain InstanceCookie whose -instanceClass is assignable to it. - -

Note that you may use this method to find singleton instances of -subclasses of - -SharedClassObject - -that have been registered in lookup (as is normally the case for - -system options). - -However for this purpose it is simpler to use the static finder method - -SharedClassObject.findObject(Class, true) - -which is guaranteed to find the singleton whether it was registered in -lookup or not (if necessary it will first - -initialize - -the object according to saved state). - -

In many situations it is normal for there to be more than one -registered implementation of a service. In such a case you use a more -general method: - -

-Lookup.Template templ = new Lookup.Template(MyService.class);
-final Lookup.Result result = Lookup.getDefault().lookup(templ);
-Collection impls = result.allInstances(); // Collection<MyService>
-// use Java Collections API to get iterator, ...
-// Pay attention to subsequent changes in the result.
-result.addLookupListener(new LookupListener() {
-    public void resultChanged(LookupEvent ev) {
-        // Now it is different.
-        Collection impls2 = result.allInstances();
-        // use the new list of instances...
-    }
-});
-
- -Here you receive a collection of all instances matching your query, -again in the order found if this matters. You can also listen to -changes in the list (additions, deletions, and reorderings). It is -fine to keep a Lookup.Result for a long period of time as -it may implement its own caching scheme and only really compute the -instances when allInstances is called; in fact it may be -more efficient to keep a result, and listen for changes in it, than to -repeatedly call lookup and create fresh result objects. - -

When a lookup query is finished - for example when -Lookup.Result.allInstances() returns some -Collection of instances - it is guaranteed that all -objects registered in the same thread prior to the call to -lookup() or prior to some change notification on the -Lookup.Result, will be returned. Specifically, lookup -instances registered via module layer will be available by the time -ModuleInstall.restored() (or .installed()) -is called. There are two situations in which lookup results may be -incomplete: when you are currently inside the dynamic scope of some -method providing a lookup instance itself; and when you are -dynamically inside a DataLoader method involved in -recognizing data objects. - -

Persisting Lookup Information

- -In some circumstances it is necessary to not only find registered -objects, but to select some of them and make this selection -persistent. For example, some setting may have as its value a choice -among available services matching some interface; the value needs to -be persisted, but it is the identity of the choice, rather than the -full state of the instance itself, which must be stored. - -

In such cases it is possible to use code like this: - -

-Lookup.Template templ = new Lookup.Template(MyService.class);
-Lookup.Result result = Lookup.getDefault().lookup(templ);
-Iterator it = result.allItems().iterator();
-while (it.hasNext()) {
-    Lookup.Item item = (Lookup.Item)it.next();
-    String displayName = item.getDisplayName();
-    if (/* user accepts displayName as the right one */) {
-        MyService instance = (MyService)item.getInstance();
-        // use instance for now, and ...
-        String id = item.getId();
-        someSettings.setChosenService(id);
-        break;
-    }
-}
-// later...
-String storedID = someSettings.getChosenService();
-Lookup.Template templ = new Lookup.Template(MyService.class, storedID, null);
-Iterator it = Lookup.getDefault().lookup(templ).allInstances().iterator();
-if (! it.hasNext()) /* failed to find it... */
-MyService instance = (MyService)it.next();
-// use instance again
-
- -The ID permits you to track which instance from all those available in -the lookup result was last selected by the user, and find the "same" -instance later, perhaps after a restart of NetBeans. The exact form of -the ID is the private knowledge of the implementor of the lookup, but -typically if the instance has been provided via layer the ID will -mention the name of the file from which it was derived. - -

Creating Lookups

- -There are a number of reasons to create your own lookup -implementation. For one thing, the lookup system which scans the -Services/ folder will recognize instances of subclasses -of Lookup specially by proxying to them. This -can be very powerful because you may register just one layer file -which points to your custom lookup, which in turn may provide an -unlimited number of actual instances/items for queries (and compute -them in a manner other than registration by files). Another reason is -to associate a context with a data object using - -Environment.Provider; - -for example the data object might be an XML file and this provider -might be registered with the file by means of the public ID of the -doctype (informally, the DTD). Here the provider has an associated -lookup which can serve requests for cookies and such things. -See more information about associating lookups -with XML files. - -

The simplest way to create a fresh lookup is to base it on other -existing ones. - -ProxyLookup - -accepts a list of other lookup implementations (in the constructor and -also changeable later). The results it provides are constructed by -merging together the results of the delegate lookups. - -

- - -If you want to use the common mechanism of finding instances in -folders (or subfolders) and serving these as the results, - -Lookups.forPath(String) - -makes this possible: you need only provide a name of a folder to look in, and -use - -Lookups.forPath(theFolderName) - -to retrieve a lookup implementation which will scan this folder and -its subfolders for data objects with InstanceCookie -matching the lookup template. Furthermore, any instance cookies whose -instance class is assignable to Lookup will be treated -specially: they will be proxied to, so these sub-lookups may provide -additional instances if they match the lookup template. In order to -get the full functionality associated with such a lookup it is wise -to request presence of org.netbeans.modules.settings > 1.13 -as that is the module that does most of the work behind Lookups.forPath. -To register javax.xml.parsers.DocumentBuilderFactory into -Lookups.forName("my/xml/app/data") add the above described dependency -and put following code in your layer file: -

-<folder name="my">
-  <folder name="xml">
-    <folder name="app">
-      <folder name="data">
-        <file name="ThisIsMyRegistration.instance>
-          <attr name="instanceCreate" newvalue="pkg.ClassNameOfYourImpl"/>
-        </file>
-      </folder>
-    </folder>
-  </folder>
-</folder>
-
- -

-In fact the Lookups.forPath can be used in completely -standalone mode. This is not very recommended in the NetBeans IDE, but -can be found pretty useful when using this library in standalone applications: -Lookups.forPath(path) scans all instances registered in the -META-INF/services style just it uses -META-INF/namedservices/path prefix instead. -(@ServiceProvider supports this mode.) -As a result to -perform a successfull search for all javax.xml.parsers.DocumentBuilderFactory -inside Lookups.forName("my/xml/app/data") one can register the -implementation into META-INF/namedservices/my/xml/app/data/javax.xml.parsers.DocumentBuilderFactory. -

- -

The most powerful way to provide a lookup is to directly define -what instances and items it should provide, by subclassing. For this, - -AbstractLookup - -is recommended as it is easiest to use. - -

The simplest way to use AbstractLookup is to use its -public constructor (in which case you need not subclass it). Here you -provide an - -AbstractLookup.Content - -object which you have created and hold on to privately, and which -keeps track of instances and permits them to be registered and -deregistered. Often - -InstanceContent - -is used as the content implementation. To add something to the lookup, -simply use - -add(Object) - -(and remove(Object) for the reverse). These may be called -at any time and will update the set of registered instances (firing -result changes as needed). - -

In case it is expensive to actually compute the object in the -lookup, but there is some cheap "key" which can easily generate it, -you may instead register the key by passing in an - -InstanceContent.Convertor. - -This convertor translates the key to the real instance that the lookup -client sees, if and when needed. For example, if you have a long list -of class names and wish to register default instances of each class, -you might actually register the class name as the key, and supply a -convertor which really loads the class and instantiates it. This makes -it easy to set up the lookup, but nothing is really loaded until -someone asks for it. - -

Settings

- -Settings require special support in the lookup system: these -are objects (perhaps singletons but not necessarily) which should be -made available to lookup, yet whose content can be changed and stored -to disk (typically as a result of user interaction with the GUI). -*.instance files and similar constructions are fine for -registering fixed objects from layer - "fixed" in the sense that while -the user might copy, delete, move, or reorder them, the actual object -they provide is statically determined and does not generally have a -means of being modified. In contrast, settings have nontrivial -content. A typical setting is a system options, -simply a singleton bean with a set of properties and a structured GUI -presentation driven by BeanInfo. - -

In order to save such settings, an XML file is normally used, and -the APIs provide a convenient - -DTD - -for settings which can be represented as a single bean. In typical -usage, the module layer declares an initial settings file which -instructs lookup to create a default instance of the settings -class. This might look like the following: - -

-<?xml version="1.0"?>
-<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
-<settings version="1.0">
-    <module name="com.foo/1" spec="1.0"/>
-    <instanceof class="org.openide.options.SystemOption"/>
-    <instanceof class="com.foo.MyOption"/>
-    <instance class="com.foo.MyOption"/>
-</settings>
-
- -Such a file might be placed in -Services/com-foo-my-settings.xml (the exact name inside -the Services folder is not important but ought to be -globally unique to avoid conflicts with other modules). It provides -an InstanceCookie with the settings object as instance. - -

The interesting parts of this file are: - -

    - -
  • The <instance/> element which declares that the -actual object will be a default instance of the class -com.foo.MyOption, i.e. created via default public -constructor. - -
  • Various <instanceof/> elements which specify -what lookup templates will find this instance. Giving these elements -permits the system to defer creating the setting instance until it is -actually requested (that is, using - -InstanceCookie.Of). - -It is only necessary to indicate superclasses and interfaces that you -actually expect someone to look up when searching for this setting, -but be careful that you know what these might be. The actual class -of the instance itself should be listed as well. - -
  • An optional but recommended <module/> element -that declares which module provides this setting. You give the full -code name (including a slash followed by the major release version, if applicable) -of the module and its specification version. The purpose of -this element becomes apparent if the user ever customizes the setting -file, thus writing the changes to disk (for example in the -system/Services/ folder), and then uninstalls the module: -keeping the name of the declaring module in the file ensures that with -the module uninstalled, the system will quietly ignore the stale -setting rather than trying to blithely load the settings class and -failing with a ClassNotFoundException. If the module is -subsequently reinstalled, the setting will automatically become active -again (regain its InstanceCookie). Similarly, settings will -not be loaded if they were written by a newer version of the module than -the one currently installed - module-supplied settings should be readable -by newer versions of the module, but generally not older ones. - -
- -

There are actually three ways that the instance may be declared:

- -
    - -
  1. Using <instance/> as above to generate a -default instance. This is most common.

    - -
  2. You may pass an additional attribute method -indicating a static method to call to produce -the instance, rather than using a default constructor. -The method may either be a simple name, in which case it is assumed -to be a method in the class given by class, or you -may give a full class name followed by a dot and method name to invoke -a static method from some other class. -The method may -optionally take a FileObject argument which will be the -settings file itself. This is analogous to the mechanism used for -creating complex *.instance files. For example:

    - -
    -<file name="some-difficult-to-make-instance.settings">
    -    <![CDATA[<?xml version="1.0" encoding="UTF-8"?>
    -<!DOCTYPE settings PUBLIC
    -          "-//NetBeans//DTD Session settings 1.0//EN"
    -          "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
    -<settings version="1.0">
    -    <module name="my.module/1" spec="1.0"/>
    -    <instanceof class="javax.swing.Action"/>
    -    <instanceof class="my.module.MyAction"/>
    -    <instance class="my.module.MyAction" method="createAction"/>
    -</settings>
    -]]>
    -    <attr name="param" stringvalue="someval"/>
    -</file>
    -
    - -
    -package my.module;
    -public class MyAction extends javax.swing.AbstractAction {
    -    public MyAction(String name) {/* ... */}
    -    // ...
    -    public static MyAction createAction(FileObject fo) {
    -        return new MyAction((String)fo.getAttribute("param"));
    -    }
    -}
    -
    - -

    This will result in an instance of MyAction being -created with name someval.

    - -
  3. You may use the <serialdata> element. Its -textual contents are a hexadecimal dump (whitespace ignored) of the -raw serialized bytes of an object to serve as the instance. Naturally -this is the least preferred mechanism as it is not human-readable.

    - -
- -

(You can configure your persistance style by using -@ConvertAsProperties or -@ConvertAsJavaBean -instead).

- -

A client can find the current setting in a couple of ways: - -

    - -
  • In the common case of SystemOption, you may simply -call - -SharedClassObject.findObject(Class, true) - -which will either provide a previously initialized singleton, or find -the setting in lookup if possible and read any customized state before -returning it. You may then use property change listeners as needed to -listen for changes. - -
  • Just ask the system lookup for the settings class (or a relevant -superclass). This can be used to retrieve non-singleton settings; use -the lookup result to track changes in the list of setting instances, -and some ad-hoc method to track runtime changes in individual -instances. - -
- -

How does the customization of setting instances work? After finding a -setting instance via this DTD, the system will automatically look for -a beans-style event set of type PropertyChangeListener, -and add its own listener. If the bean changes state (either -programmatically or as a result of user manipulation), the property -change will cause the new state to be written out to the original XML -file, keeping the same name. (Normally this would mean the XML would -be written to disk in the user directory.)

- -

(Historically the state of an object is simply - serialized into -the XML file using <serialdata>, meaning the class -must be Serializable, but you can choose different form -of persistance by using -@ConvertAsProperties or -@ConvertAsJavaBean -instead).

- -

Conversely, changes to the setting file on disk should trigger a -reload of the state and modification of the in-memory bean (or -creation of a new instance cookie with a new bean).

- -

UI for Services

- -

There are several things you can do to not only have services and -lookup function programmatically but also look good and behave nicely -within the user's view of configuration options and settings.

- -

Service Templates

- -

For many kinds of services, especially ServiceTypes -but also others, it is necessary to permit the user to create new -instances of the service. Generally two criteria should be met for -such services:

- -
    - -
  1. The service is not a singleton, so it is meaningful to have more -than one instance. - -
  2. The service has some user-configurable properties, so it is useful -to have more than one instance. - -
- -

Creation of new service instances may be supported simply by -producing a template residing beneath -Templates/Services/. If the service normally resides in a -subfolder of services, for example Services/Executor/, -then the template should correspondingly be placed in -Templates/Services/Executor/.

- -
- -

The template should work like regular source code templates do: a -file giving the initial structure of the service (typically a -*.settings file), with the file attribute -template set to true, and optionally a -templateWizardDescription and -templateWizardURL. For example:

- -
-<folder name="Templates">
-    <folder name="Services">
-        <folder name="Executor">
-            <file name="my-module-executor.settings" url="executor.settings">
-                <attr name="template" boolvalue="true"/>
-                <!-- SystemFileSystem.localizedName and SystemFileSystem.icon as usual -->
-            </file>
-        </folder>
-    </folder>
-</folder>
-
- -

If the user selects New From Template on the -corresponding options folder, the template will be available.

- -
- - - -

Services display area and mirroring

- -

In addition to providing services, it is desirable to display them -to the user as well. This is done, as is customary in other aspects of -NetBeans configuration, by displaying customized variants of the data -nodes coming from the system filesystem. The root folder for -displaying options is called UI/Services/. Its subfolders -govern the display of the options available in the system.

- -

As a rule, it is undesirable to place any actual settings in this -folder (nor would they be recognized by the default lookup anyway). -That is because the organization of this folder is driven by UI needs, -without regards to API maintenance or compatibility of persisted user -settings. So this folder solely mirrors configuration -available elsewhere. You may freely reorganize the mirror according to -current UI needs: existing modules plugging into services areas will -continue to work unmodified, and existing user customizations stored -to disk will continue to apply, since both of these act on the -original files (which should not be moved frivolously).

- -
- -

While technically you could place anything you wish in the UI -folder, in practice a few types of things are used:

- -
    - -
  • Symbolic links to settings files displayed elsewhere. In -NetBeans' old-style options, these will appear as the real setting. For example:

    - -
    -<folder name="UI">
    -    <folder name="Services">
    -        <folder name="Editing">
    -            <file name="my-module-config.shadow">
    -                <attr name="originalFile" stringvalue="Services/my-module-Config.settings"/>
    -                <attr name="originalFileSystem" stringvalue="SystemFileSystem"/>               
    -            </file>
    -        </folder>
    -    </folder>
    -</folder>
    -
    - - -

    The attribute "originalFileSystem" can be omitted. In this case the search for the -linked file will be done on the Filesystem on which the link resides, which -is wanted for the usages on SystemFileSystem. The link file should have zero length.
    -Note that any localized display name -and icon should be set on the original settings file; they will be -picked up automatically by the shadow.

    - -The older style of linking using the CDATA section is still supported: - -
    -<folder name="UI">
    -    <folder name="Services">
    -        <folder name="Editing">
    -            <file name="my-module-config.shadow">                
    -                <![CDATA[Services/my-module-Config.settings
    -SystemFileSystem
    -]]>
    -            </file>
    -        </folder>
    -    </folder>
    -</folder>
    -
    - -

    Here the shadow file consists of two lines, the first being the -path to the real settings, the second always being -SystemFileSystem. - -

  • Links to other kinds of files, such as folders, whether part of -the services lookup area or not. For example:

    - -
    -<folder name="UI">
    -    <folder name="Services">
    -        <folder name="IDEConfiguration">
    -            <folder name="LookAndFeel">
    -                <file name="my-module-stuff.shadow">
    -                    <attr name="originalFile" stringvalue="Stuff"/>
    -                </file>
    -            </folder>
    -        </folder>
    -    </folder>
    -</folder>
    -<folder name="Stuff">
    -    <attr name="SystemFileSystem.localizingBundle" stringvalue="my.module.Bundle"/>
    -    <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/my/module/stuff.gif"/>
    -    <!-- perhaps some files to display here, perhaps not -->
    -</folder>
    -
    - -

    This defines a folder Stuff in the system filesystem -which may be used for some kind of special configuration, and displays -it in options.

    - -
  • Specialized nodes. In some cases you do not wish to display a -particular folder but want to have complete control over the literal -display of the option. In such a case you need only include a -*.instance file with an instance of the node (or its -handle, if you prefer), as the node delegate of this object will be (a -clone of) the node you provide. For example:

    - -
    -<folder name="UI">
    -    <folder name="Services">
    -        <folder name="Building">
    -            <!-- Some subclass of org.openide.nodes.Node: -->
    -            <file name="my-module-ConfigurationNode.instance"/>
    -        </folder>
    -    </folder>
    -</folder>
    -
    - -
- -
- -

No particular substructure of UI/Services/ is defined -by the APIs. For optimal UI integration you may wish to examine the -categories used by other modules and try to reuse an existing category -appropriate to your needs.

- -

In some cases it is necessary to hide a service file, or a -whole folder of services. While you can place files into -Services/ and simply not make any corresponding mirror in -UI/Services/, you may wish to create services or -subfolders inside existing displayable folders (for purposes of -lookup, generally) yet not have them be visible in the UI. In this -case you should mark the file or subfolder with the file attribute -hidden (set to boolean true).

- -

Property editor for services

- -

If you wish to permit the user to select a service as part of the -Property Sheet (from a node property, or as a -PropertyPanel, providing general GUI embeddability), this -is supported. You should use the property editor assigned to -java.lang.Object (not your desired service -interface). Various hints defined in the Explorer API -permit you to control the result.

- -
- -

As an example, here is a node property permitting you to ask the -user to select a value of type my.module.Thing, being -some interface or abstract superclass, where some instances are -registered to lookup, conventionally in the -Services/Things/ folder which the module has provided:

- -
-public abstract class ThingProperty extends PropertySupport.ReadWrite {
-    protected ThingProperty(String name, String displayName, String shortDescription) throws IOException {
-        super(name, Object.class, displayName, shortDescription);
-        setValue("superClass", Thing.class); // NOI18N
-        setValue("nullValue", NbBundle.getMessage(ThingProperty.class, "LBL_no_thing")); // NOI18N
-        DataFolder thingsFolder = DataFolder.create(
-            DataFolder.findFolder(Repository.getDefault().getDefaultFileSystem().getRoot()),
-            "Services/Things" // NOI18N
-        );
-        setValue("node", thingsFolder.getNodeDelegate()); // NOI18N
-    }
-    public final Object getValue() {
-        return getThing();
-    }
-    public final void setValue(Object o) {
-        if (o != null) {
-            Lookup.Template templ = new Lookup.Template(Thing.class, o, null);
-            Iterator it = Lookup.getDefault().lookup(templ).allItems().iterator();
-            if (it.hasNext()) {
-                setThingID(((Lookup.Item)it.next()).getId());
-            } else {
-                // Thing was registered but is not persistable.
-                setThingID(null);
-            }
-        } else {
-            setThingID(null);
-        }
-    }
-    public final boolean supportsDefaultValue() {
-        return true;
-    }
-    public final void restoreDefaultValue() {
-        setValue(null);
-    }
-    // May be used by code wishing to get the actual Thing (or null):
-    public final Thing getThing() {
-        String id = getThingID();
-        if (id != null) {
-            Lookup.Template templ = new Lookup.Template(Thing.class, null, id);
-            Iterator it = Lookup.getDefault().lookup(templ).allInstances().iterator();
-            if (it.hasNext()) {
-                return (Thing)it.next();
-            } else {
-                // Invalid ID.
-                return null;
-            }
-        } else {
-            return null;
-        }
-    }
-    // Subclasses implement to actually read/write Thing persistent IDs (or null):
-    protected abstract String getThingID();
-    protected abstract void setThingID(String id);
-}
-
- -

A property extending this class would in the current UI display a -pull-down list of all Thing implementations available in -lookup; the custom property editor dialog would display the -Things folder with anything contained inside it for the -user to select from, provided it in fact had an instance assignable to -Thing. The special null value is explicitly permitted -here and would be displayed with the label given in the bundle.

- -
- - -
@FOOTER@ - - diff -r b3ae88304dd0 -r a2947558c966 openide.util/test/unit/src/org/openide/util/LookupUsesRequestProcessorTest.java --- a/openide.util/test/unit/src/org/openide/util/LookupUsesRequestProcessorTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - * - * Contributor(s): - * - * Portions Copyrighted 2009 Sun Microsystems, Inc. - */ - -package org.openide.util; - -import java.io.IOException; -import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import org.netbeans.junit.NbTestCase; -import org.netbeans.junit.RandomlyFails; -import org.openide.util.lookup.Lookups; - -/** - * - * @author Jaroslav Tulach - */ -public class LookupUsesRequestProcessorTest extends NbTestCase -implements LookupListener { - int cnt; - - public LookupUsesRequestProcessorTest(String s) { - super(s); - } - - @RandomlyFails // NB-Core-Build #3891: Count is now 1 expected:<1> but was:<0> - public void testMetaInfLookupDeliversEventsInRPThread() throws InterruptedException { - ClassLoader l = new MyCL(); - Lookup lkp = Lookups.metaInfServices(l); - Lookup.Result result = lkp.lookupResult(Runnable.class); - result.addLookupListener(this); - - assertNull("No runnables found", lkp.lookup(Runnable.class)); - assertNotNull("Thread found", lkp.lookup(Thread.class)); - assertNotNull("Now runnable found", lkp.lookup(Runnable.class)); - assertEquals("Count is now 1", 1, cnt); - } - - public void resultChanged(LookupEvent unused) { - if (Thread.currentThread().getName().contains("request-processor")) { - cnt++; - return; - } - fail("Changes shall be delivered in request processor thread. But was: " + Thread.currentThread().getName()); - } - - - private static final class MyCL extends ClassLoader { - - @Override - protected Enumeration findResources(String path) throws IOException { - if (path.equals("META-INF/services/java.lang.Thread")) { - return Collections.enumeration( - Collections.singleton( - LookupUsesRequestProcessorTest.class.getResource(LookupUsesRequestProcessorTest.class.getSimpleName() + ".resource") - ) - ); - } - return super.findResources(path); - } - - } -} diff -r b3ae88304dd0 -r a2947558c966 openide.util/test/unit/src/org/openide/util/UtilitiesTest.java --- a/openide.util/test/unit/src/org/openide/util/UtilitiesTest.java Wed Jan 27 17:46:23 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,660 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ - -package org.openide.util; - -import java.awt.Button; -import java.awt.Canvas; -import java.awt.Checkbox; -import java.awt.CheckboxMenuItem; -import java.awt.Choice; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Desktop; -import java.awt.Dialog; -import java.awt.Dialog.ModalExclusionType; -import java.awt.Dialog.ModalityType; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.FileDialog; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Frame; -import java.awt.HeadlessException; -import java.awt.Image; -import java.awt.Label; -import java.awt.Menu; -import java.awt.MenuBar; -import java.awt.MenuItem; -import java.awt.Panel; -import java.awt.Point; -import java.awt.PopupMenu; -import java.awt.PrintJob; -import java.awt.ScrollPane; -import java.awt.Scrollbar; -import java.awt.TextArea; -import java.awt.TextField; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.datatransfer.Clipboard; -import java.awt.dnd.DragGestureEvent; -import java.awt.dnd.InvalidDnDOperationException; -import java.awt.dnd.peer.DragSourceContextPeer; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.im.InputMethodHighlight; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.ImageObserver; -import java.awt.image.ImageProducer; -import java.awt.peer.ButtonPeer; -import java.awt.peer.CanvasPeer; -import java.awt.peer.CheckboxMenuItemPeer; -import java.awt.peer.CheckboxPeer; -import java.awt.peer.ChoicePeer; -import java.awt.peer.DesktopPeer; -import java.awt.peer.DialogPeer; -import java.awt.peer.FileDialogPeer; -import java.awt.peer.FontPeer; -import java.awt.peer.FramePeer; -import java.awt.peer.LabelPeer; -import java.awt.peer.ListPeer; -import java.awt.peer.MenuBarPeer; -import java.awt.peer.MenuItemPeer; -import java.awt.peer.MenuPeer; -import java.awt.peer.PanelPeer; -import java.awt.peer.PopupMenuPeer; -import java.awt.peer.ScrollPanePeer; -import java.awt.peer.ScrollbarPeer; -import java.awt.peer.TextAreaPeer; -import java.awt.peer.TextFieldPeer; -import java.awt.peer.WindowPeer; -import java.io.File; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.Semaphore; -import javax.swing.AbstractAction; -import javax.swing.AbstractButton; -import javax.swing.Action; -import javax.swing.JButton; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.JSeparator; -import javax.swing.KeyStroke; -import junit.framework.Assert; -import org.netbeans.junit.MockServices; -import org.netbeans.junit.NbTestCase; -import org.openide.util.actions.Presenter; -import org.openide.util.lookup.AbstractLookup; -import org.openide.util.lookup.InstanceContent; -import org.openide.util.lookup.Lookups; -import org.openide.util.lookup.implspi.NamedServicesProvider; -import org.openide.util.actions.ActionPresenterProvider; -import org.openide.util.test.MockLookup; - -/** - * @author Jiri Rechtacek et al. - */ -public class UtilitiesTest extends NbTestCase { - - public UtilitiesTest (String testName) { - super (testName); - } - - private String originalOsName; - - @Override - protected void setUp() throws Exception { - super.setUp(); - Utilities.resetOperatingSystem (); - originalOsName = System.getProperty("os.name"); - } - - @Override - protected void tearDown() throws Exception { - System.setProperty("os.name", originalOsName); - super.tearDown(); - } - - public void testGetOperatingSystemWinNT () { - System.setProperty ("os.name", "Windows NT"); - //assertEquals ("System.getProperty (os.name) returns Windows NT", "Windows NT", System.getProperty ("os.name")); - assertEquals ("Windows NT recognized as OS_WINNT", Utilities.OS_WINNT, Utilities.getOperatingSystem ()); - } - - public void testGetOperatingSystemFreebsd () { - System.setProperty ("os.name", "FreeBSD"); - assertEquals ("System.getProperty (os.name) returns FreeBSD", "FreeBSD", System.getProperty ("os.name")); - assertEquals ("System.getProperty (os.name) returns freebsd", "freebsd", System.getProperty ("os.name").toLowerCase (Locale.US)); - assertEquals ("FreeBSD recognized as OS_FREEBSD", Utilities.OS_FREEBSD, Utilities.getOperatingSystem ()); - } - - public void testGetOperatingSystemFreeBSDLowerCase () { - System.setProperty ("os.name", "freebsd"); - assertEquals ("FreeBSD recognized as OS_FREEBSD", Utilities.OS_FREEBSD, Utilities.getOperatingSystem ()); - } - - public void testGetUnknownOperatingSystem () { - System.setProperty ("os.name", "Unknown"); - if (File.pathSeparatorChar == ':') { - assertTrue("Unknown os.name should be recognized as Unix.", Utilities.isUnix()); - } else { - assertEquals("Unknown os.name not OS_OTHER.", Utilities.OS_OTHER, Utilities.getOperatingSystem()); - } - } - - public void testWhatIsWinXP () { - System.setProperty ("os.name", "Windows XP"); - assertTrue ("Windows XP isWindows", Utilities.isWindows ()); - assertFalse ("Windows XP not isUnix", Utilities.isUnix ()); - } - - public void testWhatIsLinux () { - System.setProperty ("os.name", "Linux"); - assertFalse ("Linux not isWindows", Utilities.isWindows ()); - assertTrue ("Linux isUnix", Utilities.isUnix ()); - } - - public void testWhatIsMac () { - System.setProperty ("os.name", "Mac OS X"); - assertFalse ("Mac not isWindows", Utilities.isWindows ()); - assertTrue ("Mac isMac", Utilities.isMac ()); - } - - public void testWhatIsFreeBSD () { - System.setProperty ("os.name", "freebsd"); - assertFalse ("freebsd is not isWindows", Utilities.isWindows ()); - assertTrue ("freebsd isUnix", Utilities.isUnix ()); - } - - public void testCustomCursorNotSupported() { - NoCustomCursorToolkit toolkit = new NoCustomCursorToolkit(); - CustomToolkitComponent c = new CustomToolkitComponent( toolkit ); - Image icon = new BufferedImage( 16, 16, BufferedImage.TYPE_BYTE_BINARY ); - Cursor cursor = Utilities.createCustomCursor( c, icon, "junittest" ); - assertTrue( "fallback to wait cursor", Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ).equals( cursor ) ); - assertTrue( "getBestCursorSize was called", toolkit.getBestCursorSizeCalled ); - assertFalse( "no custom cursor created", toolkit.createCustomCursorCalled ); - } - - public void testKeyConversions() throws Exception { - assertEquals("CS-F1", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_F1, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK))); - assertEquals(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.ALT_MASK), Utilities.stringToKey("A-EQUALS")); - // XXX stringToKeys, Mac support, various more exotic conditions... - } - - public void testKeyConversionsPortable() throws Exception { - if (Utilities.isMac()) { - assertEquals("SD-D", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK | KeyEvent.META_MASK), true)); - assertEquals("SO-D", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK | KeyEvent.CTRL_MASK), true)); - assertEquals("A-RIGHT", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_MASK), true)); - } else { - assertEquals("SD-D", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK | KeyEvent.CTRL_MASK), true)); - assertEquals("O-RIGHT", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_MASK), true)); - } - } - - public void testSpecialKeyworksOn14AsWell15 () throws Exception { - KeyStroke ks = Utilities.stringToKey("C-CONTEXT_MENU"); - assertNotNull ("key stroke created", ks); - KeyStroke alt = KeyStroke.getKeyStroke(ks.getKeyCode(), KeyEvent.ALT_MASK); - String s = Utilities.keyToString(alt); - assertEquals ("Correctly converted", "A-CONTEXT_MENU", s); - } - - public void testSpecialKeyworksOn14AsWell15WithoutModificators () throws Exception { - KeyStroke ks = Utilities.stringToKey("CONTEXT_MENU"); - assertNotNull ("key stroke created", ks); - String s = Utilities.keyToString(ks); - assertEquals ("Correctly converted", "CONTEXT_MENU", s); - } - - public void testActionsToPopupWithLookup() throws Exception { - MockServices.setServices(AwtBridgeImpl.class); - final List commands = new ArrayList(); - class BasicAction extends AbstractAction { - public BasicAction(String name) { - super(name); - } - public void actionPerformed(ActionEvent e) { - commands.add((String) getValue(Action.NAME)); - } - } - class ContextAction extends BasicAction implements ContextAwareAction { - public ContextAction(String name) { - super(name); - } - public Action createContextAwareInstance(final Lookup actionContext) { - return new AbstractAction() { - public void actionPerformed(ActionEvent e) { - commands.add(ContextAction.this.getValue(Action.NAME) + "/" + actionContext.lookup(String.class)); - } - }; - } - } - class SpecialMenuAction extends BasicAction implements Presenter.Popup { - public SpecialMenuAction(String name) { - super(name); - } - public JMenuItem getPopupPresenter() { - JMenuItem item = new JMenuItem((String) getValue(Action.NAME)); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - commands.add(((String) getValue(Action.NAME)) + "/popup"); - } - }); - return item; - } - } - Action duplicated = new BasicAction("duplicated"); - Action[] actions = new Action[] { - null, - null, - new BasicAction("first"), - duplicated, - null, - null, - new BasicAction("second"), - duplicated, - null, - new ContextAction("context"), - new SpecialMenuAction("presenter"), - null, - new BasicAction("top"), - new BasicAction("HIDDEN"), - null, - new BasicAction("bottom"), - null, - null, - }; - Lookup l = Lookups.singleton("thing"); - JPopupMenu menu = Utilities.actionsToPopup(actions, l); - for (Component element : menu.getComponents()) { // including separators - if (element instanceof AbstractButton) { - ((AbstractButton) element).doClick(); - } else { - commands.add(null); - } - } - String[] expectedCommands = new String[] { - // leading separators must be stripped - "first", - "duplicated", - null, // adjacent separators must be collapsed - "second", - // do not add the same action twice - null, - "context/thing", // ContextAwareAction was checked for - "presenter/popup", // Presenter.Popup was checked for - null, - "top", - // exclude HIDDEN because of AwtBridgeImpl.convertComponents - // separator should however remain - null, - "bottom", - // trailing separators must be stripped - }; - assertEquals("correct generated menu", Arrays.asList(expectedCommands), commands); - } - - public void testActionsForPath() throws Exception { - MockLookup.setInstances(new NamedServicesProviderImpl()); - // #156829: ensure that no tree lock is acquired. - final Semaphore ready = new Semaphore(0); - final Semaphore done = new Semaphore(0); - EventQueue.invokeLater(new Runnable() { - public void run() { - synchronized (new JSeparator().getTreeLock()) { - ready.release(); - try { - done.acquire(); - } catch (InterruptedException ex) { - Exceptions.printStackTrace(ex); - } - } - } - }); - ready.acquire(); - try { - assertEquals("[hello, null, there]", Utilities.actionsForPath("stuff").toString()); - } finally { - done.release(); - } - } - - private static class CustomToolkitComponent extends Component { - private Toolkit customToolkit; - - public CustomToolkitComponent( Toolkit t ) { - this.customToolkit = t; - } - - public Toolkit getToolkit() { - return customToolkit; - } - } - - private static class NoCustomCursorToolkit extends Toolkit { - public FontMetrics getFontMetrics(Font font) { - return Toolkit.getDefaultToolkit().getFontMetrics( font ); - } - - protected TextFieldPeer createTextField(TextField target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected ListPeer createList(java.awt.List target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected MenuBarPeer createMenuBar(MenuBar target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { - return Toolkit.getDefaultToolkit().createDragSourceContextPeer( dge ); - } - - public boolean prepareImage(Image image, int width, int height, ImageObserver observer) { - return Toolkit.getDefaultToolkit().prepareImage( image, width, height, observer ); - } - - public int checkImage(Image image, int width, int height, ImageObserver observer) { - return Toolkit.getDefaultToolkit().checkImage( image, width, height, observer ); - } - - protected PopupMenuPeer createPopupMenu(PopupMenu target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - public PrintJob getPrintJob(Frame frame, String jobtitle, Properties props) { - return Toolkit.getDefaultToolkit().getPrintJob( frame, jobtitle, props ); - } - - protected ButtonPeer createButton(Button target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - public Image createImage(ImageProducer producer) { - return Toolkit.getDefaultToolkit().createImage( producer ); - } - - protected CanvasPeer createCanvas(Canvas target) { - throw new IllegalStateException("Method not implemented"); - } - - protected ScrollbarPeer createScrollbar(Scrollbar target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - public Image getImage(String filename) { - return Toolkit.getDefaultToolkit().getImage( filename ); - } - - public Image createImage(String filename) { - return Toolkit.getDefaultToolkit().createImage( filename ); - } - - protected MenuPeer createMenu(Menu target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected MenuItemPeer createMenuItem(MenuItem target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - public Map mapInputMethodHighlight(InputMethodHighlight highlight) throws HeadlessException { - return Toolkit.getDefaultToolkit().mapInputMethodHighlight( highlight ); - } - - public Image createImage(byte[] imagedata, int imageoffset, int imagelength) { - return Toolkit.getDefaultToolkit().createImage( imagedata, imageoffset, imagelength ); - } - - public Image getImage(URL url) { - return Toolkit.getDefaultToolkit().getImage( url ); - } - - protected CheckboxPeer createCheckbox(Checkbox target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - public Image createImage(URL url) { - return Toolkit.getDefaultToolkit().createImage( url ); - } - - protected TextAreaPeer createTextArea(TextArea target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected FileDialogPeer createFileDialog(FileDialog target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected ScrollPanePeer createScrollPane(ScrollPane target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected DialogPeer createDialog(Dialog target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected PanelPeer createPanel(Panel target) { - throw new IllegalStateException("Method not implemented"); - } - - protected ChoicePeer createChoice(Choice target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected FramePeer createFrame(Frame target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected LabelPeer createLabel(Label target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected FontPeer getFontPeer(String name, int style) { - throw new IllegalStateException("Method not implemented"); - } - - protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - protected WindowPeer createWindow(Window target) throws HeadlessException { - throw new IllegalStateException("Method not implemented"); - } - - public void sync() { - Toolkit.getDefaultToolkit().sync(); - } - - protected EventQueue getSystemEventQueueImpl() { - return Toolkit.getDefaultToolkit().getSystemEventQueue(); - } - - public Clipboard getSystemClipboard() throws HeadlessException { - return Toolkit.getDefaultToolkit().getSystemClipboard(); - } - - public Dimension getScreenSize() throws HeadlessException { - return Toolkit.getDefaultToolkit().getScreenSize(); - } - - public int getScreenResolution() throws HeadlessException { - return Toolkit.getDefaultToolkit().getScreenResolution(); - } - - public String[] getFontList() { - return Toolkit.getDefaultToolkit().getFontList(); - } - - public ColorModel getColorModel() throws HeadlessException { - return Toolkit.getDefaultToolkit().getColorModel(); - } - - public void beep() { - Toolkit.getDefaultToolkit().beep(); - } - - boolean createCustomCursorCalled = false; - public Cursor createCustomCursor(Image cursor, Point hotSpot, String name) throws IndexOutOfBoundsException, HeadlessException { - - createCustomCursorCalled = true; - return Toolkit.getDefaultToolkit().createCustomCursor(cursor, hotSpot, name); - } - - boolean getBestCursorSizeCalled = false; - public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) throws HeadlessException { - getBestCursorSizeCalled = true; - return new Dimension(0,0); - } - - @Override - protected DesktopPeer createDesktopPeer(Desktop target) throws HeadlessException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean isModalityTypeSupported(ModalityType modalityType) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean isModalExclusionTypeSupported(ModalExclusionType modalExclusionType) { - throw new UnsupportedOperationException("Not supported yet."); - } - } - - public static final class AwtBridgeImpl extends ActionPresenterProvider { - public JPopupMenu createEmptyPopup() { - return new JPopupMenu(); - } - public JMenuItem createMenuPresenter(Action action) { - return new JMenuItem(action); - } - public JMenuItem createPopupPresenter(Action action) { - return new JMenuItem(action); - } - public Component createToolbarPresenter(Action action) { - return new JButton(action); - } - public Component[] convertComponents(Component comp) { - if (comp instanceof JMenuItem && "HIDDEN".equals(((JMenuItem) comp).getText())) { - return new Component[0]; - } else { - return new Component[] {comp}; - } - } - } - - private class NamedServicesProviderImpl extends NamedServicesProvider { - - public NamedServicesProviderImpl() { - } - - public Lookup create(String path) { - if (!path.equals("stuff/")) { - return Lookup.EMPTY; - } - InstanceContent content = new InstanceContent(); - InstanceContent.Convertor actionConvertor = new InstanceContent.Convertor() { - - public Action convert(final String obj) { - return new AbstractAction() { - - public void actionPerformed(ActionEvent e) { - } - - @Override - public String toString() { - return obj; - } - }; - } - - public Class type(String obj) { - return AbstractAction.class; - } - - public String id(String obj) { - return obj; - } - - public String displayName(String obj) { - return id(obj); - } - }; - InstanceContent.Convertor separatorConvertor = new InstanceContent.Convertor() { - - public JSeparator convert(Boolean obj) { - Assert.fail("should not be creating the JSeparator yet"); - return new JSeparator(); - } - - public Class type(Boolean obj) { - return JSeparator.class; - } - - public String id(Boolean obj) { - return "sep"; - } - - public String displayName(Boolean obj) { - return id(obj); - } - }; - content.add("hello", actionConvertor); - content.add(true, separatorConvertor); - content.add("there", actionConvertor); - return new AbstractLookup(content); - } - } - -} diff -r b3ae88304dd0 -r a2947558c966 pom.xml --- a/pom.xml Wed Jan 27 17:46:23 2010 -0500 +++ b/pom.xml Wed Feb 03 00:04:30 2010 +0100 @@ -32,7 +32,6 @@ http://apidesign.org - lookup spring.lookup anagramdemo diff -r b3ae88304dd0 -r a2947558c966 spring.lookup/pom.xml --- a/spring.lookup/pom.xml Wed Jan 27 17:46:23 2010 -0500 +++ b/spring.lookup/pom.xml Wed Feb 03 00:04:30 2010 +0100 @@ -50,20 +50,15 @@ - org.apidesign - lookup - 7.22.0 - - org.netbeans.api org-netbeans-modules-nbjunit - RELEASE65 + RELEASE68 test org.netbeans.modules org-netbeans-insane - RELEASE65 + RELEASE68 test @@ -81,6 +76,11 @@ spring-context 2.5.6 + + org.netbeans.api + org-openide-util + RELEASE68 + Provides mapping between Lookup library, so it is directly usable with Spring Framework's